Rails configurable authorization per-role/crud action - ruby-on-rails

I'm working with a Rails 2.3 app that is already using declarative_authorization to handle user permissions. Each user belongs to one group (no fancy roles) with permissions on certain models, mostly the regular CRUD actions, but with a few special ones. This all works fine with declarative_authorization in it's usual out of the box mode.
We now want to allow admins to set permissions on particular groups of users with regards to model types. For example, we create a new group Foo, assign some users to it, and then decide with checkboxes if users in group Foo can c/r/u/d objects of model Bar.
I've used acl9 before, and I think I see how I could make that work. I've been a fan of CanCan lately, but I don't see how do it easily with that. If declarative_authorization can do this, I'll stick with it, but I'm prepared to bite the bullet and switch.
What plugin would be the best way to accomplish this? Is there a way to get declarative_authorization to do the job? An elegant way to use CanCan? Are there any gotchas I should watch for, e.g. database performance?
I could be convinced to upgrade the app to Rails 3.1, but I'd prefer to find a 2.3-compatible solution.
I've seen some similar questions, but no satisfactory answers
Rails Dynamic Role-Based Authorization plugin?
and this, for cancan
https://github.com/ryanb/cancan/wiki/Role-Based-Authorization

I'm a fan of the StoneWall gem - authorization checks are in the form of a Ruby block, so in that block you could look up records and see if the user in question has authorization.
There's not a lot of documentation, but the idea is:
a_user_object.may_read?(object)
If object is a Todo instance, then Stonewall will look int the Todo model and execute the read block
# app/models/todo.rb
stonewall do |s|
s.action :read do |todo, user|
todo.owner == user # only the owner of a todo item may read the item
end
end
This approach makes two things easy:
read is just a Ruby block, so whatever you want to happen can happen
actions can be given arbitrary names, so if you want to check to see if a user has permission to comment on a todo item (for example), just create a s.action :comment and access it with a_user_object.may_comment?(object)

Related

Access Control List in ActiveAdmin?

I was wondering if there is any gem that implements an active admin control list in ActiveAdmin?
If none, what's the best way or approach to simply do this?
Reading up on pundit and still active admin whether or not I should really write one from scratch.
Thanks!
Edit:
I currently worked on this yesterday and have my access control list together with my group model. the form looks roughly something like this:
its rendered partial in my activeadmin group.rb
So yeah I guess the correct word is managing permissions on my activeadmin. I'm reading up if there is any way I can integrate activeadmin roles in my current setup. I'm kinda seeing this kind of setup is tedious?
I made it like this because eventually if there needs to be a lot of different roles, they don't have to ask the devs to code it everytime.
I think you might be looking for ActiveAdminRole

How to implement a group/team permission system with Rails 5 and Pundit or other gem?

From what I understand of Pundit so far, it is geared more toward allowing the current user to perform certain actions on certain controllers, but how is it possible to extend this to cover if the user is part of a team or group that that would allow them certain actions? Or for one user to allow another user certain actions on, say, a post they created?
I like the idea of Pundit being "plain old ruby object" but I am open to working with another gem that may simplify how to do what I'm looking for. I have found a gem, Groupify (https://github.com/dwbutler/groupify), that seems to have gone cold for the past several months. I do have a requirement that anything I implement must be actively maintained so that one is disqualified. Does anything similar come to mind?
use cancancan gem. This is the great solution for permission.

Path security and before_filters rails

I am currently creating an app where users can create and apply for jobs. However as I am fairly new to rails I am facing a fairly significant security feature in that if any user knows the correct path, for example:
localhost:3000/users/user_id/apps
Then they can see any application made by any user for any job!
I am fairly sure that I need to use a before_filter to check that the current_user.id matches either the user_id found in my jobs table for each job or matches the user_id found in my applications table.
I am really not sure how to structure this though or where to apply the filter - for example is it better to create the filter in the application controller and then apply a skip_before_filter instance where needed.
Any help people can offer on contructing this code and where to place it would be much appreciated! Thanks :)
Before you start looking at authorization solutions such as cancan, a simple approach is to avoid doing
App.find params[:id]
Since an app is associated to a user and you've got current_user setup you can do
app = current_user.apps.find params[:id]
Which will only find apps associated with the user, no matter what the parameters to find.
Where cancan really comes into its own is when you need a more complicated who can do what system. For example a user might be able to edit any job they've created but view (and not edit) another set of jobs.
For example
can :manage, Project, :user.id => user.id
can :read, Project, :department => user.department
This would allow users full access to any of their projects and read access to projects in their department
Another thing about cancan is that rather than having before_filters or macros scattered around your controllers you declare the rules in one place, so it's usually easier to see what's going on. There's loads more info on the cancan wiki an a railscast too.
You are right a before_filter might be an sollution but its not the state of the art solution. Theres a railscast for that,...
http://railscasts.com/episodes/192-authorization-with-cancan/
When your using cancan but not devise you need to create the current_user helper that should return the User object of the currently logged in user...

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.

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