Devise - limit registrations by using the password reset mechanism? - ruby-on-rails

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.

Related

Devise Invitable invitation to accept an event?

I'm trying to wrap my head around Devise_Invitable controller. It looks like it uses a good deal of reflection but it seems that it assumes that any sublcass you create will be a User (of some kind - perhaps an admin, etc).
What I would like to do is leverage the gem to invite users to accept (presumably by overriding the update method) or reject an event (presumably by creating a new "reject" method that works a lot like update).
Is this a reasonable thing to try to do or am I totallybarking up the wrong tree? I feel like I have enough knowledge to get myself into deep trouble but not get myself out at this point in my rails learning.
I think devise_invitable is not designed for your use case; it's intended use is for invitation-only user registration. That is, you only want people to be able to sign up for an account on your site if they've been invited to do so and have a special invitation code. That's an authentication problem (which is why there's a devise addon that's a solution for it) -- you need to use tokens in order to authenticate invited users who have not yet registered a password.
Your problem appears very different, at least superficially -- it sounds like you just want to implement a user interface for already-authenticated users.

Devise: Make user login in two ways

I am trying a weird thing in devise. Here I have got two types of login.
1) Default devise login using username and password.
2) Login with user id and password.
The password (password2) in second step is different from that (password1) in first step.
I want to login through both using same interface, i.e. there will be one login page where you need to enter email or user id and corresponding password (password1 or password2 respectively).
Is it possible to do the same in devise?
Thanks
Paritosh
Allowing multiple user identifiers is discussed on the Devise wiki which I have linked here.
Update: However, as I now understand, you want two separate sets of credentials (userid/pw1, and email/pw2) for some reason.
I think the answer to your question is that "while it's possible to accomplish with Devise, it's far more effort to change Devise than it is to write yourself". If you look at the link, there's actually a fair amount of work needed to make the simpler change of accepting either userid or email for the same password. It gets even more complicated when implementing your requirements.
Unless you really create your own system from scratch, either Devise or Rails' built-in has_secure_password both make several assumptions about the name of the attribute holding the password (i.e. that it's called password). And while there's an assumption that there's a (single) model containing the authentication information and this attribute, I see no reason why you couldn't have two models, perhaps both belonging to a User model, each of which provide the basic functionality of encrypting, storing, and validating the attributes for the method the user has used, but for which all of the other functionality is provided by the parent User record, and its controllers and views. Some simple logic in the User model determines which method is being used and farms off that functionality to the appropriate sub-model.
So yeah, it can be done, and I would suggest has_secure_password will be simpler in your unusual case.
But perhaps it's worth asking: if I am the first person to encounter this situation, perhaps there's an alternative that could meet my requirements that follows some existing convention or approach. For example, is this a "single sign-on" interface that provides authentication for several unrelated services? If so, that might be the thing to search for.
here is a complete tutorial to login with both username and email. you can replace username with user_id or whatever you required.

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

Using Devise for Two Different Models but the same Login Form

I have seen lots of similar questions here but nothing that quite fits my need.
I am a pretty experience rails developer but this new project is my first time using both Rails 3 and Devise (I'm normally on authlogic).
My app has two different models that I want to authenticate via devise.
One, User is just a standard users model
Two, Business is similar to a user, (it has an email address column too) but it has additional info in the database (address, phone number, etc..)
I want to be able to log them both in via the same login form. Then obviously once they are logged in they will be presented with different info depending on what type of Model has logged in.
It may or may not be relevant that I was planning on using OmniAuth to allow Users (though probably not businesses) to sign up/on via facebook.
Thanks!
What's the easiest way to go about doing this?
I think the only way to handle this would be to have your own custom sign in form and controller that determined the type of user and then sign them in correctly. I would recommend an approach like what mark mentioned for simplicity (take a look at something like CanCan to manage roles).
Another potential problem with having multiple user models is that you will have multiple versions of all the devise helper methods. So for current_<resource> and <resource>_signed_in? you would have current_user, current_business_user, user_signed_in? and business_user_signed_in?. Then you would either have to implement your own versions of these methods or you would need to check both versions everywhere you used them.
Can do this in application_controller?
current_user = current_resource_a || current_resource_b

Restful authentication + Facebook connect - User model redesign

I have a site with Restful authentication as authentication plugin. I need to integrate Facebook connect. Facebook does not provide email address for the user (maybe only if user agrees if), and of course does not provide a password.
The main issue is that the User model has a lot of validates_** on those 2 fields (from Restful authentication modules).
Another little issue would be that we already have a lot of code (observers sending emails after user creation, etc etc) that depends on email address.
The solution present in the facebook_connect tutorials was to save the user model bypassing validations, but this is sooo wrong..
How would you redesign the User model to include any/both of the authentication methods(standard and/or facebook_connect)?
Refactor all validations (with :unless => :is_facebook_user), put conditions on observers, etc.
Implement STI on User table (and have StandardUser / FacebookUser, each with custom authentication modules)
User table having polymorphic reference to standard_user and facebook_user
Other ideea
Please notice that the functionality to link a 'standard' account to a 'facebook' account is also required, which complicates things.
References:
http://crazyviraj.blogspot.com/2010/01/test-cases-for-basic-facebook-connect.html
http://blog.yangtheman.com/2009/08/23/how-to-integrate-facebook-connect-with-a-rails-app/comment-page-1/
A good example to get your started here.

Resources