Misc account management pages in a RESTful design in Rails 3 - ruby-on-rails

How do miscellaneous account management pages fit into a RESTful design in Rails 3?
For example, a user registers (create action) and is then forwarded to a registration success page (? action) where they are asked to now verify their email address via a url with a token (emailed to them).
When they click the link in the email, technically they are "updating" their account as part of the verification process right? So I'm thinking that would somehow map to the "update" action but the update action is expecting a PUT request. Is that correct? How do you make that work via the email?
I'm also wondering how forgot password, reset password, etc also fit into a RESTful design? Just trying to wrap my head around this.

Just because you have a result design, doesn't mean you HAVE to restrict yourself to only CRUD verbs that map 1:1 to Get/Post/Put/Delete. That said, if you want to get really RESTful, you can start to think of some of these things in terms of being their own resources. For example user verification:
User signs up, and gets sent a verification email, you already have that all squared away RESTfully it looks like
Verification url looks like: http://app.com/user_verifications/new?token=foobar (GET)
They follow the url and maybe are presented with a "Hello Dan, welcome back! Click here to verify your account" at that point you submit a form to http://app.com/user_verifications to trigger the create action there. Now on the backend, you can perform whatever actions you want, updating the user, setting them to active, or actually creating a "UserVerification" model.
Not a perfect example, but the idea is that the RESTful interface you are providing has an additional resource, in this case "user_verifications" and a user is acting upon it via HTTP methods in order to achieve the user's goals. You can apply similar logic to reset/forgot password either with a "UserSession" type resource or even as specific as a specific "ForgotPassword" resource.

Success page is just create.html.erb file. Usually you are redirecting from create action, but here you can just render success template.
Verifying. If you want to stay REST you should add one more step: GET verify, where is the form with your token present, which will lead to PUT update action. User recieves a link to this page.
But I prefer to use simple GET request here, which will update information without any additional clicks.
The same way you work with restoring passwords and other functionality. You add a page to with form that gets email, then you send a letter with link to a page with form filled with tokens and so on.

Related

Rails 3 - Prevent form_for DOM action change

To generalize this question I asked this morning, and please accept my apologies if this has been asked before and I simply don't know what to search for, but I'm curious how Rails handles the following situation:
Using Devise, I log in a user, with an ID of 2.
I click on a link that has been created to "edit my profile" (which simply would go to the /users/2/edit page).
Using Firebug (or something similar), I modify the form and change the action from action='/users/2' to action='/users/5'.
I change an element on the form, and click submit.
At this point, Rails appears to allow the submission and update user with ID 5 with my changes.
I'm guessing I'm not the first one to ask this question. It seems to me like Rails should handle this "out of the box", but I could be wrong. Does Rails handle this natively and I'm just missing something? Has this been asked before on SO or somewhere else that I'm missing?
A few things:
Don't create a route that accepts a DB id. Instead, make it something like /my_profile.
If an id is passed in the params, ignore it entirely in the controller. Instead lookup the current_user that is logged in and show them their own profile regardless of what profile/user id is passed in.
Finally, and possibly most important, use authorization (what a user is allowed to do) in order to disallow one user from editing another user's profile. Not to be confused with authentication (user logins/logouts).
With this approach it won't matter if the DOM is changed, because the server should never implicitly trust what is passed to it, which is the problem you're facing now. Any web/app server must always confirm that the parameters being passed to it are actually valid in the context of what the current user is allowed to do.
This idea that the server should never trust what's passed to it is a critical idea to apply to every single action in your app, without exception.

Safely passing hidden data from view to controller

In my application users are able to transfer points between them. In my view, I check if user can transfer points from his account, if he can, I render something that allows him to do that. I would not like to check that again in my controller, so I need some mechanism, that will allow me to check if user that I rendered a viewpage for, is the same as the one that is sending a request to my controller.
So basically, I would like to check in my controller, if currently logged user is the same as the one that sent the request - and to do this, I think that I need something that works similar to ViewBag, but not from the controller to a view, but from view to a controller. Is that possible?
A proper way to do this will not be the transfer of such information between user requests. Every request shall be stateless but you trying to embed a state. This is a fair way to shoot yourself in a foot.
If your action requires authentication (you are who you say you are) you should do it using standard classic ASP net way. This will embed a standard authentication token to any further user requests. This way you will know that the user is authenticated or not.
For some actions that require authorisation (user has permissions to perform an action) you must validate that a user has the power to perform such action. This must be done for every request and it is usually a fast operation. No need to optimise things here by reducing your security barrier.
If you search for authentication and authorisation with classic asp, you will get a more fine grained answer on how to do the coding bit.
I wouldn't recommend, but you can still embed hidden information with
<input type="hidden" value="..."/>

Lazy registration with RESTful routing in Rails

