What's the best way to implement ACLs to a Rails application?
I use the authorization plugin (Created by Bill Katz):
Roles can be authorized for the entire application, a model class, or a specific object. The plugin provides a way of checking authorization at the class or instance method level using permit and permit? methods. It also provides english-like dynamic methods like "user.is_manager_of project" (where "user" acts as authorized, "manager" is a role, and "project" is an authorizable model). You can specify how control is redirected if authorization is denied. (quote source)
Homepage:
http://www.writertopia.com/developers/authorization
Docs:
http://github.com/DocSavage/rails-authorization-plugin/tree/master/authorization/README.rdoc
You might also be interested in reading this comparison (from last year but still somewhat useful; it's where I got the above quote from):
http://www.vaporbase.com/postings/Authorization_in_Rails
And a more recent comparison:
http://steffenbartsch.com/blog/2008/08/rails-authorization-plugins/
Using s3 in a healthcare application, private links
From the Documentation,you should use one of Amazon's "canned" ACLs.
Amazon accepts the following canned ACLs:
:private
:public_read
:public_read_write
:authenticated_read
:bucket_owner_read
:bucket_owner_full_control
You can specify a the ACL at bucket creation or later update a bucket.
# at create time, defaults to :private when not specified
bucket = s3.buckets.create('name', :acl => :public_read)
# replacing an existing bucket ACL
bucket.acl = :private
Rails ACL Design Question
I think CanCan can help you. It's simple to use and should do just what you need. Here's a RailsCast: Authorization with CanCan
Adding customizable user-groups and ACLs to your web app(s) (the smart way)
If you roll your own RDBMS schema, the performance and scalability is all up to your implementation. Instead you could use LDAP. You dont need to implement the LDAP (or below x.500 directory service). There are existing servers that can be used like OpenLDAP. If your company can afford you could use eDirectory from Novell or AD from MS. eDirectory supports some nice feature called dynamic groups. You may read that from here http://www.novell.com/coolsolutions/feature/5414.html.
How should I be implementing my ACL in a web application?
That's basically the same approach I take in my own web apps (and a bit of trial and error has gone into that for me). The only difference is, I'd probably use a table which has the different permissions as columns, so that if you want to add more permissions later on, you can. Using bits in an integer limits you to a fixed number of permissions, namely as many bits as there are in the integer. Typically that would be 32 which I suppose is probably enough, but I prefer not to limit myself that way.
For what it's worth, that's also the model that phpBB uses (permissions as table columns), and if it's good enough for arguably the most popular PHP web app, it's probably good enough for you ;-)
Rails: Is there any way to build dynamic role based authorization in rails?
Pundit vs CanCanCan
Your conclusions about CanCanCan and Pundit are just nonsense. Neither of them are "static" or "dynamic" and they have pretty much the same features. The architecture and design philosophy are radically different though.
CanCanCan (originally CanCan) is written as a DSL which was the hottest thing since pre-sliced bread back when Ryan Bates created CanCan 10 years ago. It scales down really well and is easy to learn but gets really ugly as soon as you reach any level of complexity. If anything doing "dynamic authorization" in CanCanCan is going to be a nightmare due its architecture. The ability class in CanCanCan is the god of all god objects.
Pundit is just Object Oriented Programming. In pundit your policies are just classes that take a user and resource as initializer arguments and respond to methods like show?
, create?
etc. Pundit is harder to understand initially but since its just OOP you can tailor it however you want. And since your authentication logic is stored in separate objects it scales up to complexity far better and adheres to the SOLID principles.
How do I setup a dynamic roles system?
This is you standard role system ala Rolify:
class User < ApplicationRecord
has_many :user_roles
has_many :roles, through: :user_roles
def has_role?(role, resource = nil)
roles.where({ name: role, resource: resource }.compact).exists?
end
def add_role(role, resource = nil)
role = Role.find_or_create_by!({ name: role, resource: resource }.compact)
roles << role
end
end
# rails g model user_roles user:belongs_to role:belongs_to
class UserRole < ApplicationRecord
belongs_to :user
belongs_to :role
end
# rails g model role name:string resource:belongs_to:polymorphic
class Role < ApplicationRecord
belongs_to :resource, polymorphic: true, optional: true
has_many :user_roles
has_many :users, through: :user_roles
end
You can then scope roles to resources:
class Forum < ApplicationRecord
has_many :roles, as: :resource
end
Rolify lets you go a step further and just defines roles with a class as the resource. Like for example user.add_role(:admin, Forum)
which makes the user an admin on all forums.
How do I create a permissions system?
A simple RBAC system could be built as:
class Role < ApplicationRecord
has_many :role_permissions
has_many :permissions, through: :role_permissions
def has_permission?(permission)
permissions.where(name: permission).exists?
end
end
# rails g model permission name:string
class Permission < ApplicationRecord
end
# rails g model role_permission role:belongs_to permission:belongs_to
class RolePermission < ApplicationRecord
belongs_to :role
belongs_to :permission
end
So for example you could grant "destroy" to "moderators" on Forum.find(1)
by:
role = Role.find_by!(name: 'moderator', resource: Forum.find(1))
role.permissions.create!(name: 'destroy')
role.has_permission?('destroy') # true
Although I doubt its really going to be this simple in reality.
Related Topics
How to Run Rake with --Trace Within Capistrano
Ruby Incorrectly Parses 2 Digit Year
Case Expression Different in Ruby 1.9
How to Extend Redcarpet to Support Auto Linking User Mentions
Converting an Array of Hashes to One Hash in Ruby
Installing Ruby Gem Less-Rails on Windows MAChine Using Therubyracer
Sorting a Hash in Ruby by Its Value First Then Its Key
How to Add New View to Ruby on Rails Spree Commerce App
Ruby on Rails Country/State Select Enigma
Authlogic Perishable_Token Resets on Every Request
Ruby Variable as Same Object (Pointers)
How to Create a Charge and a Customer in Stripe (Rails)
Could Not Find Rake-10.0.4 in Any of the Sources (Bundler::Gemnotfound)
Clicking a Button with Ruby Mechanize
Ruby 1.9.2 - Read and Parse a Remote CSV