Declarative Authorization: restrict model actions on specific attributes - ruby-on-rails

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.

Related

Adding new admins using device

I need to make three admins on the web page I am developing.
Admins will have access to view all the users.
When I follow the instructions, the current user is being made the admin. I need to add two more to my admin list.
I have device gem installed in it.
You need to post a lot more detail. I'll take a bit of a shot in the dark:
You've made a new model, Admin, which is different from User, right? If you want new admins, you'll need to create them. Admin.create(admin_params) and such. Users are not and cannot be admins.
If you want your admins to also be users, you're better off following option 2 in the how-to guide, adding an 'admin' boolean property to the user model. Then you can set any user an admin with some_user.update_attribute :admin, true (and all the ways you'd normally manage model attributes) and test for it with current_user.admin?

Ruby on rails. How safe is an admin attribute for user model?

I can't find any definitive answers to this.
I have a user model with devise, and I have added an 'admin' attribute that is a boolean, which defaults to false. Currently I have to go to the console and manually change the attribute to true to give a user this admin status.
My question is, how secure is this? Is there any way for someone to change the status of their own user without accessing the server (Currently my computer)?
Could safety be compromised once I put the site into production? The admin attribute is not a permitted parameter on sign in, sign up or update.
I am asking as I want to add a personal dashboard for myself to view, edit or delete anything I might need to when the site goes into production.
If you use strong params then the risk is only if you allow setting this attribute from any action outside of admin panel.
To be extra safe you can use attr_readonly so you can only set this attribute when object is created.
Considering Devise, safety is the last thing that could go wrong, unless either one of Rails or Devise is broken, which is unlikely.
You have taken sufficient steps like not allowing the admin parameter, which should be enough for pretty much every situation.
Several Rails applications, including GitHub and Shopify have been doing this (possibly without Devise, but that's not a concern) without security issues. I myself use Devise and admin flags and can vouch that it is safe enough.
Any reason you are not using something like RoleModel? It will allow you to expand to other roles in the future in a much more manageable way than adding an attribute to User for each role.
Either way... unless you provide a way for them to update that field, it should be secure. If you want to ensure that there's no way a non-admin could update that field, you could always add something like this to UsersController#update:
params[:user].delete(:admin) unless current_user.admin?

Is it possible to make model class as a role in 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.

Rails CanCan and dynamically generated Abilities

I would like to use CanCan on top of a Mongoid based Rails 3 application. I would like to introduce general models for user, role and privilege. Essentially the authorization system shall authorize at a per action base. Therefore we want to store action x roles privilege objects.
Now when it comes to the ability DSL we could generate the abilities dynamically as an after_save hook in the proivilege model. But this results in a problem in production mode, cause these runtime changes only affect the server process where the privilege changes were made.
On the other hand one could reevaluate all (the users) abilities as before_filter in every controller. But that slowed down every request.
Just now, we are undecided how to solve this problem. I am thankful for every suggestion.
Regards
Felix
CanCan uses a simple authorization system based on a role column on the User model.
Here are some good links:
Abilities
Role Based Authorization
Why do you need to dynamically set up privileges? Unless you have a compelling reason to do so you are just introducing unnecessary complexity. Just define the roles you need to with the correct abilities (you can do this on a controller/action basis with cancan) and then assign those roles upon creation/update.

What is the best way to securely add administrative access to my rails website?

I think the answer is an admin login and then check if the user has an admin flag, but I also thought of some other related questions.
Is it better to have an admin flag (attr_protected) in the same user table as non admins? or should i have an admin users table?
Should I create a separate rails application for the admin users? This might be overkill since they will both have to access the same datbase (not to mention it might be a huge pain to set up).
Any other suggestions? Right now I just need to secure a page or two so I even looked into HTTP basic or digest authentication as a temporary measure (the protected content is actually not THAT private/important). But... I don't know how to implement HTTP auth for specific actions, I have only seen how to implement it to prevent directory access.
Any direction and discussion would be great. I am sure other Stack Overflow users will benefit from this discussion.
Thanks!
Ryan Bates has a great three part series of Railscasts on this topic which should give you some food for thought:
Part 1: Where Administration Goes
Part 2: Restricting Access
Part 3: Super Simple Authentication
There are also three Railscasts on different authentication techniques:
RESTful Authentication
HTTP Basic Authentication
Authlogic
I'm using restful_authentication plugin for this purpose. And it is very simple to restrict access to any controller or any method. On example in controller add this function:
private
def authorized?
user.admin?
end
or
private
def authorized?
user.admin? if update? || create?
end
I defined admin? method in my User model. I also created update? and create? methods that check which action was called. In restful_authentication authorized? method is always run when accessing controller.
I would put everything in one application and in one table (don't create users and admin table). You can secure admin flag in your users controller by allowing to set this value only for existing admin users.
I think it depends on the type of administration.
If the view your administrators will have of the site is the same as a normal user's, but with additional privileges, I would go with an admin flag. (Or, as your needs expand, a full-fledged roles table.) This is a situation where everybody sees the same stuff, but administrators have access to various actions (delete? edit? ban? etc.) that normal users do not.
If the view your administrators need is wildly different than the normal site, I would recommend a completely separate Rails app that accesses the same database. For example, if your "administrators" are really help desk employees that are going to answer phone calls or deal with billing questions, they may have completely different views of the database (and perhaps ways to edit the data) that aren't available in the regular application.
The disadvantage to having multiple sites is that it is possible to have models (validations, associations, etc.) get out of sync. The disadvantage to having a single site is that you may end up inserting all sorts of ugly "if-admin" code in previously easy-to-understand portions of your site. Which problem is easier to handle depends on your requirements.

Resources