Permission management without using cancan or rolify for active admin - ruby-on-rails

I have the requirement in one of the application to use active admin as the admin panel and I have used devise for the authentication purpose.
Now we have three types of users, super_admin admin and normal users. Super admin and admin will have the different functionality and we should use the same active admin interface.
The problem over here is as the devise will not allow two models like
devise_for :admins, ActiveAdmin::Devise.config
devise_for :super_admins, ActiveAdmin::Devise.config
we cant use both in routes to differntiate user type from routes and we can't scope the user type in the active admin as we are not using the role management systems(like cancan), but using the type field in user.
So can any one please help me to find the way to use active admin with two types of admin(super admin and admin). By using type and not using the role managements.
Thanks.

While it might be possible you're really just making a huge mess by pushing down authorization into the authentication layer.
It would make your Devise setup truly cringeworthy and you also need to setup a authorization layer if your own such as:
(current_super_admin || current_admin).is_a?(SuperAdmin) # yuck
You end up with a greatly overcomplicated authentication layer and a crappy homerolled authorization system. Both are a recipe for disaster.
Its also less than desirable if you need to be able to grant/revoke privileges since you need to transfer the user data from one table to another and also any relations that user might have.
If you want to do roles on the cheap you can simply use a enum column:
rails g migration add_role_to_user role:integer:index
class User
enum role: [:peasant, :admin, :super_admin]
end

Related

When using cancancan with devise, does devise need to be added to ability.rb?

