Consider an application, which needs to have two different types of user:
User as in standard client
Organization as an entity offering some services through the application
Requirements:
different standard controllers (sessions, registrations etc)
access to different parts of the application of course
This seems like a walk in the park by simply creating two separate models with devise, but I really wouldn't like to duplicate so much functionality for authentication.
I went with a polymorphic association, where Organization and User are different models, both with a 1-1 relation with Entity representing authentication. Entity only has devise attributes (like password etc), while others have type-specific ones. Unfortunately this solution comes with a lot of drawbacks, like having to define custom helpers, warden strategies and devise failure apps.
I'm wondering, is there a concise solution for this type of issue?
Ideally, something like having two devise models delegating everything regarding authentication to a separate entity.
Related
I'm fairly new to rails. I'm having problem on designing the model classes. So this app will be used by 5 different users(Students, Teachers, Head and Coordinator). They each are different users to login into the website and have different functionality (example: Head makes an event. Students register for an event. Coordinator sets who can be head etc). I have created all four models with USERNAME and PASSWORD on each models.I don't have user model right now because the users in this app are these 4 models. Now, while making login page, i'm having hard time on implementing the best way to authenticate the users. For example, If a Head puts its login credentials, the app should identify that user that logged in is Head. What approach will be best to encounter this?
Also, after not figuring out the way to approach this. I was thinking of using devise and CanCanCan gem. But the same promblem comes in even if i use this gems.(i maybe wrong)
Do not create multiple models for different kinds of users. This is almost always not what you want. Instead add a column called role of the type enum which contains all of the kinds of roles you want to add like Sergio pointed out. Your comment about having too many attributes on one model is a non issue compared to the one you are planning to create with 5 user models.
It sounds like you are possible putting too much data on the user model if that is your concern
and have different functionality (example: Head makes an event. Students register for an event.
For this you want a permissions system such as cancancan where you can specify which features of the website each role has access to.
In my Rails application with Devise, I plan to make multiple types of Users (Student, Teacher, and Admin). They have a number of shared attributes such as username, email, password, etc, but with some differences. Students will be able to interact with the content posted by teachers (and probably each other), Teachers can make classes and post content and interact with their students, and Admin will likely have control over most everything (including taking down users, content, etc.)
I am trying to figure out the best way to do this, and preferably with the least headaches as I am still new to Rails. Should I make multiple Devise Models, one for each type of User, or should I make multiple models inherit from User (which I believe is called Single table inheritance?) I am fairly open to trying either one, but I am unsure of which is the best way to go
If you want different authorizations (for example Admin & User) level you can use Pundit.
If you have different roles with the same authorizations (like Student and Teacher in the same context) you should use Inheritance and Concerns, maybe defining a base controller from which all other controllers can derive.
When is it okay to use multiple devise models?
I have 3 types of users - users, vendors and admin. Vendors have a bunch more fields than users so I want to have separate tables for them. Users can sign up and sign in using facebook (vendors cannot). And users and vendors share the same sign-in page/form.
I started with multiple devise models, got confused how to handle a single sign-in page, and then read a lot here about using polymorphic associations and STI instead of discrete models. I'm still confused as to when each approach should be used and what would work better here... i know its a little vague, any advise would be great though, or any good links..
Users also fill out a bunch of extra fields when they sign up - even through facebook. How can I keep track of those fields for an omniauth login? (and should I use devise for this or something like omniauth identity..?)
Thanks for looking at this! I'm a rails newbie setting up authentication first time, really appreciate the help
Depending on the case it is recommended to separate or use a single model. The alternatives:
Use separate models, override the controllers, so firstly you check if the record match in User, and if it doesn't match try with Vendor
Use a single model for storing User and Vendor, use a boolean (a string if it is a polymorphic association) to check the kind of user, and add related models in order to store the additional fields
I think option #1 is easier but bigger, and option #2 is a little bit difficult but shorter.
Also, it would be a good idea to separate the models because User connects to FB and Vendor no, it represents a lot of differences.
In another way, the searches will be faster using option #2, because it will be only 1 query, and the table will be light because it will not contain the specific fields for users and vendors; you also have to consider this in order to make a decision.
For Admin you can follow a similar criteria.
Check this out: https://github.com/mkdynamic/omniauth-facebook
I'm writing a trading system and I have 3 models/roles: Buyers, Sellers and Administrators. I have generated the devise views for each of the models but I would like to use the same sign in, forgotten password pages etc. for them, rather than maintaining 3 sets of views, is there a way of doing this?
The buyer and seller have similar fields (forename, surname, email address, telephone etc.), is it possible to use STI with devise and is it fairly straightforward? At the moment I have 3 separate models with no inheritance.
You can simply have a single User model with a :role attribute and also implement a simple ACL via CanCan or decl_auth (gems). This way they will all sign in etc. via the same session. Devise and CanCan is quite a popular approach and well documented online and in their respective Github wiki's.
For administrators, you can modify your validations to skip on the extra attributes and leave them as blank in the DB.
I have models A,B,C,D, etc. I have my usual controllers/views/helpers for each of these models. These are accessed by a set of content authors in a form based application to populate data into the db. The content authors will also have categories like authors, publishers, super admins etc. Essentially we have built out a mini content management system.
A set of other users (unrelated to the above set) need to access data in some of these models. But the view for those are totally different. I also do not want these users to have the edit screens for the models they are allowed to view. Essentially these guys are end users who use the application as a read only/analytics data store.
How do I accomplish this? Should I create separate controllers and invoke these models for the user website? How do I ensure the website users do not have access to the cms screens? Any pointers, design principles, routing methods, gems for such an application?
How do I accomplish this? Should I create separate controllers and invoke these models for the user website?
I would create a different set of controllers for the backend and frontend. I would move the backend controller to a namespace. More Information on namespaces: http://guides.rubyonrails.org/routing.html#controller-namespaces-and-routing
How do I ensure the website users do not have access to the cms screens? Any pointers, design principles, routing methods, gems for such an application?
For this you need some kind of authentication and authorization. Some examples:
authentication:
authlogic
devise
authorization:
cancan
declarative_authorization
aegis
acl9
There are some good screencasts on this matter:
Authlogic
Declarative Authorization
Authorization with CanCan
Introducing Devise
Customizing Devise
You need a layer of authentication.
The easiest way, and I'd say the most common one is to make separate controllers for each section, and add a before_filter method in each section authenticating and authorizing user to continue (usually a is_admin? method on the user model), or redirect back with an error message if the user is not allowed.
You can separate your controllers with namespaces (something like /admin/authors, /admin/books/1/edit and so on), and keep them RESTful this way.
If you need a more complex schema, you can use any of the authorization tools out there http://ruby-toolbox.com/categories/rails_authorization.html