granted 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.markdown +23 -22
- data/VERSION +1 -1
- data/granted.gemspec +2 -2
- data/lib/granted/granter.rb +1 -1
- data/lib/granted/modules/grantee.rb +16 -0
- data/spec/models/grant_spec.rb +100 -86
- metadata +3 -3
data/README.markdown
CHANGED
@@ -1,27 +1,23 @@
|
|
1
|
+
# Dead easy rails permissions [](http://badge.fury.io/rb/granted) [](https://travis-ci.org/jayniz/granted)
|
2
|
+
|
3
|
+
Installation is as easy as 1,2,3:
|
4
|
+
<table>
|
5
|
+
<tr>
|
6
|
+
<td align="center"><h1>1.</h1>Add to Gemfile:<pre>gem 'granted'
|
7
|
+
</pre></td>
|
8
|
+
<td align="center"><h1>2.</h1>Add to Rakefile: <pre>require 'granted/tasks'
|
9
|
+
</pre></td>
|
10
|
+
<td align="center"><h1>3.</h1>Create grants migration: <pre align="left">rake granted:create_migration
|
11
|
+
rake db:migrate</pre></td>
|
12
|
+
</tr>
|
13
|
+
</table>
|
14
|
+
|
1
15
|
This gem lets you define arbitrary permissions on a per object level (as opposed to roles).
|
2
16
|
They are implemented purely as active record associations and hence easy to understand.
|
3
17
|
Check out this readme on how to grant read/write permissions on individual documents to
|
4
18
|
individual users. This is a [moviepilot.com](http://moviepilot.com) project licensed
|
5
|
-
[MIT](LICENSE.txt).
|
6
|
-
|
7
|
-
[](https://travis-ci.org/jayniz/granted)
|
8
|
-
|
9
|
-
# Quickstart
|
10
|
-
|
11
|
-
Install with bundler:
|
12
|
-
|
13
|
-
gem 'granted'
|
19
|
+
[MIT](LICENSE.txt). And now, code:
|
14
20
|
|
15
|
-
Add to Rakefile:
|
16
|
-
|
17
|
-
require 'granted/tasks'
|
18
|
-
|
19
|
-
Create the migration for the grants table:
|
20
|
-
|
21
|
-
rake granted:create_migration
|
22
|
-
rake db:migrate
|
23
|
-
|
24
|
-
And then:
|
25
21
|
|
26
22
|
```ruby
|
27
23
|
# Let's grant a user access to a document
|
@@ -39,6 +35,10 @@ user.readable_documents.count
|
|
39
35
|
# Let's count all documents a user has any access to
|
40
36
|
user.all_documents.count
|
41
37
|
|
38
|
+
# List the rights a user has to a certain document
|
39
|
+
user.grants_for(document)
|
40
|
+
=> [:read, :write]
|
41
|
+
|
42
42
|
# Define the things we took for granted (scuse me) above
|
43
43
|
class Document
|
44
44
|
include Granted::ForGranted
|
@@ -95,8 +95,9 @@ class User < ActiveRecord::Base
|
|
95
95
|
has_many :readable_documents, source: :subject, source_type: 'Document', through: :read_grants
|
96
96
|
has_many :all_documents, source: :subject, source_type: 'Document', through: :grants, uniq: true
|
97
97
|
|
98
|
-
|
99
|
-
|
98
|
+
# It does not do this yet, but hopefully soon :)
|
99
|
+
# attr_accessible :writeable_documents_attributes, :readable_documents_attributes
|
100
|
+
# accepts_nested_attributes_for :writeable_documents, :readable_documents
|
100
101
|
end
|
101
102
|
```
|
102
103
|
|
@@ -146,7 +147,7 @@ my_document.revoke(:read).from(my_user)
|
|
146
147
|
|
147
148
|
# Clever: even weird grammatic yields identic results
|
148
149
|
my_user.on(my_document).revoke(:read)
|
149
|
-
my_document.
|
150
|
+
my_document.from(:my_user).revoke(:read)
|
150
151
|
|
151
152
|
# This is what the grant/revoke methods do:
|
152
153
|
Granted::Granter.new.grant(:read).on(my_document).to(my_user)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/granted.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "granted"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Jannis Hermanns"]
|
12
|
-
s.date = "2013-08-
|
12
|
+
s.date = "2013-08-08"
|
13
13
|
s.description = "Takes care of defining what actions one model is allowed to do with another model."
|
14
14
|
s.email = "jannis@gmail.com"
|
15
15
|
s.extra_rdoc_files = [
|
data/lib/granted/granter.rb
CHANGED
@@ -14,5 +14,21 @@ module Granted
|
|
14
14
|
.rights(rights)
|
15
15
|
.to(self)
|
16
16
|
end
|
17
|
+
|
18
|
+
def grants_for(subject)
|
19
|
+
grants.subject(subject).map do |g|
|
20
|
+
grant_class_name_to_symbol(g.type)
|
21
|
+
end.sort
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def grant_class_name_to_symbol(c)
|
27
|
+
# A class name could be Granted::ReadGrant
|
28
|
+
# and we want to make :read out of it
|
29
|
+
c.underscore[8..-1] # Remove granted/ prefix
|
30
|
+
.chomp('_grant') # Remove trailing _grant
|
31
|
+
.to_sym
|
32
|
+
end
|
17
33
|
end
|
18
34
|
end
|
data/spec/models/grant_spec.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'spec_helper.rb'
|
2
2
|
|
3
3
|
describe Granted::Grant do
|
4
|
+
|
4
5
|
before(:all) do
|
5
6
|
@alfred = User.create name: 'Alfred'
|
6
7
|
@bruce = User.create name: 'Bruce'
|
@@ -10,105 +11,118 @@ describe Granted::Grant do
|
|
10
11
|
Granted::WriteGrant.create! grantee: @alfred, subject: @alfreds
|
11
12
|
end
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
14
|
+
describe "granting/revoking rights" do
|
15
|
+
describe "using a grantee as the starting point" do
|
16
|
+
it "lists Alfred's document as one of his writeable documents" do
|
17
|
+
@alfred.writeable_documents.count.should == 1
|
18
|
+
end
|
19
|
+
|
20
|
+
it "Alfred has no readable documents" do
|
21
|
+
@alfred.readable_documents.count.should == 0
|
22
|
+
end
|
23
|
+
|
24
|
+
it "Bruce has no documents at all" do
|
25
|
+
@bruce.all_documents.count.should == 0
|
26
|
+
end
|
27
|
+
|
28
|
+
it "grant read access on Alfred's document to Bruce" do
|
29
|
+
Granted::Grant.destroy_all
|
30
|
+
expect{
|
31
|
+
@bruce.grant(:read).on(@alfreds)
|
32
|
+
}.to change(@bruce.readable_documents, :count).from(0).to(1)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "grant all access on Alfred's document to Bruce" do
|
36
|
+
Granted::Grant.destroy_all
|
37
|
+
expect{
|
38
|
+
@bruce.grant(:read, :write, :destroy).on(@alfreds)
|
39
|
+
}.to change(Grant, :count).from(0).to(3)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "revoke write access on Alfred's document from Alfred" do
|
43
|
+
expect{
|
44
|
+
@alfred.revoke(:write).on(@alfreds)
|
45
|
+
}.to change(@alfred.writeable_documents, :count).from(1).to(0)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "returns Alfred only once even though he has multiple rights" do
|
49
|
+
Granted::DestroyGrant.create(subject: @alfreds, grantee: @alfred)
|
50
|
+
@alfred.grants.count.should == 2
|
51
|
+
@alfred.all_documents.count.should == 1
|
52
|
+
end
|
44
53
|
end
|
45
54
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
55
|
+
describe "using a subject as the starting point" do
|
56
|
+
it "lists Alfred's document as one of his writeable documents" do
|
57
|
+
@alfreds.write_users.count.should == 1
|
58
|
+
end
|
59
|
+
|
60
|
+
it "grant read access on Alfred's document to Bruce" do
|
61
|
+
Granted::Grant.destroy_all
|
62
|
+
expect{
|
63
|
+
@alfreds.grant(:read).to(@bruce)
|
64
|
+
}.to change(@alfreds.read_users, :count).from(0).to(1)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "grant all access on Alfred's document to Bruce" do
|
68
|
+
Granted::Grant.destroy_all
|
69
|
+
expect{
|
70
|
+
@alfreds.grant(:read, :write, :destroy).to(@bruce)
|
71
|
+
}.to change(Grant, :count).from(0).to(3)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "revoke write access on Alfred's document from Alfred" do
|
75
|
+
expect{
|
76
|
+
@alfreds.revoke(:write).from(@alfred)
|
77
|
+
}.to change(@alfreds.write_users, :count).from(1).to(0)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "returns Alfreds only once even though he has multiple rights" do
|
81
|
+
Granted::DestroyGrant.create(subject: @alfreds, grantee: @alfred)
|
82
|
+
@alfreds.grants.count.should == 2
|
83
|
+
@alfreds.all_users.count.should == 1
|
84
|
+
end
|
50
85
|
end
|
51
|
-
end
|
52
86
|
|
53
|
-
|
54
|
-
|
55
|
-
|
87
|
+
describe "granting/revoking rights: rails association style" do
|
88
|
+
it "adds a grant via subject's <<" do
|
89
|
+
expect{
|
90
|
+
@bruces.read_users << @alfred
|
91
|
+
@bruces.save!
|
92
|
+
}.to change(@alfred.readable_documents, :count).from(0).to(1)
|
93
|
+
end
|
94
|
+
|
95
|
+
it "adds a grant via grantee's <<" do
|
96
|
+
expect{
|
97
|
+
@alfred.readable_documents << @bruces
|
98
|
+
@alfred.save!
|
99
|
+
}.to change(@bruces.read_users, :count).by(1)
|
100
|
+
end
|
56
101
|
end
|
57
102
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
it "grant all access on Alfred's document to Bruce" do
|
66
|
-
Granted::Grant.destroy_all
|
67
|
-
expect{
|
68
|
-
@alfreds.grant(:read, :write, :destroy).to(@bruce)
|
69
|
-
}.to change(Grant, :count).from(0).to(3)
|
70
|
-
end
|
103
|
+
describe "removing grant objects" do
|
104
|
+
it "when subject is deleted" do
|
105
|
+
expect{
|
106
|
+
@alfreds.destroy
|
107
|
+
}.to change(Grant, :count).by(-1)
|
108
|
+
end
|
71
109
|
|
72
|
-
|
110
|
+
it "when grantee is deleted" do
|
73
111
|
expect{
|
74
|
-
@
|
75
|
-
}.to change(
|
76
|
-
|
77
|
-
|
78
|
-
it "returns Alfreds only once even though he has multiple rights" do
|
79
|
-
Granted::DestroyGrant.create(subject: @alfreds, grantee: @alfred)
|
80
|
-
@alfreds.grants.count.should == 2
|
81
|
-
@alfreds.all_users.count.should == 1
|
112
|
+
@alfred.destroy
|
113
|
+
}.to change(Grant, :count).by(-1)
|
114
|
+
end
|
82
115
|
end
|
83
116
|
end
|
84
117
|
|
85
|
-
|
86
|
-
it "
|
87
|
-
|
88
|
-
@bruces.read_users << @alfred
|
89
|
-
@bruces.save!
|
90
|
-
}.to change(@alfred.readable_documents, :count).from(0).to(1)
|
118
|
+
describe "reading grants" do
|
119
|
+
it "alfred should have write grants to his document" do
|
120
|
+
@alfred.grants_for(@alfreds).should == [:write]
|
91
121
|
end
|
92
122
|
|
93
|
-
it "
|
94
|
-
|
95
|
-
|
96
|
-
@alfred.save!
|
97
|
-
}.to change(@bruces.read_users, :count).by(1)
|
123
|
+
it "alfread should have all grants for his document" do
|
124
|
+
@alfred.grant(:destroy, :read).on(@alfreds)
|
125
|
+
@alfred.grants_for(@alfreds).should == [:destroy, :read, :write]
|
98
126
|
end
|
99
127
|
end
|
100
|
-
|
101
|
-
context "removing grant objects" do
|
102
|
-
it "when subject is deleted" do
|
103
|
-
expect{
|
104
|
-
@alfreds.destroy
|
105
|
-
}.to change(Grant, :count).by(-1)
|
106
|
-
end
|
107
|
-
|
108
|
-
it "when grantee is deleted" do
|
109
|
-
expect{
|
110
|
-
@alfred.destroy
|
111
|
-
}.to change(Grant, :count).by(-1)
|
112
|
-
end
|
113
|
-
end
|
114
128
|
end
|
metadata
CHANGED
@@ -2,14 +2,14 @@
|
|
2
2
|
name: granted
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.2.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Jannis Hermanns
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-08-
|
12
|
+
date: 2013-08-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -338,7 +338,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
338
338
|
- !ruby/object:Gem::Version
|
339
339
|
segments:
|
340
340
|
- 0
|
341
|
-
hash:
|
341
|
+
hash: -1869263062967453258
|
342
342
|
version: '0'
|
343
343
|
none: false
|
344
344
|
required_rubygems_version: !ruby/object:Gem::Requirement
|