Question: when using cancancan for authorization and devise for authentication, do I have to define any authorizations for the devise part of the app, or does devise take care of everything itself?
Example
For example, for (all) other resources, we should place load_and_authorize_resource in the controller of that resource so that users who should not access it are prevented from doing so. Then, to allow access to those should have access, we can define abilities by adding code like this to ability.rb:
# ability.rb
can [:index, :show], [Patient], user_id: user.id
Back to my question - do I have to add load_and_authorize_resource to any of devise's controllers and define permissions for devise controllers in ability.rb? OR does devise take care of all that without the developer having to do anything?
We obviously don't want to allow one user to change another user's account info!
It's important to distinguish between devise authorization part of account info (session creation/logout/email+password+restoration/changing if you have that enabled) and any other custom logic and data related to it (for example - names, shoe sizes, whatever) that is kept inside or accesses the same model.
Devise controllers, if you did not change them much - are very simple and do not need additional access control because by design user is only able to edit their own auth data (they simply do not handle user id from outside thus there's no way to tamper it). Moreover just adding load_and_authorize_resource will at least have no effect or more probably will interfere with existing devise code because it was not designed around cancancan.
But if you have your own controllers for user profile(s), like user index, admin editing other's profiles etc - obviously, you have to facilitate access control there.

Is there a way to use the Rolify gem in a multi-tenant setup?

I like the Rolify (https://github.com/RolifyCommunity/rolify) API and would like to use it in my app but am having an issue finding anything in it's docs or tutorials that would allow me to define a role scoped to both a params[:account_id] && a resource instance. Has anyone used Rolify in such a way and could offer an advise on how to set this up?
Ideally this would look something like
user.add_role :moderator, Notes.where(account_id: params[:account_id])
You can add a role to a particular instance as follows:
note = Notes.where(account_id: params[:account_id].first
user.add_role(:moderator, note)
We have a multi-tenant Rails app in production that uses Acts As Tenant and Rolify for a use case like you described. There are User accounts, which are independent from any tenant, each user can have multiple Memberships, thus be a member of multiple tenants.
Each users memberships can have individual roles. For the lower ranking roles, we needed to allow access to only certain instances that more privileged members can assign to them.
A good multi-tenant gem should take care of scoping all Rails models that you want to only one specific organization and prevent any member from organization A to access data from organization B. So there really should be no need to use something like params[:account_id] manually, when you want define a role scoped to a resource instance.

Creating new users through Devise with an admin user who is already logged in

I'm building a service on Rails using Devise which requires an 'admin' user to add regular users to their organization account.
The default behaviour of Devise doesn't support this, as the ':require_no_authentication' method is called when a logged in admin user tries to create a regular user account.
What would be the recommended method of achieving the functionality I am looking for?
:require_no_authentication is called by prepend_before_filter in the
Devise::RegistrationsController class, rather that in one of the
RegistrationsController methods, so I do not know if this can be
overridden (correct me if I'm wrong).
I believe separating the admin users from the regular users would
work, however these users will share very similar properties, so I
believe doing this will add unnecessary repetition.
I am currently trying to create new admin users (who in turn create
the organization that regular users belong to) using the regular
Devise sign up flow with 'users#new' and 'users#create' controller
actions, and allowing admins to add new users through a 'users#add'
action.
If there is perhaps another good user authentication gem that would better suit my needs, I would be happy to take a look at switching to that.
This seems to be more of an authorization problem than an authentication problem. You can use an authorization gem, such as cancan, to assign roles to users (such as admin) and grant abilities to those roles. This works really well alongside Devise. Here's a tutorial:
http://www.tonyamoyal.com/2010/07/28/rails-authentication-with-devise-and-cancan-customizing-devise-controllers/
EDIT: I think I may have misunderstood your problem. Maybe what you need is just another controller to handle the creating of users outside of the Devise controllers. You could use cancan to restrict access to this controller to only admins.

Rails Single table inheritance (STI) with the User model

Building a small reservation site. There are users (who login and work with the site) and there are guests who are being assigned to rooms. users can be (are?) guests but not all guests are also users.
My initial inclination was to set up a belongs_to / has_one relationship between user & guest but maybe STI would work here? Being as users & guests have first_name, last_name, email etc. does it make sense to set up the model such that, say, user and guest both inherit from person?
I will roll my own simplistic authentication so the only additional fields user is likely to have are password_digest, roles_mask and a icon_color.
Any suggestions? I only ask because things can get tricky around authentication, authorization & whatnot.
Appreciate any ideas/tips!
The simplest approach here would be to, as suggested, stick to STI. You can, for example, setup a single devise User model as well as apply ACL with CanCan and define roles for your users.
CanCan's ability spec will determine which resources are accessible and what are not. The advantage here is that users can be guests, and depending on how you setup your ACL, guests can be prevented from having admin like access.
However, Jesse's suggestion of going two separate Devise models is also a good idea as this ensures their sessions are separate. This is more straightforward to implement as you can then setup a User-specific ACL and Guest-specific ACL accordingly.
https://github.com/ryanb/cancan

Ruby on Rails login

for a university project i have to create a small ruby on rails application, in Netbeans, which allows staff of the university to maintain their absence records.
The sample logins available in books have been regarding a singular user table. My application will require 3 types of users staff (who are assigned to a manager), manager and admin (to create/edit/delete all employees). Thus the login will have to bring up a particular users home page, in steps my confusion.
My table structure at the moment has the field user_id in both the manager and staff table which has a 'has_one' relationship with ID of the users table which simply contains the fields user_id, user_name password and user_type.
I can't get any adapted sample code for logins to work with this multi user application, any insights or ideas on tutorials available similar to this?
Cheers.
P.S. I have the full spec available if any other further information is required.
I couldn't tell from your question if you already have authentication working.
But, I've set up similar systems using the devise and cancan gems.
With devise, you just need to specify the root path in config/routes.rb and your user will be redirected there upon signin. For example you could have a route like this:
namespace :user do
match 'dashboard' => 'dashboard#index', :as => :root
end
Then, in dashboard#index, you could provide profile-specific actions. Also, a good way to manage user roles would be to put a role column on the users table and use the cancan gem.
Check out this railscast on the subject http://railscasts.com/episodes/192-authorization-with-cancan... So you could assign someone to the admin role, and using cancan's simple DSL they could create/edit/delete all employees.

Resources