diff --git a/README.md b/README.md index 68cf56b..b962254 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,25 @@ user.permitted_documents.with_permission ["viewer", "editor"] ``` +The inverse relationship is also possible by specifying `can_grant_permissions_to` on objects: + +``` +class Document < ApplicationRecord + include Caber::Object + can_grant_permissions_to User +end + +document.permitted_users +# => all users with any permission + +document.permitted_users.with_permission "viewer" +# => all users with viewer permission + +document.permitted_users.with_permission ["viewer", "editor"] +# => all users with viewer or editor permission + +``` + ## Development After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. diff --git a/app/models/concerns/caber/object.rb b/app/models/concerns/caber/object.rb index ee8df20..849b199 100644 --- a/app/models/concerns/caber/object.rb +++ b/app/models/concerns/caber/object.rb @@ -2,7 +2,12 @@ module Caber::Object extend ActiveSupport::Concern included do + has_many :caber_relations, as: :object, class_name: "Caber::Relation" scope :with_permission, ->(permission) { where("caber_relations.permission": permission) } + + def self.can_grant_permissions_to(model) + has_many :"permitted_#{model.name.pluralize.parameterize}", through: :caber_relations, source: :subject, source_type: model.name + end end def grant_permission_to(permission, subject) diff --git a/app/models/concerns/caber/subject.rb b/app/models/concerns/caber/subject.rb index a3baedc..30822da 100644 --- a/app/models/concerns/caber/subject.rb +++ b/app/models/concerns/caber/subject.rb @@ -3,6 +3,7 @@ module Caber::Subject included do has_many :caber_relations, as: :subject, class_name: "Caber::Relation" + scope :with_permission, ->(permission) { where("caber_relations.permission": permission) } def self.can_have_permissions_on(model) has_many :"permitted_#{model.name.pluralize.parameterize}", through: :caber_relations, source: :object, source_type: model.name diff --git a/spec/dummy/app/models/document.rb b/spec/dummy/app/models/document.rb index 78bd6e4..3a1675a 100644 --- a/spec/dummy/app/models/document.rb +++ b/spec/dummy/app/models/document.rb @@ -1,3 +1,5 @@ class Document < ApplicationRecord include Caber::Object + + can_grant_permissions_to User end diff --git a/spec/models/caber/relation_spec.rb b/spec/models/caber/relation_spec.rb index 8df4757..cfea283 100644 --- a/spec/models/caber/relation_spec.rb +++ b/spec/models/caber/relation_spec.rb @@ -37,6 +37,14 @@ it "gives Alice a list of objects she can view" do expect(alice.permitted_documents.with_permission("viewer")).to include object end + + it "includes Alice in a list of permitted users for the object" do + expect(object.permitted_users).to include alice + end + + it "includes Alice in a list of users with viewer permission for the object" do + expect(object.permitted_users.with_permission("viewer")).to include alice + end end context "with multiple objects" do @@ -75,6 +83,10 @@ it "gives Alice a list of objects she can view or own" do expect(alice.permitted_documents.with_permission(["viewer", "owner"])).to include object end + + it "includes Alice in a list of users with viewer or owner permission for the object" do + expect(object.permitted_users.with_permission(["viewer", "owner"])).to include alice + end end context "when anyone can view a object" do