Open Side Menu Go to the Top
Register
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** ** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD **

08-21-2013 , 06:34 PM
Also, I think having a setup where you can bomb through TDD is vital to making it as efficient/more efficient than other ways of doing things. If you can run tests using a tool that speeds up the load time through your editor, it's really pretty fast.

I see people trying to make specs pass, and slowly going back and forth to their terminal... that's going to be painful.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
08-21-2013 , 07:07 PM
Yeah spring or zeus is necessary for testing with rails.

Also I'm one of those really lazy devs, tabbing in/out to a terminal to run tests is something that would drive me nuts. I actually found a way to automate this before I even read a single tutorial about rails.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
08-21-2013 , 08:18 PM
Quote:
Originally Posted by Nchabazam
What's wrong with EC2?
What will it cost when running PostrgreSQL and fetching articles from it? What would I pay if one of my articles gets a traffic spike from Hacker News, Reddit, or Twitter?
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
08-21-2013 , 08:26 PM
dave digitalocean will be cheaper for you. do be prepared to spend a good chunk of time when doing things yourself though. otoh, you will save a ton of money compared to heroku for similar power.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
08-21-2013 , 10:06 PM
I'm okay spending $20/month for hosting. I'm just not okay spending $60 for a usable database and extra for dynos or anything else. Although there is certainly an argument for saving time, I'm not "worth" enough where this is a factor.

Comparing the prices at $20, it seems like there isn't too much difference, except that Linode offers more CPU and a HD, whereas Digital Ocean makes up for lower CPU by using SDD. DO offers 1 more TB of outgoing transfer (all incoming on both sites are free).

https://www.digitalocean.com/pricing

https://www.linode.com/

A little research suggests that Linode is generally more dependable, noticeably faster, and has better customer service, although I hopefully won't need the CS too often.

For another reason I'm sort of upset at Heroku: they changed the way to deploy Clojure apps with absolutely no notification. I now have to keep track of more boilerplate and use some stupid foreman tool to test the modified version of my site. There was no warning about this at all. Even a command line: "Oh, we see you are deploying a Clojure/Lieningen site. Check our documentation for changes." would be useful. Of course, there was no documentation, just a new article on how to deploy on Clojure that looked exactly like the old one except for a few lines of code.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
08-21-2013 , 10:18 PM
At $20/month digital ocean is giving you 2 gigs of ram instead of 1. That seems like a massive difference to me at that price point, especially since you're on the JVM.

Wouldn't you give the JVM a gig or so and then dedicate the remainder to a DB cache? That combined an SSD is likely going to give you a massive performance boost over what linode gives you.

You should profile your app locally and see how much ram it uses and what the latency is with various amounts of concurrent traffic at a high percentile. That is the only way you'll be able to figure out what the sweet spot will be for hosting.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
08-21-2013 , 10:55 PM
Quote:
Originally Posted by Shoe Lace
At $20/month digital ocean is giving you 2 gigs of ram instead of 1. That seems like a massive difference to me at that price point, especially since you're on the JVM.

Wouldn't you give the JVM a gig or so and then dedicate the remainder to a DB cache? That combined an SSD is likely going to give you a massive performance boost over what linode gives you.

You should profile your app locally and see how much ram it uses and what the latency is with various amounts of concurrent traffic at a high percentile. That is the only way you'll be able to figure out what the sweet spot will be for hosting.
Peeking around, it appears the DO is generally faster, especially with database read/write, so that is definitely a consideration if you are are running an app that is highly DB dependent. Also appears a bit faster with static response. The numbers are all over the place, and honestly there doesn't seem to be any consensus, except that people seem generally afraid to put anything large on DO. I don't have to worry about that, obviously.

I did bump my RAM from 1 to 3 on the VM and that was a massive improvement in all programs, especially Clojure, which barely started on 1G. Mind though that I am not working with compiled .jar files either, but you are probably right that RAM is pretty important. How much this matters with a headless Linux is the question.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
08-21-2013 , 11:06 PM
I wouldn't worry too much about static asset speed because those should be perma cached and if you wanted to get fancy you could use a combination of S3/cloudflare/etc. to serve static files for you if your site ever got popular.

RAM is very important if you can find a use for it. The speed difference between hitting a non-SSD and RAM is silly. You will also want to likely stuff most of your app's goodies in a cache because that could be the difference between having something like a 500ms response time to render a response or 5ms.

