scoped_rolify 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/CHANGELOG.md +14 -0
- data/README.md +65 -0
- data/lib/scoped_rolify/finders.rb +15 -7
- data/lib/scoped_rolify/policy.rb +1 -1
- data/lib/scoped_rolify/role.rb +37 -3
- data/lib/scoped_rolify/version.rb +1 -1
- data/spec/scoped_rolify/finders_spec.rb +29 -9
- data/spec/scoped_rolify/role_spec.rb +35 -1
- data/spec/spec_helper.rb +8 -3
- data/spec/support/adapters/active_record.rb +11 -2
- data/spec/support/data.rb +3 -7
- data/spec/support/schema.rb +5 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6ccae7235a31e93ee0b08d01aa8f6e8b15289389
|
4
|
+
data.tar.gz: 2e9e9177bf449409e77178e480fc7f6a3808d222
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ddb035951cee915f2c3dc380818885b82c1d34fab18746ae375e37a9a20bbfb1f086fd97f092df2e2696cfcd249526af0fd1d4dc1b132ef14bee05200c09888f
|
7
|
+
data.tar.gz: 158e81b64ab7521155e2a751b5028053e531b327837ee7d12b4273a92dc66647b2737c4db330a0695532e4b10a02a3e8a55c75fe450ecd4eefa5dfae2ebc9437
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.0.0-
|
1
|
+
ruby-2.0.0-p451
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -61,6 +61,71 @@ You can't play with none persisted object
|
|
61
61
|
|
62
62
|
Method ```with_any_scoped_role``` return an ```ActiveRecord::Relation``` of all users with all roles asked for one resource
|
63
63
|
|
64
|
+
## Root Resource
|
65
|
+
|
66
|
+
In some case you can add right on child resource instead of parent resource, the problem is you haven't access directly to objects throught Parent resource, for exemple
|
67
|
+
|
68
|
+
You grant user on specifc Forum, user.add_role(:moderator, Forum.first) the Forum have one Category, if you want get all moderators of this Category you can't. This modification make this possible.
|
69
|
+
|
70
|
+
moderator_john = User.new
|
71
|
+
moderator_jane = User.new
|
72
|
+
|
73
|
+
geek_world = Category.new
|
74
|
+
|
75
|
+
geek_forum = Forum.new
|
76
|
+
nerd_forum = Forum.new
|
77
|
+
|
78
|
+
class Forum < ActiveRecord::Base
|
79
|
+
belongs_to :category
|
80
|
+
|
81
|
+
def root_resource
|
82
|
+
:category
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class Category < ActiveRecord::Base
|
87
|
+
has_many :forums
|
88
|
+
end
|
89
|
+
|
90
|
+
geek_world.forums << geek_forum
|
91
|
+
geek_world.forums << nerd_forum
|
92
|
+
|
93
|
+
moderator_john.add_role(:moderator, nerd_forum)
|
94
|
+
moderator_jane.add_role(:moderator, geek_forum)
|
95
|
+
|
96
|
+
For grab all moderators of this Category
|
97
|
+
|
98
|
+
User.with_scoped_role :moderator, geek_world, root=true
|
99
|
+
|
100
|
+
## Roadmap
|
101
|
+
|
102
|
+
Refactoring on root resource API
|
103
|
+
|
104
|
+
Change
|
105
|
+
|
106
|
+
User.with_scoped_role :moderator, geek_world, root=true
|
107
|
+
|
108
|
+
to
|
109
|
+
|
110
|
+
User.with_scoped_role :moderator, geek_world, scope: :forum
|
111
|
+
|
112
|
+
And change
|
113
|
+
|
114
|
+
class Forum < ActiveRecord::Base
|
115
|
+
belongs_to :category
|
116
|
+
|
117
|
+
def root_resource
|
118
|
+
:category
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
to
|
123
|
+
|
124
|
+
class Forum < ActiveRecord::Base
|
125
|
+
belongs_to :category
|
126
|
+
scoped_roles belongs_to: :category
|
127
|
+
end
|
128
|
+
|
64
129
|
## Contributing
|
65
130
|
|
66
131
|
1. Fork it ( http://github.com/<my-github-username>/scoped_rolify/fork )
|
@@ -1,26 +1,34 @@
|
|
1
1
|
module Rolify
|
2
2
|
module Finders
|
3
3
|
|
4
|
-
def with_scoped_role role_name, resource
|
4
|
+
def with_scoped_role role_name, resource, root_only=false
|
5
5
|
ScopedRolify::Policy.new(self, resource).check_persisted!
|
6
|
-
self.joins(:roles).where(rolify_constraints(role_name, resource))
|
6
|
+
self.joins(:roles).where(rolify_constraints(role_name, resource, root_only))
|
7
7
|
end
|
8
8
|
|
9
|
-
def with_any_scoped_role role_names, resource
|
9
|
+
def with_any_scoped_role role_names, resource, root_only=false
|
10
10
|
ScopedRolify::Policy.new(self, resource).check_persisted!
|
11
|
-
self.joins(:roles).where(rolify_constraints(role_names, resource))
|
11
|
+
self.joins(:roles).where(rolify_constraints(role_names, resource, root_only))
|
12
12
|
end
|
13
13
|
|
14
|
-
def rolify_constraints role_names, resource
|
14
|
+
def rolify_constraints role_names, resource, root_only=false
|
15
15
|
raise 'You should give somes role' if role_names.nil? or (role_names||[]).empty?
|
16
|
+
|
16
17
|
ScopedRolify::Policy.new(self, resource).check_persisted!
|
18
|
+
|
17
19
|
table = Arel::Table.new(:roles)
|
20
|
+
|
18
21
|
[].tap do |_constraints|
|
19
22
|
Array.wrap(role_names).each do |name|
|
20
23
|
_constraints << [].tap do |_constraint|
|
21
24
|
_constraint << table[:name].eq(name)
|
22
|
-
|
23
|
-
|
25
|
+
if root_only
|
26
|
+
_constraint << table[:root_resource_type].eq(resource.class.name)
|
27
|
+
_constraint << table[:root_resource_id].eq(resource.id)
|
28
|
+
else
|
29
|
+
_constraint << table[:resource_type].eq(resource.class.name)
|
30
|
+
_constraint << table[:resource_id].eq(resource.id)
|
31
|
+
end
|
24
32
|
end.reduce(:and)
|
25
33
|
end
|
26
34
|
end.reduce(:or)
|
data/lib/scoped_rolify/policy.rb
CHANGED
@@ -8,7 +8,7 @@ module ScopedRolify
|
|
8
8
|
|
9
9
|
def check_persisted!
|
10
10
|
check!
|
11
|
-
raise
|
11
|
+
raise PersistenceError, "You should ask on persisted resource" unless self.resource.persisted?
|
12
12
|
end
|
13
13
|
|
14
14
|
end
|
data/lib/scoped_rolify/role.rb
CHANGED
@@ -12,25 +12,59 @@ module Rolify
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def has_role?(role_name, resource = nil)
|
15
|
+
root_resource = resource.respond_to?(:root_resource) ? resource.send(resource.root_resource) : nil
|
15
16
|
if self.new_record?
|
16
|
-
self.roles.detect { |r| r.name.to_s == role_name.to_s && (r.resource == resource || resource.nil?) }
|
17
|
+
self.roles.detect { |r| r.name.to_s == role_name.to_s && (r.resource == resource || resource.nil?) && (r.root_resource == root_resource || root_resource.nil?) }
|
17
18
|
else
|
18
|
-
self.class.adapter.where(self.roles, :
|
19
|
+
self.class.adapter.where(self.roles, name: role_name, resource: resource, root_resource: root_resource)
|
19
20
|
end.present?
|
20
21
|
end
|
21
22
|
|
22
23
|
private
|
23
24
|
|
24
25
|
def add_resourced_role(role_name, resource)
|
26
|
+
root_resource = resource.respond_to?(:root_resource) ? resource.send(resource.root_resource) : nil
|
25
27
|
if self.new_record?
|
26
|
-
self.class.adapter.role_class.new(name: role_name, resource: resource).tap do |role|
|
28
|
+
role = self.class.adapter.role_class.new(name: role_name, resource: resource, root_resource: root_resource).tap do |role|
|
27
29
|
self.roles << role
|
28
30
|
if Rolify.dynamic_shortcuts and !self.respond_to?("is_#{role_name}?".to_sym)
|
29
31
|
self.class.define_dynamic_method(role_name, resource)
|
30
32
|
end
|
31
33
|
end
|
32
34
|
else
|
35
|
+
role = add_role_with_root(role_name, resource, root_resource)
|
36
|
+
end
|
37
|
+
add_role_to_resource(role)
|
38
|
+
load_dynamic_shortcuts(role_name, resource)
|
39
|
+
role
|
40
|
+
end
|
41
|
+
|
42
|
+
def load_dynamic_shortcuts(role_name, resource)
|
43
|
+
if Rolify.dynamic_shortcuts and !self.respond_to?("is_#{role_name}?".to_sym)
|
44
|
+
self.class.define_dynamic_method(role_name, resource)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def add_role_to_resource(role)
|
49
|
+
self.roles << role unless self.roles.include?(role)
|
50
|
+
end
|
51
|
+
|
52
|
+
def add_role_with_root(role_name, resource, root_resource)
|
53
|
+
unless root_resource
|
33
54
|
add_role(role_name, resource)
|
55
|
+
else
|
56
|
+
conditions = {
|
57
|
+
name: role_name.to_s,
|
58
|
+
resource_type: resource.class.name,
|
59
|
+
resource_id: resource.id,
|
60
|
+
}
|
61
|
+
if root_resource
|
62
|
+
conditions.merge!({ root_resource_type: (root_resource.is_a?(Class) ? root_resource.to_s : root_resource.class.name) })
|
63
|
+
unless root_resource.is_a?(Class) # Useless for the moment (Already false)
|
64
|
+
conditions.merge!({ root_resource_id: root_resource.id })
|
65
|
+
end
|
66
|
+
end
|
67
|
+
self.class.adapter.role_class.where(conditions).first_or_create
|
34
68
|
end
|
35
69
|
end
|
36
70
|
|
@@ -1,28 +1,48 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Rolify::Finders do
|
4
|
-
let(:resource) { Forum.first }
|
4
|
+
let(:resource) { Forum.where(name: 'forum 1').first }
|
5
5
|
let(:admin) { User.where(login: 'admin').first }
|
6
6
|
|
7
7
|
before { admin.add_role(:admin, resource) }
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
it { expect { subject.with_scoped_role(:admin, Forum) }.to raise_error InstanceResourceError }
|
12
|
-
it { expect { subject.with_scoped_role(:admin, resource) }.to_not raise_error }
|
9
|
+
it { expect { User.with_scoped_role(:admin, Forum) }.to raise_error InstanceResourceError }
|
10
|
+
it { expect { User.with_scoped_role(:admin, resource) }.to_not raise_error }
|
13
11
|
|
14
12
|
context 'regular way' do
|
15
|
-
it {
|
13
|
+
it { User.with_scoped_role(:admin, resource).should eq([admin]) }
|
16
14
|
end
|
17
15
|
|
18
16
|
context '#with_any_scoped_role' do
|
19
|
-
let(:moderator) {
|
17
|
+
let(:moderator) { User.where(login: 'moderator').first }
|
20
18
|
before { moderator.add_role(:moderator, resource) }
|
21
19
|
it do
|
22
|
-
expect(
|
20
|
+
expect(User.with_any_scoped_role([:admin, :moderator], resource)).to be_a(ActiveRecord::Relation)
|
23
21
|
end
|
24
22
|
it do
|
25
|
-
expect(
|
23
|
+
expect(User.with_any_scoped_role([:admin, :moderator], resource).to_a).to eq([admin, moderator])
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'with root resource' do
|
28
|
+
let(:root_resource) { Category.where(name: 'category 1').first }
|
29
|
+
let(:another_resource) { Forum.where(name: 'forum 2').first }
|
30
|
+
let(:super_admin) { User.where(login: 'super admin').first }
|
31
|
+
let(:moderator) { User.where(login: 'moderator').first }
|
32
|
+
|
33
|
+
before do
|
34
|
+
root_resource.forums << resource
|
35
|
+
root_resource.forums << another_resource
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'add role to user' do
|
39
|
+
before do
|
40
|
+
super_admin.add_scope_role(:super_admin, resource)
|
41
|
+
moderator.add_scope_role(:super_admin, another_resource)
|
42
|
+
end
|
43
|
+
|
44
|
+
it('should retreive super_admin') { expect(User.with_scoped_role(:super_admin, resource).to_a).to eq([super_admin]) }
|
45
|
+
it('should retreive all user for Category') { expect(User.with_scoped_role(:super_admin, root_resource, true).to_a).to eq([super_admin, moderator]) }
|
26
46
|
end
|
27
47
|
end
|
28
48
|
end
|
@@ -17,6 +17,7 @@ describe Rolify::Role do
|
|
17
17
|
|
18
18
|
it { expect { subject.add_scope_role(:admin, resource) }.to_not raise_error }
|
19
19
|
it { should have_role :admin, resource }
|
20
|
+
it { expect(User.with_scoped_role(:admin, resource).to_a).to eq([user]) }
|
20
21
|
end
|
21
22
|
|
22
23
|
context 'new record way' do
|
@@ -33,5 +34,38 @@ describe Rolify::Role do
|
|
33
34
|
end
|
34
35
|
end
|
35
36
|
|
36
|
-
|
37
|
+
context 'with root resource' do
|
38
|
+
context 'persisted way' do
|
39
|
+
let(:root_resource) { Category.first }
|
37
40
|
|
41
|
+
before { root_resource.forums << resource }
|
42
|
+
|
43
|
+
context 'add role to user' do
|
44
|
+
before { subject.add_scope_role(:admin, resource) }
|
45
|
+
it('should retreive user') do
|
46
|
+
expect(
|
47
|
+
User.joins(:roles).where(
|
48
|
+
Role.where(name: :admin, resource_type: 'Forum', resource_id: resource.id,
|
49
|
+
root_resource_type: 'Category', root_resource_id: root_resource.id).arel.constraints.first
|
50
|
+
).to_a
|
51
|
+
).to eq([subject])
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'unpersisted way' do
|
57
|
+
let(:root_resource) { Category.new(name: 'UnCategoized') }
|
58
|
+
let(:resource) { Forum.new(name: 'forum 42') }
|
59
|
+
let(:user) { User.new(login: 'John Doe') }
|
60
|
+
|
61
|
+
before { root_resource.forums << resource }
|
62
|
+
|
63
|
+
it { expect(root_resource.forums).to eq([resource]) }
|
64
|
+
|
65
|
+
context 'add role to user' do
|
66
|
+
before { user.add_scope_role(:admin, resource) }
|
67
|
+
it { should have_role :admin, resource }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -10,9 +10,14 @@ Coveralls.wear!
|
|
10
10
|
ENV['ADAPTER'] ||= 'active_record'
|
11
11
|
|
12
12
|
load File.dirname(__FILE__) + "/support/adapters/#{ENV['ADAPTER']}.rb"
|
13
|
-
load File.dirname(__FILE__) + '/support/data.rb'
|
14
13
|
|
15
|
-
RSpec.configure do |
|
16
|
-
|
14
|
+
RSpec.configure do |config|
|
15
|
+
config.filter_run focused: true
|
16
|
+
config.run_all_when_everything_filtered = true
|
17
|
+
|
18
|
+
config.before(:each) do
|
19
|
+
[ User, Role, Forum, Category].each &:destroy_all
|
20
|
+
load File.dirname(__FILE__) + '/support/data.rb'
|
21
|
+
end
|
17
22
|
end
|
18
23
|
|
@@ -13,11 +13,20 @@ end
|
|
13
13
|
class Role < ActiveRecord::Base
|
14
14
|
has_and_belongs_to_many :users, join_table: :users_roles
|
15
15
|
belongs_to :resource, polymorphic: true
|
16
|
+
belongs_to :root_resource, polymorphic: true
|
16
17
|
|
17
18
|
extend Rolify::Adapter::Scopes
|
18
19
|
end
|
19
20
|
|
20
|
-
# Resources classes
|
21
21
|
class Forum < ActiveRecord::Base
|
22
|
-
|
22
|
+
belongs_to :category
|
23
|
+
|
24
|
+
def root_resource
|
25
|
+
:category
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Resources classes
|
30
|
+
class Category < ActiveRecord::Base
|
31
|
+
has_many :forums
|
23
32
|
end
|
data/spec/support/data.rb
CHANGED
@@ -1,10 +1,6 @@
|
|
1
|
-
# Users
|
2
|
-
User.destroy_all
|
3
1
|
User.create login: 'admin'
|
2
|
+
User.create login: 'super admin'
|
4
3
|
User.create login: 'moderator'
|
5
|
-
|
6
|
-
# Roles
|
7
|
-
Role.destroy_all
|
8
|
-
|
9
|
-
# Resources
|
10
4
|
Forum.create name: 'forum 1'
|
5
|
+
Forum.create name: 'forum 2'
|
6
|
+
Category.create name: 'category 1'
|
data/spec/support/schema.rb
CHANGED
@@ -8,6 +8,7 @@ ActiveRecord::Schema.define do
|
|
8
8
|
create_table(:roles) do |t|
|
9
9
|
t.string :name
|
10
10
|
t.references :resource, polymorphic: true
|
11
|
+
t.references :root_resource, polymorphic: true
|
11
12
|
t.timestamps
|
12
13
|
end
|
13
14
|
|
@@ -18,6 +19,10 @@ ActiveRecord::Schema.define do
|
|
18
19
|
|
19
20
|
create_table(:forums) do |t|
|
20
21
|
t.string :name
|
22
|
+
t.integer :category_id
|
21
23
|
end
|
22
24
|
|
25
|
+
create_table(:categories) do |t|
|
26
|
+
t.string :name
|
27
|
+
end
|
23
28
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scoped_rolify
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joel AZEMAR
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-03-
|
11
|
+
date: 2014-03-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rolify
|
@@ -133,7 +133,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
133
133
|
version: '0'
|
134
134
|
requirements: []
|
135
135
|
rubyforge_project:
|
136
|
-
rubygems_version: 2.
|
136
|
+
rubygems_version: 2.2.2
|
137
137
|
signing_key:
|
138
138
|
specification_version: 4
|
139
139
|
summary: This is a monkey patch of rolify
|