Rails Devise: Separate Profile or integrate with Devise Controller? - ruby-on-rails

I have a web app that will have 4 different users on it:
Owner Admin (My Team and I)
Common User of the App (the everyday people using the site
Company Admins (The people who pay the bills)
Company Users
Of these the last 3 will require profiles and other controller and Model relations.
My question is do I create separate controllers for each of these users and have them link through their current devise ID to their individual profile, or should I edit the devise DB tables to accommodate for profiles and different levels of access?
Cheers,
Andrew

Mostly depends on what you want. I prefer to use a single table for all user types.
should I edit the devise DB tables to accommodate for profiles and different levels of access?
Again depends on what you want since there are many ways to provide different levels of access.
Edit user table (ie. roll your own solution on top of devise)
use authorization gem (eg. cancan)
Therefore no hard answers.

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.

Rails App: best way of modelling two user models (like Uber). Devise? 1 Profile model?

I have following models (models don't overlap, an accountant can not be a customer):
Company has many accountants
Accountant has many customers
Accountants and customer can sign in / up.
What is the best way to do the auth?
Option A:
Use Devise with two separate models (Accountant & Customer:
https://github.com/plataformatec/devise/wiki/How-to-Setup-Multiple-Devise-User-Models
Option B:
Use Devise with one Model user, then another model Profile, which has some information, for example, column role.
Pros and cons would be very helpful, since I ask my question myself every time I build such a Rails App. I am used to work with Option B
Thanks.
Well, the right solution depends on how you are going to handle these 2 types of users, accountants and customers. Both options are reasonable, however, I would stay with Option B.
Pros are:
You don't have to worry about the same logins of Accountants and Customers models. When using the same Sign In form for logging in customers and accountants (I doubt that there will be 2 different login form for them) the controller will have to find out if it is a customer or accountant. There can be ambiguity if the given login will be in customers and accountants table. When you use only one table, users, there is no such problem.
You don't have to duplicate code related to authorization. Sooner or later, but with 2 different models, it's inevitable. Different views, different mail templates, sometimes different controllers.
I'm not sure about your case, but the same user can be a customer AND accountant at the same time. It's more about usability, and some applications really separate these accounts: that double-role users have separate logins, one for accountant role and other for customer. As for me, it's not user-friendly, and it's better to have a single login with an option to switch between the roles when logged in.
On the other hand, if accountants and customers do not overlap at all, like regular users and admins, then it makes sense to have them in different models. But in this case they would need different interfaces too, the same as admin panel for site administrators and regular UI for regular users.

Devise and discourse: Seperate devise users for vendors and users or just one devise for users?

I'm building a website, where vendors can have their own separate website on. There is vendors and normal users.
The goal is to have a closed profile page w. login for both, where a vendor can edit his website, check out stats and more. A normal user is also able to login to mark different vendor's websites as favourites and check out newest post on the forum. So what is important here is: They booth need to be on my Discourse forum, but I'd like to avoid a Vendor to have a login both for vendor and for a user (Signing up twice).
http://www.discourse.org/ has SSO ability for devise, but im not sure if it allows for two different devise models.
Should I:
Create one devise-model for both, called Users? (And have a boolean or integer if User is a vendor/has vendor-access?)
Or:
Separate them: One for Users and one for Vendors?
I haven't tested out if Discourse allows for two devise-models, since Discourse is the easiest to set up in production-mode. But I need your advice: Can I use Single sign-on for devise with two different devise models? Is it the preferable way? Or is there other ways than this I haven't noticed? Like adding a user to a vendor, or something?
Using rails 5
We can achieve this by managing role field. We can make entry on the time of sign_up in role field that user is normal user or vendor. After create this we check user_role can in after_sign_up_path and redirect to path accordingly.
for this refer gem rolify
please correct me if getting any thing wrong.

Rails, managing access of dashboard pages by models roles. Using devise

I am creating dashboard appliaction on Rails4. I have created model Partner with some data. I also have created a lot of models with views that will be associated to this Partner.
I can edit data of all models without any restrictions. Now I want to create Admin, that will login to my app and will manage data. Admins will be added via console and it does not need registration.
Also I want to make Partners to login/register too. Partners can only open pages that are connected to their data and edit them.
Here my questions depending on this situation:
How to remove registration element from Admins not affecting to Partners?
How to restrict Partners to only their own pages while Admins can be everywhere?
Is it good approach to make Admins and Partners to edit data on same dashboard, or I need to create different controllers with different views for Admins and Partners separately?
You should be able to do everything you're discussing by using a gem for handling authorization ( authority ) and one for roles ( rolify )
https://github.com/nathanl/authority
https://github.com/RolifyCommunity/rolify
You shouldn't have to create distinct views/controllers, however, depending on how divergent they are it may be appropriate. You should be able to do most of that logic by using logic to switch based on the permissions you set up.
current_user.can_edit?(page)
within the Authorization setup, you would have to determine who can edit/view/create/etc. There's a good writeup for doing this in the authority 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