I'm not sure how fast templates render in clojure but even with express an uncached medium sized template will take 50-200ms with no DB I/O but a cached one will be served in 1ms.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
08-21-2013 , 11:27 PM
Also relevant to a prior discussion: https://www.digitalocean.com/communi...ache-and-nginx

You convinced me. I'll hand my cash to Digital Ocean. Why take a risk?
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
08-22-2013 , 12:54 AM
Quote:
Originally Posted by Nchabazam

Then again, I did have to refactor an app at my last job where we split some views up into two namespaces. This broke pretty much every link in the app. Having tests there to make sure that every page was working was soooo nice in figuring out if we had missed anything, saved us a ton of time.
Wow. I'm seriously not understanding this. There isn't a gem that keeps your routes in tact?

Quote:
Originally Posted by Shoe Lace
In your creating your own auth I don't think it's a bad idea to have high test coverage. It's something you plan to use in many different projects and maybe even down the line you'll release it as a gem. I think code like this should have a healthy mix of different test levels.
Authorization is pretty dangerous stuff. Should be tested with a machine gun.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
08-22-2013 , 05:15 AM
Quote:
Originally Posted by daveT
Wow. I'm seriously not understanding this. There isn't a gem that keeps your routes in tact?



Authorization is pretty dangerous stuff. Should be tested with a machine gun.
well there's a file called routes.rb where you manage your routes. The problem was a ton of views changed, and many of these needed one of two routes now. So it wasn't an issue of being able to find and replace all.

Also, authorization isn't bad, at least in rails. I wrote my own system which worked quite well. Just depending on the user type, and type of object you're trying to view, you'd either white list an action, or pass in a variable to be evaluated in a block to conditionally authorize that action. Very similar to a gem called cancan. I did write a lot of tests for this, though. The cool thing was I could write them all at a model level. Also, scoping everything to the "current_user" or some top level object will prevent most authorization problems... doubling down with something like I just described above makes it nearly foolproof.

That being said, my last company was a security testing website. Our site was one of the first sites to be tested (by people, not machines). A few guys found the one authorization hole I had overlooked in like 1 hour. Some of these guys have pretty ridiculous scripts to find things really really fast. Basically, I did ModelName.find(params[:id]) instead of scoping it to its parent object, which a hacker wouldn't have access to. I also messed up the authorization model for that one specific event... messing up both things. Fortunately, it was pretty irrelevant if people could fudge the IDs and see the different pages of that specific model, but still amazing how fast it was discovered.


I was talking of authentication, which I'm certainly not rolling my own... just using some prebuilt salting/hashing algorithm which is used by other solutions, without all the extra annoyingness that is provided by it.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
08-22-2013 , 06:24 AM
Quote:
Basically, I did ModelName.find(params[:id]) instead of scoping it to its parent object, which a hacker wouldn't have access to.
i dont understand what this means
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
08-22-2013 , 07:14 AM
Quote:
Originally Posted by gaming_mouse
i dont understand what this means
So if you have a users_controller, and an update action, you're going to want to say something like current_user.update_attributes(params[:user]), instead of @user = User.find(params[:id]), then @user.update_attributes(params[:user]).

This prevents someone from fudging a request to update anyone's account.

Similarly, if you have something like a widget class. And widgets have many gears. If you're updating a gear, you'll be authorizing against that top level widget (most of the time). So you might pass the widget into cancan in the gears controller. This might then pass the widget into a block, and give access to the route if widget.managing_users.include?(current_user).

So that's a nice level of security to lock down the action, but only if you then say @widget = Widget.find(params[:widget_id]), and THEN scope create/update/destroy of gears, to that widget. So @gear = @widget.gears.find(params[:id]), instead of Gear.find(params[:id]) when updating. If I don't scope it to that @widget, someone can create a widget that they own, fudge the params to make the widget_id their widget's id, then just fudge the id of the gear to any they want to update.

Does that make any sense? I'm tired.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
08-22-2013 , 08:03 AM
Quote:
Originally Posted by Grue
I haven't had a job in 10 years before this year so maybe I'm weird but I don't understand how people say things like "touch base" and "bandwidth" and especially "scrum" with a straight face over and over.
What's your velocity?
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
08-22-2013 , 08:13 AM
I'll ping you back on that.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
08-22-2013 , 08:25 AM
Take it as an action item.

