User registration server-side wizard with Devise authentication - ruby-on-rails

All the authentication plugins I've seen are implementing one-page user registration - user enters all his fields and then they are submitted at once. So the Devise authentication does.
Bun now we have requirements to do multi-page registration wizard.
Implementing it with JQuery with posting on last wizard's page would be easy if we haven't a requirement that user should be created on the very first page and then, on other pages should provide more and more information with saving after each page submit.
How would you suggest to implement this in a project which is using Devise authentication? How does this correspond to user's activation process (I mean sending account confirmation e-mails)?

Multistep forms have nothing to do with any authentication plugin you use. It depends on how you integrate it.
The complexity becomes much harder since you have multiple requests from page to page.
- How do I keep the data?
- When do I create the database model?
- Should I use hidden fields an pass the values from page to page or should I stick them in the session?
Those are all questions that pop up at some point and you should try sorting them out beforehand.
Creating the model on the initial request has the big disadvantage that you could end up with a bogus database entry, which obviously you don't want.
You could create a temporary model for instance, that you use for collecting the userdata and at the end you create your real usermodel, going through devise, based on this tmp model and delete it when you're done...
Ryan Bates talks in one of his screencasts about multistep forms. http://railscasts.com/episodes/217-multistep-forms
might be interesting for you to watch.

Related

Customizing Devise vs Creating own authentication for multi page registration

I'm creating a ruby on rails project (soon to be a mobile app). I wanted to utilize the Devise gem for authentication, but I am struggling with the customization of Devise. I wanted to implement a multi-page registration/sign up process. The standard devise gem automatically provides a form that includes email and password. For my project, I wanted the users to add in their name on one page, then their email on the next page, and then their password on the page after, etc. Please see the attached jpg picture for a super basic example.
So far, I separated the registration controller from the devise package. The registration controller comes with the new.html.erb and the edit.html.erb files. I want to take the standard form in the new.html.erb file and split that into multiple html.erb files. The controller would obviously need to be connected to these multiple files. As I was working on it, I realized how complicated it is. I'm wondering is it better to create my own authentication process instead of devise, or is it better to stick with devise?
I really want to make it work with devise, so if you have any suggestions on how to customize the gem to implement the multipage registration that I want, please let me know.
This can be done by modifying the views and the devise controller to accept multi-part registration, but it is cumbersome: I would counsel you to avoid it. Rather, another option would be to: (i) use devise to handle the email and username in one form and then (ii) handle the multi-part registration using the wicked gem - whose sole purpose for existence is to handle multi part registration problems.

Rails devise having multiple fields in sign up form

I am designing an app where the user signs up using the devise gem (email + password).
Then, i have a form to capture other personal information and since i am creating something like a social dating app i need to match users using this data.
My question is based on a design concern because I created a Model with devise and then I am using a different database to hold the data coming from the form after sign up.
Do you suggest having a mutual column between Model from Devise and the new Database, maybe Id or email since they are both unique
OR
Ask for this information in the sign up for by overwrite devise using a custom controller?
What is considered best practise? Keep in mind that I have two types of users, it is not males/females, it is something else, therefore Maybe two databases are helpful having another one from devise so in total 3.
I think the best way to go would be to keep the Devise model for the users and then create another model (for example "Profile"), where you can store all the more "personal" data for each user.
Then you can either ask for the user to fill that data through a new form, or you can create nested fields in the sign up form where the user can fill some information right away.

Building a user register page

I am trying to setup user registration. I have been recommended not to use scaffold.
So far I have run this command to generate model for all profile information:
rails generate model User name email birthday:date zip_code time_zone sexuality career education religion politics children height does_user_smoke does_user_drink about_me:text career
I want the required sign up information from when a user first visits the website to be name, email, birthday, zip code, and password. I am not sure what the next step is. As far as building the page to have the users sign up. I know I have to edit app/views/users/new.html.erb. When I did the tutorials I ran scaffold which did the work for me, but now I have been told by several people to not user scaffold and just do everything yourself. But I haven't read a tutorial, nor can I find any examples on the internet that will walk me through building a user register page in rails.
So I don't know if I should go back to using scaffold or hopefully someone can point me in the right direction with starting on the user register page.
Yes, there are tutorials about authentication. I personally like Ryan Bates's screencast authentication from scratch. That tutorial should include everything you need.
As for the scaffolding, I think it really depends on what you're trying to achieve here. All scaffolding does is create the basic CRUD (create, read, update, delete) operations on a model for you, including controller, views and tests. Since you needed those views, for example, you could have used that. And prewritten tests are awesome.
However, in this case I would just go with the screencast and not use scaffolding. Scaffolding is nice for any model that doesn't need anything fancy like authentication, but only the basic CRUD operations.
Try to Analise that do you want views/controllers/models or all.
Since this problem is specific to user registration, so you may only need to have user registration view and user model and the controller that performs the registration logic.
Scaffolding is useful to automate your task specifically if you want a complete MVC functionality.
For ex:
If you use the controller generator, this will generate the controller action and the view.
rails g controller controllername new create
This will create new and create actions with their relevant views.

Devise - limit registrations by using the password reset mechanism?

