Ruby on Rails login - ruby-on-rails

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.

Related

How can you set up a multi-tenant Rails app without using subdomains?

I'm trying to create a SAAS e-commerce tool with a backend for staff that also allows customers to have accounts and checkout on the front end. I'm struggling with how to design this so that the Company, Account Owners, Staff, and Customers are all siloed off to each Company, while also having the appropriate restrictions based on their roles.
From what I've read so far most of the rails solutions use multi-tenant patterns with subdomains, such as the Apartment gem, to silo off accounts. But it seems simpler to just have your site use one big app and database. For instance Basecamp recently switched to this approach with Basecamp3. Newer apps seem to be built this way.
And, should the admin features and the customer accounts / front end shop be separate apps completely, or can you do this with a "majestic monolith"? One big app and database, while large, seems more straight forward to me.
I found this blog post that explains how to do something like this with Pundit, but I'm still having trouble groking the big picture of how this could work with Account Owners, Staff, and Customers all in the same app.
Here are the basic needs for my app:
User Roles
Account Owner (creates the company's account and has full access to their company's data)
Staff (invited to join a company and doesn't have access to some of the company's data, such as billing information)
Customer (can sign up for the site and view products, add the them to cart, but can't access any of the staff or account owner features.)
All Users (no matter the role) belong to a Company and can't access another company's data. (Thus providing the the ability to run separate stores on the same app, which is needed to run this as a SAAS app.)
Account Owners and Staff can CRUD Products, but not Customers.
A great analogy would be how Shopify's admin area and customer accounts currently work for shop owners, but unlike Shopify, it doesn't require using subdomains.
Potential Models and Associations
Company
has_many :users, dependent: :destroy
has_many :products, dependent: :destroy
User
belongs_to :company
Product
belongs_to :company
Authorization
Would it work to use Pundit to restrict the controller actions based on User roles and then ensure that data is siloed off via the Model associations?
Signup Flow
I'm a little fuzzy on how to handle scoping the different User roles and where the "staff invites" and "customer" sign up could fit into a sign up flow.
Would this approach work?
Create separate controllers for "Account Owner Signup," "Staff Signup," "Customer Signup," and then embed my signup form into those views. (Using Clearance for authentication and would like to keep that if possible, but just augment it as needed).
Account Owner Signup: So if a someone signs up through the New Account Signup controller (with embedded authentication form) they would also create a Company.
Staff Invite: The Account Owner can create new Staff Users by inputing a Name and Email address. This creates a new User with the role of "Staff" (and thus cannot become Account Owners on another account). The new "Staff" user is sent an invite email that is basically password reset email inviting them to accept the invitation by creating a password.
Customer Signup: If someone signs up through the "Customer Signup" controller, they would automatically be given the user role "customer". Not sure how to set the Company ID in this case. (Pass the company_id as a hidden input on the customer sign up form?)
Is there a better way to design this type of app that I'm missing? Am I on the right track? I have no experience building something like this so any clues would be extremely helpful.
It seems like newer apps follow this type of pattern for multi-tenancy rather than subdomains.
You open with simple e-commerce site but the questions you're asking indicate that you're looking for something that's a little more complex :) You're on the right track.
The acts_as_tenant gem is worth a look. We use this now and it helps make sure your queries are all scoped appropriately.
I would also look at & evaluate rolify if you need to do roles (but don't rule out a boolean flag on your user as well).
I wouldn't rule out devise, but clearance is quite popular.
Using a subdomain might be unrealized work depending on the amount of effort, unless you need to actually use subdomains for vanity purposes (my.example.com vs example.com/my), you can do multi-tenancy without it.
I would consider separate controllers & namespacing for the different roles if their access varies wildly; you can also combine them into singular controllers using Pundit (but this could be unwieldy). You'll still want to use Pundit, however, Pundit can do things like scope the records a user should see.
You're on the right track and asking the right questions but the answers to all of these will depend on other questions (that you probably can't even answer right now).
I have a project where I'm doing what you noted (pundit to restrict data, acts_as_tenant to silo things) but as it develops certain patterns emerge that lead me down a different path. Namespacing admin, rather than doing admin checks inside the same controller for example; because if you re-write to an API you end up trying to make the same endpoint do different things and it's much cleaner to separate out the 2 endpoints behind a namespace & document the actual behavior in my opinion.

Permission management without using cancan or rolify for active admin

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

Using ActiveAdmin in Rails to create user specific admin pages

To explain it in a sentence, I am asking if it is possible to use the ActiveAdmin gem to create admin pages specific to admin users, i.e. each admin user only gets to see models and associating models specific to him. If so, how would I implement this?
To further explain my situation, I have a model called Sponsor(who would essentially be the admin users), and they put up different offers(another model that belongs to Sponsor) for users to redeem. So what I am trying to do is create an admin page where each sponsor gets his own admin credentials, and the admin page only shows the information that relates to this sponsor, i.e. the information regarding the offers this sponsor put up, and all relating models and its details. Is this possible to implement using the ActiveAdmin gem or any other gems for that matter?
I would rather not implement this from scratch if there are gems out there that I could use. Any suggestions?
I haven't tried this myself but it should be easily achievable in ActiveAdmin
either by changing the default scope on per controller basis or by using AuthorizationAdapter.

Respecting associations with rails_admin

We are using rails_admin plug in to manage back end for a classroom. There is an admin(Coordinator) and several moderators(Teaching assistants). The admin and moderators should be able to add students to the database. Each student is associated with a moderator(TA). When a moderator clicks to view the students the rails_admin renders all the students in the database. How can we restrict rails_admin to show only those students whose TA is the moderator who is logged in? Admin should be able to see all the students in the database.
Rails_admin has this capability built in. You've got a couple of options as per their wiki page:
Editing the config/initializers/rails_admin.rb configuration file as per this section
Or my personal preference, using CanCan or CanCanCan as per this section
Happy to help if you run in to more specific issues.
Good luck!
Edit: Bonus link for CanCan & rails_admin, again on their wiki

How to create users with different dashboard layouts and privileges using RailsAdmin in Ruby on Rails

We are trying to create different groups of users with restricted database
functionality using the railsAdmin plugin in Rails. Specifically, there is a
table in the database that indexes all personnel. We want to create two
levels of user accounts. "Admins" have access to all personnel. "Moderators"
have access to a subset of personnel only. Further, moderators should be
able to add personnel to the database, but they should be visible only to
that moderator and the admins. As an example, if user A is a moderator and
adds a person named "Dave,", we don't want Dave to be visible in the
dashboard for other moderators (e.g., B, C, etc). Similarly, if moderator B
adds a person, s/he should be visible only to moderator B. We are having
difficulty determining where in the code this type of functionality should
be added. Any pointers would be appreciated. Thank you.
Have you considered using CanCan with rails_admin?
There is a pretty good guide on authorisation using CanCan with rails_admin on their wiki:
https://github.com/sferik/rails_admin/wiki/Cancan
p.s. you might prefer to use CanCanCan which is more actively maintained

Resources