I am building an internal project management software (ala Basecamp) that will be for our internal and external use. I am struggling to find the best strategy for doing advanced permissions though.
Like Basecamp, there will be a number of clients, with a number of projects under them. I want to be able to assign each user different viewing rights to each client and project, which will dictate who can see what. Basically, an admin should be able to say "this user can see these 4 projects", and then when that user logs in, they are presented with those 4.
I am using Cancan for overall permissions, but this does not appear to be able to assign in the way I need. I've looked at role_model, cantango, et. but can't find a use case that fits exactly what I am trying to do, even though it seems quite standard.
Any insight here?
Thanks!
Edit:
It has obviously occurred to me to just do a permissions table (described here: How to create a basic User Permissions per project association?). I struggle with a) is this the best way? and more importantly b) what is the best way to check permissions in the app and only show allowed data?
How about creating extra model Permission, that will hold permission for user for each project?
Of course you can use can_can, but this approach will make is simple to analyze and solution will be dedicated for problem.
ie.
class Permission < ActiveRecord::Base
TYPES = {
:user=>1,
:manager=>10,
:admin=>100
}
belongs_to :user
belongs_to :project
validates :permission_type,
:inclusion=>{:in=>Permission::TYPES.values},
:presence=>true
end
class User < ActiveRecord::Base
has_many :permissions
has_many :projects, :through=>:permissions
...
end
class Project < ActiveRecord::Base
has_many :permissions
has_many :users, :through=>:permissions
end
Related
I have a rails 4.1 application setup with Devise.
I have:
one USER model and one PROFILE model. The user has_one profile
However, I have two types of users - Buyers and Sellers (it's a service platform and I have to use states to check if the user & profile is 100% completed to mark a user active).
Everything is working up to this level, but I am looking for some suggestion on how to model these two user types. Please note that the sellers have more responsibility, like adding portfolio items, applying for jobs etc. The buyers on other hands only post jobs and message sellers. Think of it like any other standard marketplace.
My question is:
Whether to use STI, please if someone can let me know how to do this, using the current setup?
Use roles system using Cancan or other?
The current setup is:
User model:
class User < ActiveRecord::Base
has_one :profile, dependent: :destroy, autosave: true
class Profile < ActiveRecord::Base
belongs_to :user
All profile data of both users types is in profiles table.
Thank you for your time.
I'm currently building a rails application that contains 3 user types. This is my first experience with web development, and I would like to avoid making crucial design errors that will cost me later on. Hopefully more experienced rails users and web developers will be able to guide me in the right direction.
I want to use Devise as my primary authentication system, and I am currently planning something like this in order to support 3 user-types within the Devise framework:
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :email, :password, :password_confirmation, :remember_me
belongs_to :rolable, :polymorphic => true
end
For each of the three user-types:
# usertype1.rb
class UserType1 < ActiveRecord::Base
has_one :user, :as => :rolable
end
# usertype2.rb
class UserType2 < ActiveRecord::Base
has_one :user, :as => :rolable
end
Essentially, there is a polymorphic association between the user class and the several different user types. My hope is that this approach will allow me to eventually add different associative keywords within the user-type models (such as has-many) that will allow convenient querying of the database.
I'm also concerned about how to implement user-dependent routing. The idea is that each user-type will see a separate "hub" when they log-in, with different dashboards, different actions, etc. I was thinking that I would approach this by overriding the Devise SessionsController. Something like this:
class SessionsController < ApplicationController
def new
end
def create
user = User.find_by_email(params[:email])
if user && user.authenticate(params[:password])
session[:user_id] = user.id
if user.type == 1
redirect_to hub_typeone
else if user.type == 2
redirect_to hub_typetwo
else
redirect_to hub_typethree
else
flash.now.alert = "Email or password is invalid"
render "new"
end
end
def destroy
session[:user_id] = nil
redirect_to root_url, notice: "Logged out!"
end
end
The idea is that upon successful authentication, the user is routed to a different page based on user type. I'm planning on using the devise current_user framework to then query the database to populate the hubs with the user-specific data.
Do you guys have any pointers for me? Do you see any huge flaws in my plans/reasoning/approach? Thanks in advance!
I get a feeling you are over-engineering this, and building something You Aren't Gonna Need It
It's best if you are clear about what the three different user types are. Most applications would require the following three user types:
Guest users, who aren't logged in, and can access some part of the application
Regular users
Admin users who administer the rights of regular users.
I am curious to know what other user types you would need if they are not in this list.
Devise wikipages has suggestions on how to create a guest user, and how to add an admin role. Probably best to start by implementing the functionality of the regular users of your application, and then use the above mentioned resources to add other user types.
I am trying to write a database for a company in town. I am using Devise for authentication, and Forem for the forums of the site. I decided to just have one class, "Account" for the Devise authentication, which will have many different access types to the site.
The bulk of the users will be just customers, which are segregated by routes (not Rails routes, street routes). So I decided to have them have their own profile model.
I want to do this - Profile is linked to account, and to route. (Routes are named gmr_routes)
Is this code the proper way to do it? Documentation I've found hasn't told me I can't, but I just want to be sure....
class Profile < ActiveRecord::Base
attr_accessible :first_name, :last_name, :phone_number, :street_address
belongs_to :account
belongs_to :gmr_route
end
Account has a has_one relationship with Profile, and gmr_route has a has_many.
Is this right?
Bryan
Yes, that's perfectly acceptable. You need to remember to include a foreign key id on any model with a belongs_to.
So in the case you describe, you would have account_id:integer and gmr_route_id:integer in your migration, and include those in the attr_accessible call in your model
Hi I have a NOOB question in light of what happend at GITHUB with their application being exploited because of the security hole in Rails.
What is the best way to protect object attributes in Rails but still allow them to be assigned values where applicable?
Thanks
Actually Rails 3.1 has added new built-in ways to handle mass-assignment with roles which is probably something that you want to take a look at.
Release notes here
Basically it works like this:
class User < ActiveRecord::Base
attr_accessible :name
attr_accessible :name, :role, :as => :admin
end
What this enables you to do is that you can use the following way to allow the user to update his own information in one of your controllers:
#user.update_attributes(params[:user])
And that usage can never update the :role attribute in the User model. But when you have your admin users managing the roles in a separate controller, then you can user the following syntax:
#user.update_attributes(params[:user], :as => :admin)
And that will allow the :role attribute to be updated as well
I'm a Rails noob and am hoping someone can help me wrap my head around this issue. I have an app that has a single User model using Authlogic for authentication and CanCan for authorization. There are three roles: Consumer, Business, and Admin. A user can have any number of these roles.
Businesses have additional attributes, however, and I need to model this such that I can add roles that each have potentially different attributes. Instinct tells me that I need to have a separate model to represent each role's attributes, i.e. BusinessRoleProfile, ConsumerRoleProfile, etc and then maybe mixin a module programmatically that adds the appropriate has_one reference(s) to the profile model(s).
Is this the best way to handle the separate attributes? If so, can someone guide me through how to dynamically include those mixins based on what role the user has?
EDIT:
Did some more research, this may help you. https://github.com/thefrontiergroup/scoped_attr_accessible
Looks like you can do things like:
class User < ActiveRecord::Base
# All attributes are accessible for the admin scope.
attr_accessible :all, :scope => :admin
# The default scope can only access a and b.
attr_accessible :a, :b
# Make both :c and :d accessible for owners and the default scope
attr_accessible :c, :d, :scope => [:owner, :default]
# Also, it works the same with attr_protected!
attr_protected :n, :scope => :default
end
OLD ANSWER
Looks like it may be featured in CanCan 2.0.
https://github.com/ryanb/cancan/issues/326