Roles that are User<>Project Based - ruby-on-rails

Currently I'm using Devise & CanCan which allows me to create
Users with Roles using a (Roles_Users) table.
That's nice, but what I want is to Have Projects in my app and for
each project for a user to possibly have a role like (Admin, Viewer,
etc) IE, roles are not assigned to users but to users based on what projects they are a member of.
Examples:
User X belong to Project A with an Admin Role
User X belong to Project B with an Guest Role
User Y belong to Project B with an Observer Role
What kind of Model would work for this?
Models
Users
has_many: projects
Projects
?
Roles
?
Users_Roles_Projects (user_id, project_id, role_id)
What do you think? I'm a newbie and could use the understanding and
thinking from you fine experienced folks. Thanks!

You should have a look in to has_many :through. This Railscast should get you up and running: http://railscasts.com/episodes/47-two-many-to-many
For example, you could have User has_many Projects through Memberships (I'm sure you can come up with a better name!)
Your Users model would contain the standard user details, the Projects model would contain the project details and presumably you have some Roles model somewhere (I've not used either of the libraries you mentioned so I can't comment in terms of how they work). The key is the Memberships model.
The membership model would contain the userID, projectID and a roleID. In the database there should only be one instance of any given userID and projectID pairing so by storing the roleID along side this pairing you can assign the role to that user on the specified project.

Related

Devise Model inherit from another devise model

I'm creating an online real estate platform which facilitates (normal) Users and Real Estate agencies. This platform has following user types:
Normal Users: can search houses for rent/purchase, reviews agencies
etc.
Agencies: can upload posts for house rent/sell etc
Employee: works for a Agencies
Super Admin: manages the site
Team Member: manages portions of the site delegated by Super Admin
Each user type then has different fields (4 - 6 additional fields each). Normal Users and Agencies can self-register. Employees and Admins can be registered by Agencies and Super Admins respectively. Furthermore there are some different multiple roles for a user type (which is not relevant to discuss for this case).
Currently, I have three different devise models (User, Agencies & Super Admin). They have different login and registration forms but share same session [Reference: [https://github.com/plataformatec/devise/wiki/How-to-Setup-Multiple-Devise-User-Models]][1] User has facility to register via social media (OmniAuth) but Agency must has to register via private Email Id. And Admins will only be registered by Super Admins.
Here comes requirement [PROBLEM]:
The following fields are what I've identified as being shared between the three user types above: Email address & Username They must be unique for all cases. For example, if an agency has a username then user can't register with same username. At the moment, we are not meeting above requirement as we have different tables/models for different type of user.
MY PLAN
Now, since these are all really different users who interact with different sections of the application, so it feels clean to have three different devise models. Therefore, what I think is to create a parent devise model which should be inherited by all type of user models. This way can help me to solve my problem. But now, I'm not confident that how can I inherit parent devise model and use it for my case.
Second option is to use STI (Single Table Inheritance). But my major concern with this approach is that it will create mess with registration and security things.
Now here is my problem with my researched options. What would you recommend me to chose. Moreover, it'd be great if you put an example for elaboration.
P.s. I am inclined to the first one option as I have already done with three different models and their login/registration stuff. :)
Not sure how your going to accomplish this without a roles system.. I suppose you could namespace or scope it out but wouldnt be the most secure to keep access to a specific user group.. atleast in my oppinion.
You could Use Single Table Inheritance (STI)..
Essentially you could do something like this (if i understand you correctly)
class User < ApplicationRecord
# MASTER
end
class AnotherUser < User
# Inherits attributes from User Table
end
going this route you will need to add type:string to your User model.
here are a few reference links:
http://api.rubyonrails.org/classes/ActiveRecord/Inheritance.html
http://eewang.github.io/blog/2013/03/12/how-and-when-to-use-single-table-inheritance-in-rails/
they helped me when i ventured down the STI path..
For example, In a project I did this like so:
class User < ApplicationRecord
# Devise Modules Here
end
class Admin < User
end
class SuperAdmin < User
end
now the tricky part I found was creating these users.. i opted to create a controller and a link, so in my app a User is created only by an admin or superadmin, and an admin can only be created by a superadmin

Group formation with owner and members using mongoid based databases

In my rails app, I have a user model with other fields and associations in it. Now I want, my users can make many projects and a project can have many users as members in it. And, the owner of the project is the one who created it. So, the whole scenario is Users can be owner or member and can be part of many projects. I have made my user using devise and I am using mongodb as my database. My user model has already many fields and associations in it, now I am struck at defining associations and relations for the above mentioned problem.
I have found one similar article with Active record: https://coderwall.com/p/rqjjca/creating-a-scoped-invitation-system-for-rails
But I want to execute all using mongoid and rails 4.
The solution for above problem is not so hard, as mongoid allows has_and_belongs_to_many association in rails, we can associate as:
In my users.rb:
has_and_belongs_to_many: projects
In my projects.rb:
has_and_belongs_to_many: users
Later we can also define roles of users as admin and member according to our requirement.

Rails, Devise, CanCan or Declarative authorization

I am developing a app in ruby on rails, and I reached a point where I don't know what is my best solution for the fallowing scenario. So far I am able to create Users, create projects, associate users (something like on FB), I am able to invite users to my website and now I would like to allow users to give different levels of access to projects that they created, to other users(something similar with github). Also the users after creating the account they will get a role of superadmin, like that they will be able to manage their on projects, or assign projects to their associates. So which will be my best option between cancan and declarative authorization. Also do I need a table which will store the user_id, role_id, and project_id if I will use cancan or declarative authorization?
Thank you
I will explain my problem better.
So far I have User (with devise) which are able to create projects. So, if user1 creates project A and project B I want him, to be able to assign user2 with role admin on project A, and user2 with moderator role on project B.
I was thinking in creating a UserRoleProject link table, is it a good idea? Or if not please help me with some pointers.
The action will be something like, User1 select from a list user2, select a project from another list(that user1 created), and select the role that the user2 will have on that project.
Any user will be able to perform the same action on their projects.
Also there will be n projects and n users and 3 access levels(admin, moderator, guest)
Thank you
I once made a huge app with allot of roles and each role had its sets of available actions, and i used devise and cancan and they work like a charm, they integrate quite well and both have great documentation.
for the other question you can do something like this
project model:
has_one :user
has_many :collaborators, :through => :team
team model:
belongs_to :user
belongs_to :project

Devise + STI + Authorization

I have the following situation:
My app has several types of users: Owner, Team Member, Collaborator, Client, and Guest. (the Guest type isn't relevant for this question)
These are the connections between the different models:
Owner belongs_to Account
Account has_many Team Members
Account has_many Projects
Projects habtm (or hmt) Collaborators
Project habtm (or mht) Clients
There are four key functions I need for my authentication & authorization:
Be able to upgrade a Collaborator to a Team Member (this means removing all habtm's to Projects, and add a belongs_to to Account
Be able to have different Devise strategies for different users (Owners have registerable, clients do not)
Have different login pages which only accept a subset of users (separate login for owner/team members/collaborators and clients)
Be able to call the different subset of users using Account.owner, Account.team_members, Project.collaborators, and Project.clients
I have gone over several solutions in my head, but I am unsure which would work best in my situation.
At first I thought about using Devise for both the authorization and authentication, but I figured I'd better use something like CanCan for the authorization part.
I also considered using one table for each user type, but that would make it harder to change roles after initial creation
I am now dubbing on using STI fo have TeamMember < User, Client < User, etc. But since Clients and Collaborators belong to Projects and Owners and Team Members belong to an Account, I am not sure that will work easily with STI, and I also haven't really found any good examples on Devise with STI.
Any ideas how to solve this situation?

How I can create with multiple types of users, using a simple login with Devise?

I'm using Mongoid, Devise and Rails 3.1.
I have four models: Students, Teacher, Parents and School (the main account). All them will log in on system. But, I don't want create four ways to login. I want create an unique login method using anyone this models, but with respectives roles (This is the minor problem, I already can do that with CanCan).
Anybody have a easy solution, without create a programming-hell?
Actually, people logging on to your system are all Users. So either you choose to let the classesTeacher, Student, Parent, SchoolRepresentative to inherit from User using STI.
Most of the times I prefer simply that a User has roles. And the role would then be teacher, student ...
The roles define what a user is allowed to see.
Hope this helps.

Resources