Is it possible to make model class as a role in rails? - ruby-on-rails

I know that there are many excellent authorization gems out there like cancan, declarative authorization, cantango etc etc. I want to know is it possible to use the model class as a role itself?
Like for e.g. let there be two resources tutor and student then is it possible to make tutor and student as roles also? I am asking this because I have different authentication pages for different resources as my resources are totally different from each other and I am not going for a single user class for authentication.
Also guide me if I am doing it totally wrong as I am new to rails :-).

The short answer is "yes". For cancan, ultimately you are defining what constitutes authorized access and you can do that however you want. Most of the automatic pieces do assume a user model but there's no hard requirement to use the helpers provided. You'd define the authorization logic in the ability.rb file as usual but manually call authorize! in your controller.
That said, why not make life simpler and go with a single user model, but make the user's role be context-dependent? Then you benefit from an established workflow for auth and probably have a clearer domain model as well.

Related

What's a good way to validate access to models in controller specs?

I have Users which create HomeRepairTickets.
Firms can create TicketBids for HomeRepairTickets they are interested in.
Should my controller spec ensure that Firms can only bid on HomeRepairTickets they have access to? And make sure they can only update HomeRepairTickets that they created?
Or is there a better way to test appropriate authentication (eg that the ids match or that the authentication_token matches)
I'm using rspec.
You should use externalized authorization / attribute-based access control (abac).
ABAC is an authorization model defined by NIST that lets you describe authorization requirements in terms of attributes and policies. Based on your question, you would want to implement a policy along the lines of
A user can view a ticket if the ticket belongs to the same firm as the user.
With ABAC you can have as many policies as you like. There is a standard called XACML that implements ABAC but I do not believe there is anything in Ruby that implements XACML.
Your best bet is the CanCanCan gem which provides you with similar capabilities. Check it out here.
The short answer to your question is 'yes'.
"Firms can only bid on HomeRepairTickets they have access to" and "Firms can only update HomeRepairTickets that they created" are good functional requirements (aka system behaviors). You should definitely be testing at this level.
Now, you may decide to test at lower levels (e.g., tokens/ids matching, etc.) as you go along developing, but it's always good to come back to testing your high-level requirements and make sure your system is well-behaved.
Whether or not your authentication lives in a controller is a whole other topic. As is how you choose to represent your authentication logic. But, it's all good stuff.

How to set up Rails app that has different types of users?

If I want to build a Rails app that has two different types of users, let's say one type is called players and the other one is owners, what is the best and most efficient approach to modeling the app?
Things to take into account:
There should only be one Login, but different Registration forms that Owners/Players can use.
Owners can have access to a control panel but Players cannot.
Owners cannot share any of Players capabilities, but both need to be able to perform Login/Registration.
I am not using Devise, so please do not suggest it.
Different Approaches I've considered:
Using cancancan gem, but it does not really seem to meet my needs in the sense that I am not looking to create a user/admin hierarchical approach but rather a if you're a Player, then you can see these pages and perform these actions but Owners cannot and vice versa. Almost like splitting the app in two. cancancan seems that it would treat Owners as "Players with extra privileges", not different privileges entirely.
Creating separate models with separate login and registration forms, which seems like a disaster waiting to happen. One small mixup between a Players table and the Owners table, especially with the primary keys, and that will be a world of trouble where people could end up logging in to the wrong accounts.
Creating a polymorphic or has_one relation toward an Account model, which so far, seems like the best way to probably go about it. If I created a polymorphic Account model, I can store different types of Players/Owners, but how could I compare login credentials against all types?
I had been trying to find something on this matter regarding how to map this out and was surprised to not find an information on how to do this without using Devise. If anyone has any good links they can point me to that also address this matter (without Devise), please leave them in your answer! Thanks.
I'd suggest one User class with a type attribute that determines whether the user is a Player or an Owner (single table inheritance). This way you keep the registration logic in one place but can customize the forms depending on the user's class.
There must be alternatives to cancancan that help with what you want to do, or you can implement helpers yourself:
def can_access_control_panel?
current_user.is_a?(Owner)
end
You have to have a way to separate one user from another. One way is to add an attribute to the User table so you can call current_user.role and it will return "owner" or return "player".
I have used Pundit gem in the past. It lets you define which controller actions the current user is allowed to access. So as you create resources for your application, you can add a policy that specifies who is allowed to that given resource. This is the repo to the application.
This answer might help you.

Declarative Authorization: restrict model actions on specific attributes

I'm quite new to rails and I'm trying to setup an authorization system that allows me to control which attributes of a model can be modified by a user.
I use declarative_authorization for a role based authorization. This already provides me quite a lot of functionality: restrict what the user can see in the view depending on his roles, which actions he can perform in the controllers and basically also which actions he is allowed to do on the model.
However, I just can't find an answer on how to restrict the actions on specific attributes of a model depending on the role.
Example:
A user that has a :guest role is allowed to update certain attributes of a user-account: When he tries to log in with a wrong password, I want to update a specific field of a user-account that will make this account inactive. The :guest role should however never be able to change the nickname of this user account.
I therefore use the "using_access_control" method in my user-model, but this either gives "update" privileges on an account for all attributes or no "update" privilege at all depending on the role.
I understand that "strong_parameters" is a gem that would basically make such functionality available but I have no clue on how to fit both "declarative_authorization" and "strong_parameters" together or how to do it simply with "declarative_authorization".
Can somebody point me to the solution?
Many thanks!
Authorization::Maintenance::without_access_control do
# do something
end
I hope this was helpful.

Rails - allow people to add association between records, but only allow admins to remove it

I have an app with the following models: People, Projects, ProjectsAdminLists.
There's is a HABTM association between people and projects. Each project has one ProjectAdminsList and each one of those can have many people.
People belonging to each Project can add other people to it, but I want to restrict the removal of this association to those belonging to ProjectAdminsList. Restricting that in the views is straightforward, but what would be the best way to do it in the controller? I'm looking for general guidance on this.
You need some kind of authorization system, I suggest you to have a look at the CanCan gem written by Ryan Bates (the RailsCasts guy), you can start watching at the Authorization with CanCan RailsCast and then look at the really good documentation.
Here an overview:
It just needs a current_user method to determine the current logged user
You write the authorization rules in a single file (ability.rb)
You use the can? method in the view layer to check if a user can do some operation on something
You call load_and_authorize_resource in the controlle to make CanCan automatically check the authorization based on the ability.rb file.
Of course I've just scratched the surface, as said the documentation is really good.

Restful model ownership validations

I know there are role based authorization gems/plugins for rails to determine if a user can do things based on which role their in. However, is there a best-practice approach to hiding actions from users based on ownership? ie: the show/edit/destroy methods for a user should only be available if they're being performed on the currently logged in user id. Hopefully that makes sense, but I've written some methods to protect against non-owners accessing methods and its become a bit bloated and ugly.
Look at cancan's implementation.
I can recommend on restful_authentication( https://github.com/technoweenie/restful-authentication ). quick tutorial http://railscasts.com/episodes/67-restful-authentication

Resources