I'm stuck figuring out the best practice...
I want to create a "following" system in a way that a user can follow a car (getting email updates when car price changes, etc). The part of implementation that's giving me headaches is when I want to introduce lazy registration by only using email.
Everything needs to work as AJAX requests.
In the interface, there will be a button to trigger the follow action, which will check if the user is registered or not. If a user is logged in, create a new CarSubscription item, otherwise display a form where he could type his email address. Once submitted, the form should create a user with no password (if email exists, ask for the password and log in) and then it should create the relationship item.
The challenge here is to use redirection after submission of the form to the CREATE action of the CarSubscriptionController. Since I can't redirect using POST I can't simulate the CREATE or DESTROY action.
The non-RESTful solution would be to create 2 actions under cars_controller: follow and unfollow and let them do the logic of creating entries and deleting them. That would enable me to just store the request path and use it after the user enters their email and logs in.
How can I achieve what I want using RESTful resources?
After trying to describe my problem here, it seems it's way too complicated and I am indeed very stuck... There are 3 different controllers and possibly 4 requests in this scenario.
Any help would be tremendously appreciated!
Please see my flow chart below:
Not an expert here, I don't know if it's the best solution, but what I have done in similar situation is :
In your controller, respond with javascript instead of redirecting the user
In your javascript file, use $.post(...) to issue a POST to your controller action
Et voilĂ !
You can also use ActiveResource to achieve this, but I actually never tried that solution : http://api.rubyonrails.org/classes/ActiveResource/Base.html#label-Custom+REST+methods
Person.new(:name => 'Ryan').post(:register)
Hope this helps
I had a very similar need and had trouble pulling the various bits of info on how to do this with Devise and Rails together into a working example. Here's a fully working example based on Rails 4, Ruby 2, and Devise 3.0:
https://github.com/mwlang/lazy_registration_demos

RoR: How to authenticate user before POST

I have a form that users can fill out, and hitting the "Create" button will issue a POST request to create a new entry in the database with the form data.
Now, only logged in users should be allowed to create the database entry, but I want all users to be able to fill out the form. Only when clicking "Create" do I want my application to redirect users who are not logged in to the login page. Once logged in, I want to continue processing the POST request and create the database entry, without the user having to enter all the form data again.
What's the best way of handling that? Putting the POST data in the session? But then, after successful login, I want to create the database entry in the original controller/action (so as to not duplicate code), and issuing a POST request from within my application (in the after-successful-login-method) seems strange. Any better ideas?
Thanks!
You're not mentioning how you do your authentication, so i suspect that you do it manually. If you use(and i would strongly recommend you do), a gem like Devise for registration, you just need to add Devise's authentication helper to your controllers, to do that.
To do it manually, every time the user registers, you set a session id variable that is tied to him/her. Then, you just check that to see whether he/she is registered. If not, you just do not allow the action and redirect.

Ruby/RoR and many subprocesses

I am trying to build a free web application using ruby/rails It should be able to send sms through online forms of various mobile operators. (like this one (in russian)).
So, I need to
wait for the user, who wants to send an sms through my website.
establish connection to operator website. Probably, using Mechanize.
retrieve captcha
show captcha to the user
allow user to enter a message and captcha
submit form on operators website (with message, captcha, phone number)
The connection to the operator website should be alive during all this process (otherwise captcha will change). As far as I understand, I need to create a (sub)process each time sms is sent.
Could you please advise what is the best way of handling this in rails\ruby?
I am still rather new to web-development...
Should I use threads? forks? popen? using PTY? some external gem? How should I communicate with my process?
Assuming there's nothing special about the operator's web site, no, you don't need to keep a connection alive during the whole process. Generally speaking, forms on web pages work like this: You visit the URL, your web browser downloads the page with the form on it. In your case, it will also have an <img> tag or similar to show the CAPTCHA. Once your browser has downloaded the page, the connection is severed. After you fill out the form and click on Submit, your web browser opens a new connection to the server and sends the data, and the server sends its response (whatever page is shown after you click Submit).
All your program has to do is emulate this experience. So: 1) Download the page with the form on it. Scrape the form fields (make sure you don't miss any hidden fields--with a CAPTCHA there will probably be some) and the CAPTCHA. 2) Build a page to show your user that includes the CAPTCHA and a form with all the fields they need to fill out. If there were hidden fields in the original form, make sure you include their values (as hidden fields in your form) as well, because when the user submits your form you'll need them. 3) Then, when the user submits your form, send the data, including the hidden values and what the user entered for the CAPTCHA, to the operator. 4) Finally, check if the operator indicated success, and build a page to tell your user.
If you're doing this in Rails, you'll probably have two methods in your controller: One called e.g. 'show' (steps 1 and 2 above) that will scrape the CAPTCHA and other info from the operator's site and show the user your form view, and one called e.g. 'send' (step 3 and 4 above) that the form will submit to, and which will take their data and send it to the operator's web site, collect the response and tell your user if it was successful or not.
Note: You'll want to read the operators' terms of service before you bother with any of this. I'm fairly certain that this kind of thing will be against their TOSes and if they notice your server sending a lot of requests their way they're going to block you pretty quick.
To answer another question of yours, you can use DRb or background_job (aka BJ) to actually accomplish the sending in the background so that after your user submits the captcha they don't have to wait for the response. Or you could wrap this in ajax and have the DRb/BJ process notify you when the sms sending has happened so you can notify the user of success or any problems.
Typically opening threads in Ruby is something to avoid as there are so many great gems that do what we need. Not to say that you shouldn't use threads, just that for the most part it's probably already been done really well.

Resources