Dead easy rails permissions
¶ ↑
Installation is as easy as 1,2,3: <table> <tr> <td align=“center”><h1>1.</h1>Add to Gemfile:<pre>gem ‘granted’ </pre></td> <td align=“center”><h1>2.</h1>Add to Rakefile: <pre>require ‘granted/tasks’ </pre></td> <td align=“center”><h1>3.</h1>Create grants migration: <pre align=“left”>rake granted:create_migration rake db:migrate</pre></td> </tr> </table>
This gem lets you define arbitrary permissions on a per object level (as opposed to roles). They are implemented purely as active record associations and hence easy to understand. Check out this readme on how to grant read/write permissions on individual documents to individual users. This is a moviepilot.com project licensed MIT. And now, code:
# Let's grant a user access to a document user.grant(:read).on(document) # Let's revoke a user's write access to a document user.revoke(:grant).from(document) # We can also do it rails association style document.read_users << user # Let's count all documents a user has read access to user.readable_documents.count # Let's count all documents a user has any access to user.all_documents.count # List the rights a user has to a certain document user.grants_for(document) => [:read, :write] # Define the things we took for granted (scuse me) above class Document include Granted::ForGranted # Creates associations and grant/revoke methods grantable :read, :write, :destroy, to: User end
How does it work¶ ↑
When creating the migration with rake granted:create_migration
, this gem will add a migration to your rails app that creates a grants
table when you run it. This is a polymorphic model sitting between a grantee
(e.g. User
and a subject
(e.g. Document
). It has only one attribute, and that is the right
that it gives the grantee to do with the subject.
What does this code do?¶ ↑
class Document < ActiveRecord::Base include Granted::ForGranted grantable :read, :write, to: User end
It does that:¶ ↑
class Granted::WriteGrant < Granted::Grant; end class Granted::ReadGrant < Granted::Grant; end class Document < ActiveRecord::Base has_many :grants, as: :subject, class_name: 'Granted::Grant', dependent: :destroy has_many :write_grants, as: :subject, class_name: 'Granted::WriteGrant' has_many :read_grants, as: :subject, class_name: 'Granted::ReadGrant' has_many :write_users, source: :grantee, source_type: 'User', through: :write_grants has_many :read_users, source: :grantee, source_type: 'User', through: :read_grants has_many :all_users, source: :grantee, source_type: 'User', through: :grants, uniq: true attr_accessible :write_users_attributes, :read_users_attributes accepts_nested_attributes_for :write_users, :read_users end class User < ActiveRecord::Base has_many :grants, as: :grantee, class_name: 'Granted::Grant', dependent: :destroy has_many :write_grants, as: :grantee, class_name: 'Granted::WriteGrant' has_many :read_grants, as: :grantee, class_name: 'Granted::ReadGrant' has_many :writeable_documents, source: :subject, source_type: 'Document', through: :write_grants has_many :readable_documents, source: :subject, source_type: 'Document', through: :read_grants has_many :all_documents, source: :subject, source_type: 'Document', through: :grants, uniq: true # It does not do this yet, but hopefully soon :) # attr_accessible :writeable_documents_attributes, :readable_documents_attributes # accepts_nested_attributes_for :writeable_documents, :readable_documents end
First it creates STI classes that inherit from Granted::Grant
, one for each right you defined as grantable (e.g. ReadGrant, WriteGrant). It then creates the appropriate has_many
relations to both User
and Document
, so that they can be connected with a Grant
instance. So you have all the access control available via normal active record associations (reading and writing).
PSA: You can only grant/revoke rights via the grantee side at the moment, the other direction is not yet implemented:
document.read_users << my_user # Works my_user.readable_documents << document # Doesn't work yet
Granting/revoking rights¶ ↑
So now that you know how querying grants/rights work, you might wonder how you give or revoke certain access rights to a user and a document. Consider this familiar snippet of code:
class Document < ActiveRecord::Base include Granted::ForGranted grantable :read, :write, to: User end
It does not only create the associations, it also creates the grant
and revoke
methods on User
and Document
. They return a convenient little object (Grant::Granter, if you’re curious). You can grant/revoke access rights using Users or Documents as a starting point, it’s all the same:
# Both ways to grant are identical my_user.grant(:read).on(my_document) my_document.grant(:read).to(my_user) # Both ways to revoke are identical my_user.revoke(:read).on(my_document) my_document.revoke(:read).from(my_user) # Clever: even weird grammatic yields identic results my_user.on(my_document).revoke(:read) my_document.from(:my_user).revoke(:read) # This is what the grant/revoke methods do: Granted::Granter.new.grant(:read).on(my_document).to(my_user) Granted::Granter.new.revoke(:read).on(my_document).from(my_user)
Interedasting things¶ ↑
You can use arrays or single objects in grantable
both as access rights and grantees:
class Document < ActiveRecord::Base include Granted::ForGranted grantable :read, to: [User, Editor] grantable :update, :destroy, to: [Editor] end my_document.grant(:read, :write).to(my_user)