I'm having to show up at 8AM for two full days of "crucial conversation" training. Which basically just attempts to teach you how not to be a dick.

It's okay though, it's not like we're all in crunch time on a gigantic project. Corporate bull**** always comes first. Most days I don't start getting any actual development done until 6PM when all the non-programmers go home.

Oh good, our third Hackathon of the year coming up next week.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
08-22-2013 , 08:52 AM
Are your Hackathon's organized "fun" or disguised death marches?
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
08-22-2013 , 09:42 AM
Quote:
Originally Posted by Nchabazam
So if you have a users_controller, and an update action, you're going to want to say something like current_user.update_attributes(params[:user]), instead of @user = User.find(params[:id]), then @user.update_attributes(params[:user]).

This prevents someone from fudging a request to update anyone's account.
ok i see what you mean now, but these both seem wrong to me. after the user logs in, you should have a session of some sort, either on the server or with a secure cookie. any updates to the user account would be done to the user in the valid session. i guess the thing that threw me was your use of "top level", as i don't see any hierarchies involved here. i didnt understand your widget example.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
08-22-2013 , 10:11 AM
I'm assuming current_user is the user retrieved from the authentication layer.

But I definitely agree that any authorization code should only ever be getting the user from the authentication layer and never, ever, from something being passed in.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
08-22-2013 , 10:17 AM
Quote:
Originally Posted by gaming_mouse
ok i see what you mean now, but these both seem wrong to me. after the user logs in, you should have a session of some sort, either on the server or with a secure cookie. any updates to the user account would be done to the user in the valid session. i guess the thing that threw me was your use of "top level", as i don't see any hierarchies involved here. i didnt understand your widget example.
So, current_user just returns the User that correlates to the valid secure session. You can't fudge that.

But in the rails controller, if you permit an object to be altered just via the ID, it can be. That's why you need to explicitly say current_user.update_attributes instead of say User.find(params[:id]).update_attributes

We're arguing basically the same thing, which is that you need to find a way to restrict the updating to the user in the session. Would you do this differently?

The widget example was overly complex. If a User has_many widgets, how do you ensure that the widget that gets updated belongs to the proper user?

You'd have a route like /users/1/widgets/14 But you wouldn't want someone to be able to "put /users/1/widgets/14" if they're user #3.

The code

Code:
  def update
    @widget = Widget.find(params[:id])
    @widget.update_attributes(params[:widget])
  end
would allow anybody to update any widget. So fudging a put request with the ID of any widget would allow you to update it.

the code

Code:
  def update
    @widget = current_user.widgets.find(params[:id])
    @widget.update_attributes(params[:widget])
  end
will only allow you to update the widget if you are logged in and are the owner of the widget.

My example of gears is what happens if you keep going down levels... and want a sort of central way to authorize the object against the current_user. It's unwieldy to have long methods in every controller in a before_filter, and easy to miss a method here or there.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
08-22-2013 , 10:20 AM
Basically, I did the first code example in one controller in one spot in a huge app, and it was exposed within 45 minutes of one guy testing our site with custom scripts. I was the only eyes, and just messed up.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
08-22-2013 , 11:45 AM
Quote:
Originally Posted by jjshabado
I'm assuming current_user is the user retrieved from the authentication layer.
At the most basic level it might be implemented as so:

Code:
def current_user
  @current_user ||= User.find(session[:user_id]) if session[:user_id]
end
Then due to how rails handles model associations you get the ability to access things that current_user might have.

Ex. current_user.tweets or current_user.widgets

Tweet and Widget would be models that are setup such that User "has many" tweets/widgets.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
08-22-2013 , 12:38 PM
@shoe, that's exactly how i'd do it
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
08-22-2013 , 12:44 PM
That's probably how Nchabazam set his current_user up to be too, or something very similar.

It took me a bit to understand how scopes work in relation to the has_many and belongs_to "linkers" in the model. It was so cool once I realized how it works because it lets you write really straight forward code. Scopes in general are amazing too, but that's an entirely different discussion.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote
08-22-2013 , 04:38 PM
Quote:
Originally Posted by kerowo
Are your Hackathon's organized "fun" or disguised death marches?
The latter. No one wants to do a second one. We have some ******ed mandate to do 4 per year. Basically our big boss (5 levels above me) has no idea what we do and likes to hamstring us whenever possible.
** UnhandledExceptionEventHandler :: OFFICIAL LC / CHATTER THREAD ** Quote

      
m