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
Related
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.
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.
I'm trying to create a login system in Rails 3 where I can access the logged in user not only from the views but also from the controller/model level. The reason is that I want to adapt functionality according to a privilege system where logged in users may execute different functions than those that are not logged in.
Up to this point, I tried to implement the login system from railstutorial.com, chapter 9.
When I use the login system only from the view, it works. However, if I try to use the system via a controller, I get the error undefined method 'cookie_jar' for nil:NilClass.
Thank you for any help or best practices you can provide for creating an authentication system where the logged in user can be identified from a controller.
The best advice here is probably "don't". If you want an authentication system, use something like Devise - which has had a lot of time and effort spent making sure that evildoers can't get in
If you want different users to execute different functions, this is access control, and for that you probably want something like cancan or ACL
And you want access to the logged in user from the model level? Again, the best practice is "don't". The model should have no interest in the currently logged in user - that is a matter for the controller.
(That said, rules are sometimes made to be broken - if you are doing an audit trail and need to store information about the user who made a change, for example, passing the currently logged in user to the model may be the best answer ....)
And finally, if you really, really want to do it all from scratch, take a look at this railscast
An extremely simple way is to do it as mentioned in railscast episode : http://railscasts.com/episodes/20-restricting-access
As mentioned in the screen cast, you can use the plugin acts as authenticated (http://www.railsrocket.com/acts_as_authenticated-plugin) for all your user model needs.
If everything done according to the tutorial you should be able to get current_user from both controllers and views. There's also another tutorial on authentication on asciicasts.com by Ryan Bates. You may want to explore it if you are just starting Rails, but for real-life applications it's highly recommended to use Devise or AuthLogic, which are thoroughly tested and constantly evolving.
I'm looking for a plugin that provides a role based authorization mechanism for securing read/write access to attributes. I'm picturing something along the lines of declarative_authorization for white listing attributes of model objects. I've spent some time looking around but have come up short, does anyone know of anything?
EDIT: I'm using declarative_authorization to control which users have access to what actions in the controller, but I need something similar that provides access control to the attributes of each model object. I'm trying to prevent information leakage through the web API or users from crafting malicious posts. I can do this through the mass_assignment_authorizer but I was hoping some plugin did this already.
CanCan Branch 2.0
https://github.com/ryanb/cancan/tree/2.0
Edit:
The continuation of CanCan is called CanCanCan.
See https://github.com/bryanrite/cancancan
What about creating a model / controller pair for each controller, and then allowing each role only to access methods in its controller(s)? Then you can make a before_filter in each controller that makes sure each user has permission to use methods in that controller.
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.