I'm looking for a way to allow private registrations, or registrations that require manual approval. The latter can be done using the strategy as described here, but I figure the former method might be more convenient if I could somehow take advantage of the password reset module to simplify the process (send an email with a one-time use token but for the purpose of account creation). Has anyone attempted anything like this, or possibly have a better strategy that makes greater use of existing components in devise?
possibly related: Ruby on rails: Devise, want to add invite code?
I have to admit I am not a big fan of using features in a framework that are designed for other uses to accomplish some other goal.
What I usually do when I want a private Sign-Up where you have to be invited to the App is to simply put the user creation/registration inside the Application. After all Devise is just an authentication mechanism ontop of the User model.
So in my current app for example there is a explicit way inside the app for existing users to invite a friend.
The inviting User has a form that creates an entry in the Users table for the new guy with his email address and a field that tells me if the user has finished his registration. I create a little Token that also gets saved to the Database (SecureRandom.hex(8) is a nice way to create such Tokens).
The system shoots the new guy a email telling him where to sign up (with a URL that contains the token), and the sign up is just a form that sets password and additional fields.
All of this is no real magic in Rails, it's all in all 2 controller actions, 2 views and 1 mailer to accomplish it and you are in no way constrained by any API Devise is or is not giving you.
I only had to make sure Devise won't authenticate Users that have not yet redeemed their invitation token but that's it then.
Sure not having to write the sign up view is convenient, but especially when you are dealing with partial information (the inviting User in my case has to fill in some information about the new user already) that gets only complemented by the new user it's quite convenient to just have regular forms where you can do anything with them.
Unless someone writes a Gem that extends Devise to do exactly this, I think I'll stick to this approach.
Turns out there was a third strategy - I could simply lock new accounts (lockable, before_create filter) and provide a manual unlock facility.

what is the omniauth & email-password registration best practice?

What is the best practice for combining Facebook login (let's say I'll use Omniauth gem) and email+password login?
I saw a few blogs, saw the Railscasts, I know everyone is using Devise gem with Omniauth. But I'm looking for some different perspective.
subquestions:
I'm considering creating email+password sign-up from scratch (not using any gem for this, lets keep it fast and light) so do you have any advice for this ? Or if you have particular gem in mind, please let it be fast.
And do you have any other recommendations for Oauth2 gems (alternative to Omniauth) handling authentication to Facebook ?
I'm sorry I'm asking this fundamental questions here, but I didn't found many answers (and most of them I found are based on Devise)
This is how I saw it's done in most examples on the web
basicly when you signup with email+password, you are creating row directly to User model (not touching the Authent. model) and when signing up with Omniauth, than you are creating new authentication that communicates with User model.
And basicly on next login you are doing something like this :
if (user.password == 'xxx')
login
elsif user.authentication.uid == 'xxx'
login
else
'hello signup !'
end
so you are swiching between 2 models, and raping (sorry for the term) the User model witch should hold only user info
The solution, in a way, I think is correct (from my experience and discussions with my colleagues but I'm still not 100% sure this is the right answer)
as you see even the user+password is going trough Authent. model, that means the site user+password is acting as a provider on its own
so to be absolutly correct it should be look like this
scenario 1
signing up with FB: you save FB uid and authKey to authentication table, then create user
scenario 2
signing up with password: you create new row in AppPass table, then you create row in Authentication table (as a access to provider witch is actually your app) and than you create user
Why?
because now when user logs in, is always going trough Authent. model, not making condition between 2 models (the Authent. and the User model)
now can anyone please tell me, ...is this a good approach :D ?
Intridea offers an email & password strategy to enable this:
https://github.com/intridea/omniauth-identity
:-)
Omniauth is great, so you should probably use that for any/all social media logins.
As far as setting up your own authentication this shouldn't be too hard. Ryan Bates has a great screencast on this: Authentication from scratch
Here is a pretty good omniauth article (you will have to adapt it to your own users table though but its still a great resource) Omniauth rails rumble. Please note that I believe the article author uses the term authorization in the wrong context here. Omniauth has nothing to do with authorization, only authentication and this is a subtle but very important difference.
Here's a link to the ruby toolbox page for the most popular authentication gems: http://ruby-toolbox.com/categories/rails_authentication.html. You probably aren't going to find the exact functionality you are looking for right out of the box with any of the solutions.
I don't think that you are correct that having the different authentication methods go to different tables will put too much strain (perhaps a better term) on the models.
It seems to me that if everyone is doing this using devise, there is a reason for it. You could probably get better performance by writing something scaled down yourself, but it's a big time investment. My guess is that the small performance improvement in your application is not going to be worth the time you spend writing something yourself.
If you're working on a current project with many thousands of concurrent users that is having difficulty scaling, please ignore my advice, since I am not familiar with those type of problems.
I kinda dig in to these problematic more deeply an done some research on my own, these are the conclusions.
The problem is that I'm trying to combine my authentication functionality with site login/signup functionality, witch are two different behaviors. At the end of the FB signup with omniauth, you will have in your Authentication table the facebook uid and that is all that it takes to back login to FB for next time (of course you can store other info (like email) ... but logicly they are more users attributes and should go to user table).
note: its ok to store user information from provider, in Authentication table,
but if you want to work with them you should copy these informations to Users table
When you are signing up with email/password solution, you are writing information that define User on your site. (Authentication is just pointing to User) If we wanted to do password signup trough Authentication table, we would have to store the username & password inside authentications table, and this way merging User model and Authentication to one model. It will be much uglier solution, not talking about problem how to store multiple rows to one user. Also you the Authentication or Oauth are synonyms for "accessing your application trough other site" ( watch these oauth2 videos if you cannot imagine it http://www.youtube.com/view_play_list?p … 0139F609), yet with normal login you are accessing the site directly.
The only way around this problem is making a small app, that will handle the email/password or the user/password signup, generate password provider UID, and write those data to Users table, and than with our main applycation we will request trough omniauth to access the miniapp and store the UID in authentications table.
http://eq8scrapbook.heroku.com/equivalents_article/on_omniauth_and_password_login_best_practice

Resources