rolify 4.0.0 → 4.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5b9f204d757588d80887b2193a4eb9ea1b0fd471
4
- data.tar.gz: 97030122590f294b06b595af6edc1dec44d13176
3
+ metadata.gz: edae47a21706d1859520df05876acf68d95c0d48
4
+ data.tar.gz: 09dbd84321d04321d1ef889db0911fa86f1ccbe4
5
5
  SHA512:
6
- metadata.gz: 75dc73295700924357b77c4359f43939c3e44d0857015f7f30dc26e4f06c99e1667f7767977e1a9bb332028ee177cab6ba860538a4d1dd640da5175246989a68
7
- data.tar.gz: 01e0a0874a8ded544155535b4b9cff68f643b20fce6e71e21615ef7c4a5f7ca47b68e4b6ea9de34ec13af5e51bce6fb781f52351483ede4e05e152f21a662c5e
6
+ metadata.gz: 910c97443cd78a0386a36f2d6645708c7f6eadf5b84815ca51f8b1cbd39f4a6e1236a16688c37ef99a48234deb44a25c684e7852ce146f7d0e75cc22817a841c
7
+ data.tar.gz: 4525bec755d35bb470d364088bdfe2c7f2a39b61cf140944363518ed5626de9f4c438c088d432002a7b41edc750dccc7a032b94f76d075d068f0770b762223cb
data/.gitignore CHANGED
@@ -8,3 +8,4 @@ coverage/*
8
8
  log*/*
9
9
  .rbx/*
10
10
  .rspec
11
+ *.swp
@@ -1,3 +1,9 @@
1
+ = 4.1.0 (Aug 04, 2015)
2
+ * added `without_role` method for resources and classes
3
+ * fix `has_role?` with :any and an unsaved user
4
+ * rename the `with_role` method on a resource to `find_as`
5
+ * add a strict parameter to check only roles that were set without supers.
6
+
1
7
  = 4.0.0 (Feb 12, 2015)
2
8
  * Increasing version number to 4.0.0 for semantic versioning since `has_role` was removed in 3.5.0
3
9
  * Fix spec to pass.
data/README.md CHANGED
@@ -1,12 +1,11 @@
1
1
  # rolify [![Gem Version](https://badge.fury.io/rb/rolify.svg)](http://badge.fury.io/rb/rolify) [![build status](https://secure.travis-ci.org/RolifyCommunity/rolify.png)](http://travis-ci.org/RolifyCommunity/rolify) [![Dependency Status](https://gemnasium.com/RolifyCommunity/rolify.svg)](https://gemnasium.com/RolifyCommunity/rolify) [![Code Climate](https://codeclimate.com/github/RolifyCommunity/rolify.png)](https://codeclimate.com/github/RolifyCommunity/rolify) [![Coverage Status](https://img.shields.io/coveralls/RolifyCommunity/rolify.svg)](https://coveralls.io/r/RolifyCommunity/rolify?branch=master)
2
2
 
3
-
4
3
  Very simple Roles library without any authorization enforcement supporting scope on resource object.
5
4
 
6
- Let's see an example:
5
+ Let's see an example:
7
6
 
8
7
  ```ruby
9
- user.has_role?(:moderator, Forum.first)
8
+ user.has_role?(:moderator, Forum.first)
10
9
  => false # if user is moderator of another Forum
11
10
  ```
12
11
 
@@ -23,7 +22,7 @@ This library can be easily integrated with any authentication gem ([devise](http
23
22
 
24
23
  ## Installation
25
24
 
26
- In <b>Rails 3</b>, add this to your Gemfile and run the +bundle+ command.
25
+ Add this to your Gemfile and run the +bundle+ command.
27
26
 
28
27
  ```ruby
29
28
  gem "rolify"
@@ -119,7 +118,7 @@ That's it !
119
118
 
120
119
  ### 5. Role queries
121
120
 
122
- To check if a user has a global role:
121
+ To check if a user has a global role:
123
122
 
124
123
  ```ruby
125
124
  user = User.find(1)
@@ -152,7 +151,7 @@ user.has_role? :moderator, Forum.last
152
151
  => true
153
152
  ```
154
153
 
155
- A global role overrides resource role request:
154
+ A global role overrides resource role request:
156
155
 
157
156
  ```ruby
158
157
  user = User.find(4)
@@ -163,7 +162,7 @@ user.has_role? :moderator, Forum.last
163
162
  => true
164
163
  ```
165
164
 
166
- ### 6. Resource roles querying
165
+ ### 6. Resource roles querying
167
166
 
168
167
  Starting from rolify 3.0, you can search roles on instance level or class level resources.
169
168
 
@@ -181,10 +180,10 @@ forum.applied_roles
181
180
 
182
181
  ```ruby
183
182
  Forum.with_role(:admin)
184
- # => [ list of Forum instances that has role "admin" binded to it ]
183
+ # => [ list of Forum instances that has role "admin" binded to it ]
185
184
  Forum.with_role(:admin, current_user)
186
185
  # => [ list of Forum instances that has role "admin" binded to it and belongs to current_user roles ]
187
- Forum.with_roles([:admin, :user], current_user)
186
+ Forum.with_all_roles([:admin, :user], current_user)
188
187
  # => [ list of Forum instances that has role "admin" or "user" binded to it and belongs to current_user roles ]
189
188
 
190
189
  User.with_any_role(:user, :admin)
@@ -202,12 +201,30 @@ Forum.find_roles(:admin, current_user)
202
201
  # => [ list of roles that binded to any Forum instance or to the Forum class with "admin" as a role name and belongs to current_user roles ]
203
202
  ```
204
203
 
204
+ ### Strict Mode
205
+
206
+ ```ruby
207
+ class User < ActiveRecord::Base
208
+ rolify strict: true
209
+ end
210
+
211
+ @user = User.first
212
+
213
+ @user.add_role(:forum, Forum)
214
+ @user.add_role(:forum, Forum.first)
215
+
216
+ @user.has_role?(:forum, Forum) #=> true
217
+ @user.has_role?(:forum, Forum.first) #=> true
218
+ @user.has_role?(:forum, Forum.last) #=> false
219
+ ```
220
+ I.e. you get true only on a role that you manually add.
221
+
205
222
  ## Resources
206
223
 
207
224
  * [Wiki](https://github.com/RolifyCommunity/rolify/wiki)
208
225
  * [Usage](https://github.com/RolifyCommunity/rolify/wiki/Usage): all the available commands
209
226
  * [Tutorials](https://github.com/RolifyCommunity/rolify/wiki#wiki-tutorials):
210
- * [How-To use rolify with Devise and CanCan](https://github.com/RolifyCommunity/rolify/wiki/Tutorial)
227
+ * [How-To use rolify with Devise and CanCanCan](https://github.com/RolifyCommunity/rolify/wiki/Devise---CanCanCan---rolify-Tutorial)
211
228
  * [Using rolify with Devise and Authority](https://github.com/RolifyCommunity/rolify/wiki/Using-rolify-with-Devise-and-Authority)
212
229
  * [Step-by-step tutorial](http://railsapps.github.com/tutorial-rails-bootstrap-devise-cancan.html) provided by [RailsApps](http://railsapps.github.com/)
213
230
 
@@ -13,6 +13,15 @@ module ActiveRecord
13
13
  end
14
14
 
15
15
  def inject_role_class
16
+ if args[1]=="engine"
17
+ if args[2]=="devise"
18
+ require 'devise'
19
+ require "#{ENGINE_ROOT}/config/initializers/devise.rb"
20
+ require "#{ENGINE_ROOT}/app/models/#{user_cname.downcase}.rb"
21
+ else
22
+ require "#{ENGINE_ROOT}/app/models/#{user_cname.downcase}.rb"
23
+ end
24
+ end
16
25
  inject_into_class(model_path, class_name, model_content)
17
26
  end
18
27
 
@@ -8,7 +8,7 @@ require 'rolify/role'
8
8
  module Rolify
9
9
  extend Configure
10
10
 
11
- attr_accessor :role_cname, :adapter, :role_join_table_name, :role_table_name
11
+ attr_accessor :role_cname, :adapter, :resource_adapter, :role_join_table_name, :role_table_name, :strict_rolify
12
12
  @@resource_types = []
13
13
 
14
14
  def rolify(options = {})
@@ -31,6 +31,9 @@ module Rolify
31
31
 
32
32
  self.adapter = Rolify::Adapter::Base.create("role_adapter", self.role_cname, self.name)
33
33
  load_dynamic_methods if Rolify.dynamic_shortcuts
34
+
35
+ #use strict roles
36
+ self.strict_rolify = true if options[:strict]
34
37
  end
35
38
 
36
39
  def adapter
@@ -48,10 +51,15 @@ module Rolify
48
51
 
49
52
  has_many association_name, resourcify_options
50
53
 
51
- self.adapter = Rolify::Adapter::Base.create("resource_adapter", self.role_cname, self.name)
54
+ self.resource_adapter = Rolify::Adapter::Base.create("resource_adapter", self.role_cname, self.name)
52
55
  @@resource_types << self.name
53
56
  end
54
57
 
58
+ def resource_adapter
59
+ return self.superclass.resource_adapter unless self.instance_variable_defined? '@resource_adapter'
60
+ @resource_adapter
61
+ end
62
+
55
63
  def scopify
56
64
  require "rolify/adapters/#{Rolify.orm}/scopes.rb"
57
65
  extend Rolify::Adapter::Scopes
@@ -65,4 +73,5 @@ module Rolify
65
73
  def self.resource_types
66
74
  @@resource_types
67
75
  end
76
+
68
77
  end
@@ -37,6 +37,11 @@ module Rolify
37
37
  end
38
38
  end
39
39
 
40
+ def all_except(resource, excluded_obj)
41
+ prime_key = resource.primary_key.to_sym
42
+ resource.where(prime_key => (resource.all - excluded_obj).map(&prime_key))
43
+ end
44
+
40
45
  private
41
46
 
42
47
  def quote(column)
@@ -8,6 +8,16 @@ module Rolify
8
8
  relation.where(conditions, *values)
9
9
  end
10
10
 
11
+ def where_strict(relation, args)
12
+ resource = if args[:resource].is_a?(Class)
13
+ {class: args[:resource].to_s, id: nil}
14
+ else
15
+ {class: args[:resource].class.name, id: args[:resource].id}
16
+ end
17
+
18
+ relation.where(:name => args[:name], :resource_type => resource[:class], :resource_id => resource[:id])
19
+ end
20
+
11
21
  def find_or_create_by(role_name, resource_type = nil, resource_id = nil)
12
22
  role_class.where(:name => role_name, :resource_type => resource_type, :resource_id => resource_id).first_or_create
13
23
  end
@@ -45,6 +55,11 @@ module Rolify
45
55
  query
46
56
  end
47
57
 
58
+ def all_except(user, excluded_obj)
59
+ prime_key = user.primary_key.to_sym
60
+ user.where(prime_key => (user.all - excluded_obj).map(&prime_key))
61
+ end
62
+
48
63
  private
49
64
 
50
65
  def build_conditions(relation, args)
@@ -59,6 +59,7 @@ module Rolify
59
59
  def in(resources, roles)
60
60
  raise NotImplementedError.new("You must implement in")
61
61
  end
62
+
62
63
  end
63
64
  end
64
65
  end
@@ -39,6 +39,10 @@ module Rolify
39
39
  end
40
40
  end
41
41
 
42
+ def all_except(resource, excluded_obj)
43
+ resource.not_in(_id: excluded_obj.to_a)
44
+ end
45
+
42
46
  end
43
47
  end
44
48
  end
@@ -8,6 +8,16 @@ module Rolify
8
8
  relation.any_of(*conditions)
9
9
  end
10
10
 
11
+ def where_strict(relation, args)
12
+ resource = if args[:resource].is_a?(Class)
13
+ {class: args[:resource].to_s, id: nil}
14
+ else
15
+ {class: args[:resource].class.name, id: args[:resource].id}
16
+ end
17
+
18
+ relation.where(:name => args[:name], :resource_type => resource[:class], :resource_id => resource[:id])
19
+ end
20
+
11
21
  def find_or_create_by(role_name, resource_type = nil, resource_id = nil)
12
22
  self.role_class.find_or_create_by(:name => role_name,
13
23
  :resource_type => resource_type,
@@ -58,6 +68,10 @@ module Rolify
58
68
  query
59
69
  end
60
70
 
71
+ def all_except(user, excluded_obj)
72
+ user.not_in(_id: excluded_obj.to_a)
73
+ end
74
+
61
75
  private
62
76
 
63
77
  def build_conditions(relation, args)
@@ -52,13 +52,13 @@ module Rolify
52
52
  private
53
53
 
54
54
  def sanity_check(role_cnames)
55
- return true if "assets:precompile"==ARGV[0]
55
+ return true if (ARGV[0] =~ /assets:/) == 0
56
56
 
57
57
  role_cnames = [ "Role" ] if role_cnames.empty?
58
58
  role_cnames.each do |role_cname|
59
59
  role_class = role_cname.constantize
60
60
  if role_class.superclass.to_s == "ActiveRecord::Base" && role_table_missing?(role_class)
61
- warn "[WARN] table '#{role_cname}' doesn't exist. Did you run the migration ? Ignoring rolify config."
61
+ warn "[WARN] table '#{role_cname}' doesn't exist. Did you run the migration? Ignoring rolify config."
62
62
  return false
63
63
  end
64
64
  end
@@ -1,8 +1,19 @@
1
+ require "rolify/configure"
2
+
1
3
  module Rolify
2
4
  module Dynamic
3
5
  def load_dynamic_methods
4
- self.role_class.all.each do |r|
5
- define_dynamic_method(r.name, r.resource)
6
+ if ENV['ADAPTER'] == 'mongoid'
7
+ # for compatibility with MongoidDB - does not support polymorphic includes
8
+ self.role_class.all.each do |r|
9
+ define_dynamic_method(r.name, r.resource)
10
+ end
11
+ else
12
+ # otherwise should be able to support polymorphic includes.
13
+ # supported Rails version >= 3.2 with AR should use find_each, since use of .all.each is deprecated
14
+ self.role_class.includes(:resource).find_each do |r|
15
+ define_dynamic_method(r.name, r.resource)
16
+ end
6
17
  end
7
18
  end
8
19
 
@@ -18,4 +29,4 @@ module Rolify
18
29
  end
19
30
  end
20
31
  end
21
- end
32
+ end
@@ -4,6 +4,10 @@ module Rolify
4
4
  self.adapter.scope(self, :name => role_name, :resource => resource)
5
5
  end
6
6
 
7
+ def without_role(role_name, resource = nil)
8
+ self.adapter.all_except(self, self.with_role(role_name, resource))
9
+ end
10
+
7
11
  def with_all_roles(*args)
8
12
  users = []
9
13
  parse_args(args, users) do |users_to_add|
@@ -6,7 +6,7 @@ module Rolify
6
6
 
7
7
  module ClassMethods
8
8
  def find_roles(role_name = nil, user = nil)
9
- self.adapter.find_roles(role_name, self, user)
9
+ self.resource_adapter.find_roles(role_name, self, user)
10
10
  end
11
11
 
12
12
  def with_role(role_name, user = nil)
@@ -16,14 +16,29 @@ module Rolify
16
16
  role_name = role_name.to_s
17
17
  end
18
18
 
19
- resources = self.adapter.resources_find(self.role_table_name, self, role_name) #.map(&:id)
20
- user ? self.adapter.in(resources, user, role_name) : resources
19
+ resources = self.resource_adapter.resources_find(self.role_table_name, self, role_name) #.map(&:id)
20
+ user ? self.resource_adapter.in(resources, user, role_name) : resources
21
21
  end
22
22
  alias :with_roles :with_role
23
+ alias :find_as :with_role
24
+ alias :find_multiple_as :with_role
25
+
26
+
27
+ def without_role(role_name, user = nil)
28
+ self.resource_adapter.all_except(self, self.find_as(role_name, user))
29
+ end
30
+ alias :without_roles :without_role
31
+ alias :except_as :without_role
32
+ alias :except_multiple_as :without_role
33
+
34
+
23
35
 
24
36
  def applied_roles(children = true)
25
- self.adapter.applied_roles(self, children)
37
+ self.resource_adapter.applied_roles(self, children)
26
38
  end
39
+
40
+
41
+
27
42
  end
28
43
 
29
44
  def applied_roles
@@ -23,8 +23,15 @@ module Rolify
23
23
  alias_method :grant, :add_role
24
24
 
25
25
  def has_role?(role_name, resource = nil)
26
+ return has_strict_role?(role_name, resource) if self.class.strict_rolify and resource and resource != :any
27
+
26
28
  if new_record?
27
- role_array = self.roles.detect { |r| r.name.to_s == role_name.to_s && (r.resource == resource || resource.nil?) }
29
+ role_array = self.roles.detect { |r|
30
+ r.name.to_s == role_name.to_s &&
31
+ (r.resource == resource ||
32
+ resource.nil? ||
33
+ (resource == :any && r.resource.present?))
34
+ }
28
35
  else
29
36
  role_array = self.class.adapter.where(self.roles, name: role_name, resource: resource)
30
37
  end
@@ -33,6 +40,10 @@ module Rolify
33
40
  role_array != []
34
41
  end
35
42
 
43
+ def has_strict_role?(role_name, resource)
44
+ self.class.adapter.where_strict(self.roles, name: role_name, resource: resource).any?
45
+ end
46
+
36
47
  def has_all_roles?(*args)
37
48
  args.each do |arg|
38
49
  if arg.is_a? Hash
@@ -1,3 +1,3 @@
1
1
  module Rolify
2
- VERSION = "4.0.0"
2
+ VERSION = "4.1.0"
3
3
  end
@@ -57,7 +57,7 @@ describe Rolify do
57
57
 
58
58
  subject { Forum }
59
59
 
60
- its("adapter.class") { should be(Rolify::Adapter::ResourceAdapter) }
60
+ its("resource_adapter.class") { should be(Rolify::Adapter::ResourceAdapter) }
61
61
  end
62
62
  end
63
63
 
@@ -88,7 +88,7 @@ describe Rolify do
88
88
 
89
89
  subject { Forum }
90
90
 
91
- its("adapter.class") { should be(Rolify::Adapter::ResourceAdapter) }
91
+ its("resource_adapter.class") { should be(Rolify::Adapter::ResourceAdapter) }
92
92
  end
93
93
  end
94
94
 
@@ -118,7 +118,7 @@ describe Rolify do
118
118
 
119
119
  subject { Forum }
120
120
 
121
- its("adapter.class") { should be(Rolify::Adapter::ResourceAdapter) }
121
+ its("resource_adapter.class") { should be(Rolify::Adapter::ResourceAdapter) }
122
122
  end
123
123
  end
124
124
  end
@@ -184,7 +184,7 @@ describe Rolify do
184
184
 
185
185
  subject { Forum }
186
186
  it { should satisfy { |u| u.include? Rolify::Resource }}
187
- its("adapter.class") { should be(Rolify::Adapter::ResourceAdapter) }
187
+ its("resource_adapter.class") { should be(Rolify::Adapter::ResourceAdapter) }
188
188
  end
189
189
  end
190
190
  end
@@ -0,0 +1,5 @@
1
+ {
2
+ "result": {
3
+ "covered_percent": 100.0
4
+ }
5
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "RSpec": {
3
+ "coverage": {
4
+ },
5
+ "timestamp": 1427836082
6
+ }
7
+ }
@@ -27,7 +27,7 @@ describe Rolify::Resource do
27
27
  let!(:player_role) { captain.add_role(:player, Team.last) }
28
28
  let!(:company_role) { admin.add_role(:owner, Company.first) }
29
29
 
30
- describe ".with_roles" do
30
+ describe ".find_multiple_as" do
31
31
  subject { Group }
32
32
 
33
33
  it { should respond_to(:find_roles).with(1).arguments }
@@ -38,15 +38,15 @@ describe Rolify::Resource do
38
38
  subject { Forum }
39
39
 
40
40
  it "should include Forum instances with forum role" do
41
- subject.with_role(:forum).should =~ [ Forum.first, Forum.last ]
41
+ subject.find_as(:forum).should =~ [ Forum.first, Forum.last ]
42
42
  end
43
43
 
44
44
  it "should include Forum instances with godfather role" do
45
- subject.with_role(:godfather).should =~ Forum.all.to_a
45
+ subject.find_as(:godfather).should =~ Forum.all
46
46
  end
47
47
 
48
48
  it "should be able to modify the resource", :if => ENV['ADAPTER'] == 'active_record' do
49
- forum_resource = subject.with_role(:forum).first
49
+ forum_resource = subject.find_as(:forum).first
50
50
  forum_resource.name = "modified name"
51
51
  expect { forum_resource.save }.not_to raise_error
52
52
  end
@@ -56,7 +56,7 @@ describe Rolify::Resource do
56
56
  subject { Group }
57
57
 
58
58
  it "should include Group instances with group role" do
59
- subject.with_role(:group).should =~ [ Group.last ]
59
+ subject.find_as(:group).should =~ [ Group.last ]
60
60
  end
61
61
  end
62
62
 
@@ -64,7 +64,7 @@ describe Rolify::Resource do
64
64
  subject { Group.last }
65
65
 
66
66
  it "should ignore nil entries" do
67
- subject.subgroups.with_role(:group).should =~ [ ]
67
+ subject.subgroups.find_as(:group).should =~ [ ]
68
68
  end
69
69
  end
70
70
  end
@@ -74,7 +74,7 @@ describe Rolify::Resource do
74
74
  subject { Group }
75
75
 
76
76
  it "should include Group instances with both group and grouper roles" do
77
- subject.with_roles([:group, :grouper]).should =~ [ Group.first, Group.last ]
77
+ subject.find_multiple_as([:group, :grouper]).should =~ [ Group.first, Group.last ]
78
78
  end
79
79
  end
80
80
  end
@@ -84,27 +84,27 @@ describe Rolify::Resource do
84
84
  subject { Forum }
85
85
 
86
86
  it "should get all Forum instances binded to the forum role and the admin user" do
87
- subject.with_role(:forum, admin).should =~ [ Forum.first ]
87
+ subject.find_as(:forum, admin).should =~ [ Forum.first ]
88
88
  end
89
89
 
90
90
  it "should get all Forum instances binded to the forum role and the tourist user" do
91
- subject.with_role(:forum, tourist).should =~ [ Forum.last ]
91
+ subject.find_as(:forum, tourist).should =~ [ Forum.last ]
92
92
  end
93
93
 
94
94
  it "should get all Forum instances binded to the godfather role and the admin user" do
95
- subject.with_role(:godfather, admin).should =~ Forum.all.to_a
95
+ subject.find_as(:godfather, admin).should =~ Forum.all.to_a
96
96
  end
97
97
 
98
98
  it "should get all Forum instances binded to the godfather role and the tourist user" do
99
- subject.with_role(:godfather, tourist).should be_empty
99
+ subject.find_as(:godfather, tourist).should be_empty
100
100
  end
101
101
 
102
102
  it "should get Forum instances binded to the group role and the tourist user" do
103
- subject.with_role(:group, tourist).should =~ [ Forum.first ]
103
+ subject.find_as(:group, tourist).should =~ [ Forum.first ]
104
104
  end
105
105
 
106
106
  it "should not get Forum instances not binded to the group role and the tourist user" do
107
- subject.with_role(:group, tourist).should_not include(Forum.last)
107
+ subject.find_as(:group, tourist).should_not include(Forum.last)
108
108
  end
109
109
  end
110
110
 
@@ -112,11 +112,11 @@ describe Rolify::Resource do
112
112
  subject { Group }
113
113
 
114
114
  it "should get all resources binded to the group role and the admin user" do
115
- subject.with_role(:group, admin).should =~ [ Group.last ]
115
+ subject.find_as(:group, admin).should =~ [ Group.last ]
116
116
  end
117
117
 
118
118
  it "should not get resources not binded to the group role and the admin user" do
119
- subject.with_role(:group, admin).should_not include(Group.first)
119
+ subject.find_as(:group, admin).should_not include(Group.first)
120
120
  end
121
121
  end
122
122
  end
@@ -126,7 +126,7 @@ describe Rolify::Resource do
126
126
  subject { Forum }
127
127
 
128
128
  it "should get Forum instances binded to the forum and group roles and the tourist user" do
129
- subject.with_roles([:forum, :group], tourist).should =~ [ Forum.first, Forum.last ]
129
+ subject.find_multiple_as([:forum, :group], tourist).should =~ [ Forum.first, Forum.last ]
130
130
  end
131
131
 
132
132
  end
@@ -135,7 +135,7 @@ describe Rolify::Resource do
135
135
  subject { Group }
136
136
 
137
137
  it "should get Group instances binded to the group and grouper roles and the admin user" do
138
- subject.with_roles([:group, :grouper], admin).should =~ [ Group.first, Group.last ]
138
+ subject.find_multiple_as([:group, :grouper], admin).should =~ [ Group.first, Group.last ]
139
139
  end
140
140
 
141
141
  end
@@ -145,14 +145,138 @@ describe Rolify::Resource do
145
145
  subject { Team }
146
146
 
147
147
  it "should find Team instance using team_code column" do
148
- subject.with_roles([:captain, :player], captain).should =~ [ Team.first, Team.last ]
148
+ subject.find_multiple_as([:captain, :player], captain).should =~ [ Team.first, Team.last ]
149
149
  end
150
150
  end
151
151
 
152
152
  context "with a resource using STI" do
153
153
  subject { Organization }
154
154
  it "should find instances of children classes" do
155
- subject.with_roles(:owner, admin).should =~ [ Company.first ]
155
+ subject.find_multiple_as(:owner, admin).should =~ [ Company.first ]
156
+ end
157
+ end
158
+ end
159
+
160
+
161
+ describe ".except_multiple_as" do
162
+ subject { Group }
163
+
164
+ it { should respond_to(:find_roles).with(1).arguments }
165
+ it { should respond_to(:find_roles).with(2).arguments }
166
+
167
+ context "with a role name as argument" do
168
+ context "on the Forum class" do
169
+ subject { Forum }
170
+
171
+ it "should not include Forum instances with forum role" do
172
+ subject.except_as(:forum).should_not =~ [ Forum.first, Forum.last ]
173
+ end
174
+
175
+ it "should not include Forum instances with godfather role" do
176
+ subject.except_as(:godfather).should be_empty
177
+ end
178
+
179
+ it "should be able to modify the resource", :if => ENV['ADAPTER'] == 'active_record' do
180
+ forum_resource = subject.except_as(:forum).first
181
+ forum_resource.name = "modified name"
182
+ expect { forum_resource.save }.not_to raise_error
183
+ end
184
+ end
185
+
186
+ context "on the Group class" do
187
+ subject { Group }
188
+
189
+ it "should not include Group instances with group role" do
190
+ subject.except_as(:group).should_not =~ [ Group.last ]
191
+ end
192
+ end
193
+
194
+ end
195
+
196
+ context "with an array of role names as argument" do
197
+ context "on the Group class" do
198
+ subject { Group }
199
+
200
+ it "should include Group instances without either the group and grouper roles" do
201
+ subject.except_multiple_as([:group, :grouper]).should_not =~ [ Group.first, Group.last ]
202
+ end
203
+ end
204
+ end
205
+
206
+ context "with a role name and a user as arguments" do
207
+ context "on the Forum class" do
208
+ subject { Forum }
209
+
210
+ it "should get all Forum instances the admin user does not have the forum role" do
211
+ subject.except_as(:forum, admin).should_not =~ [ Forum.first ]
212
+ end
213
+
214
+ it "should get all Forum instances the tourist user does not have the forum role" do
215
+ subject.except_as(:forum, tourist).should_not =~ [ Forum.last ]
216
+ end
217
+
218
+ it "should get all Forum instances the admin user does not have the godfather role" do
219
+ subject.except_as(:godfather, admin).should_not =~ Forum.all
220
+ end
221
+
222
+ it "should get all Forum instances tourist user does not have the godfather role" do
223
+ subject.except_as(:godfather, tourist).should =~ Forum.all
224
+ end
225
+
226
+ it "should get Forum instances the tourist user does not have the group role" do
227
+ subject.except_as(:group, tourist).should_not =~ [ Forum.first ]
228
+ end
229
+
230
+ it "should get Forum instances the tourist user does not have the group role" do
231
+ subject.except_as(:group, tourist).should_not =~ [ Forum.first ]
232
+ end
233
+ end
234
+
235
+ context "on the Group class" do
236
+ subject { Group }
237
+
238
+ it "should get all resources not bounded to the group role and the admin user" do
239
+ subject.except_as(:group, admin).should =~ [ Group.first ]
240
+ end
241
+
242
+ it "should not get resources bound to the group role and the admin user" do
243
+ subject.except_as(:group, admin).should include(Group.first)
244
+ end
245
+ end
246
+ end
247
+
248
+ context "with an array of role names and a user as arguments" do
249
+ context "on the Forum class" do
250
+ subject { Forum }
251
+
252
+ it "should get Forum instances not bound to the forum and group roles and the tourist user" do
253
+ subject.except_multiple_as([:forum, :group], tourist).should_not =~ [ Forum.first, Forum.last ]
254
+ end
255
+
256
+ end
257
+
258
+ context "on the Group class" do
259
+ subject { Group }
260
+
261
+ it "should get Group instances binded to the group and grouper roles and the admin user" do
262
+ subject.except_multiple_as([:group, :grouper], admin).should =~ [ ]
263
+ end
264
+
265
+ end
266
+ end
267
+
268
+ context "with a model not having ID column" do
269
+ subject { Team }
270
+
271
+ it "should find Team instance not using team_code column" do
272
+ subject.except_multiple_as(:captain, captain).should =~ [ Team.last ]
273
+ end
274
+ end
275
+
276
+ context "with a resource using STI" do
277
+ subject { Organization }
278
+ it "should exclude instances of children classes with matching" do
279
+ subject.except_as(:owner, admin).should_not =~ [ Company.first ]
156
280
  end
157
281
  end
158
282
  end
@@ -404,6 +528,7 @@ describe Rolify::Resource do
404
528
  end
405
529
  end
406
530
 
531
+
407
532
  describe '.resource_types' do
408
533
 
409
534
  it 'include all models that call resourcify' do
@@ -411,4 +536,36 @@ describe Rolify::Resource do
411
536
  "Team", "Organization")
412
537
  end
413
538
  end
539
+
540
+
541
+ describe "#strict" do
542
+ context "strict user" do
543
+ before(:all) do
544
+ @strict_user = StrictUser.first
545
+ @strict_user.add_role(:forum, Forum.first)
546
+ @strict_user.add_role(:forum, Forum)
547
+ end
548
+
549
+ it "should return only strict forum" do
550
+ @strict_user.has_role?(:forum, Forum.first).should be true
551
+ end
552
+
553
+ it "should return false on strict another forum" do
554
+ @strict_user.has_role?(:forum, Forum.last).should be false
555
+ end
556
+
557
+ it "should return true if user has role on Forum model" do
558
+ @strict_user.has_role?(:forum, Forum).should be true
559
+ end
560
+
561
+ it "should return true if user has role any forum name" do
562
+ @strict_user.has_role?(:forum, :any).should be true
563
+ end
564
+
565
+ it "should return false when deleted role on Forum model" do
566
+ @strict_user.remove_role(:forum, Forum)
567
+ @strict_user.has_role?(:forum, Forum).should be false
568
+ end
569
+ end
570
+ end
414
571
  end
@@ -49,6 +49,56 @@ shared_examples_for :finders do |param_name, param_method|
49
49
  end
50
50
  end
51
51
 
52
+ describe ".without_role" do
53
+ it { should respond_to(:without_role).with(1).argument }
54
+ it { should respond_to(:without_role).with(2).arguments }
55
+
56
+ context "with a global role" do
57
+ it { subject.without_role("admin".send(param_method)).should_not eq([ root ]) }
58
+ it { subject.without_role("moderator".send(param_method)).should_not be_empty }
59
+ it { subject.without_role("visitor".send(param_method)).should_not be_empty }
60
+ end
61
+
62
+ context "with a class scoped role" do
63
+ context "on Forum class" do
64
+ it { subject.without_role("admin".send(param_method), Forum).should_not eq([ root ]) }
65
+ it { subject.without_role("moderator".send(param_method), Forum).should_not eq([ modo ]) }
66
+ it { subject.without_role("visitor".send(param_method), Forum).should_not be_empty }
67
+ end
68
+
69
+ context "on Group class" do
70
+ it { subject.without_role("admin".send(param_method), Group).should_not eq([ root ]) }
71
+ it { subject.without_role("moderator".send(param_method), Group).should_not eq([ root ]) }
72
+ it { subject.without_role("visitor".send(param_method), Group).should_not be_empty }
73
+ end
74
+ end
75
+
76
+ context "with an instance scoped role" do
77
+ context "on Forum.first instance" do
78
+ it { subject.without_role("admin".send(param_method), Forum.first).should_not eq([ root ]) }
79
+ it { subject.without_role("moderator".send(param_method), Forum.first).should_not eq([ modo ]) }
80
+ it { subject.without_role("visitor".send(param_method), Forum.first).should_not be_empty }
81
+ end
82
+
83
+ context "on Forum.last instance" do
84
+ it { subject.without_role("admin".send(param_method), Forum.last).should_not eq([ root ]) }
85
+ it { subject.without_role("moderator".send(param_method), Forum.last).should_not eq([ modo ]) }
86
+ it { subject.without_role("visitor".send(param_method), Forum.last).should_not include(root, visitor) } # =~ doesn't pass using mongoid, don't know why...
87
+ end
88
+
89
+ context "on Group.first instance" do
90
+ it { subject.without_role("admin".send(param_method), Group.first).should_not eq([ root ]) }
91
+ it { subject.without_role("moderator".send(param_method), Group.first).should_not eq([ root ]) }
92
+ it { subject.without_role("visitor".send(param_method), Group.first).should_not eq([ modo ]) }
93
+ end
94
+
95
+ context "on Company.first_instance" do
96
+ it { subject.without_role("owner".send(param_method), Company.first).should_not eq([ owner ]) }
97
+ end
98
+ end
99
+ end
100
+
101
+
52
102
  describe ".with_all_roles" do
53
103
  it { should respond_to(:with_all_roles) }
54
104
 
@@ -79,6 +79,11 @@ shared_examples_for "#has_role?_examples" do |param_name, param_method|
79
79
  context "on instance scoped role request" do
80
80
  it { subject.has_role?("moderator".send(param_method), Forum.first).should be_truthy }
81
81
  it { subject.has_role?("moderator".send(param_method), :any).should be_truthy }
82
+ it {
83
+ m = subject.class.new
84
+ m.add_role("moderator", Forum.first)
85
+ m.has_role?("moderator".send(param_method), :any).should be_truthy
86
+ }
82
87
  end
83
88
 
84
89
  it "should not get an instance scoped role when asking for a global" do
@@ -132,4 +137,4 @@ shared_examples_for "#has_role?_examples" do |param_name, param_method|
132
137
  end
133
138
  end
134
139
  end
135
- end
140
+ end
@@ -7,6 +7,7 @@ require "rolify/shared_examples/shared_examples_for_has_any_role"
7
7
  require "rolify/shared_examples/shared_examples_for_remove_role"
8
8
  require "rolify/shared_examples/shared_examples_for_finders"
9
9
 
10
+
10
11
  shared_examples_for Rolify::Role do
11
12
  before(:all) do
12
13
  reset_defaults
@@ -13,11 +13,18 @@ end
13
13
 
14
14
  class Role < ActiveRecord::Base
15
15
  has_and_belongs_to_many :users, :join_table => :users_roles
16
+ has_and_belongs_to_many :strict_users, :join_table => :strict_users_roles
17
+
16
18
  belongs_to :resource, :polymorphic => true
17
19
 
18
20
  extend Rolify::Adapter::Scopes
19
21
  end
20
22
 
23
+ # Strict user and role classes
24
+ class StrictUser < ActiveRecord::Base
25
+ rolify strict: true
26
+ end
27
+
21
28
  # Resourcifed and rolifed at the same time
22
29
  class HumanResource < ActiveRecord::Base
23
30
  resourcify :resources
@@ -18,9 +18,18 @@ class User
18
18
  field :login, :type => String
19
19
  end
20
20
 
21
+ # Standard user and role classes
22
+ class StrictUser
23
+ include Mongoid::Document
24
+ rolify strict: true
25
+
26
+ field :login, :type => String
27
+ end
28
+
21
29
  class Role
22
30
  include Mongoid::Document
23
31
  has_and_belongs_to_many :users
32
+ has_and_belongs_to_many :strict_users
24
33
  belongs_to :resource, :polymorphic => true
25
34
 
26
35
  field :name, :type => String
@@ -148,4 +157,4 @@ end
148
157
 
149
158
  class Company < Organization
150
159
 
151
- end
160
+ end
@@ -1,7 +1,7 @@
1
1
  # Users
2
- [ User, Customer, Admin::Moderator ].each do |user|
2
+ [ User, Customer, Admin::Moderator, StrictUser ].each do |user|
3
3
  user.destroy_all
4
-
4
+
5
5
  user.create(:login => "admin")
6
6
  user.create(:login => "moderator")
7
7
  user.create(:login => "god")
@@ -25,4 +25,4 @@ Team.create(:team_code => "1", :name => "PSG")
25
25
  Team.create(:team_code => "2", :name => "MU")
26
26
 
27
27
  Organization.create
28
- Company.create
28
+ Company.create
@@ -10,7 +10,7 @@ ActiveRecord::Schema.define do
10
10
  end
11
11
  end
12
12
 
13
- [ :users, :human_resources, :customers, :admin_moderators ].each do |table|
13
+ [ :users, :human_resources, :customers, :admin_moderators, :strict_users ].each do |table|
14
14
  create_table(table) do |t|
15
15
  t.string :login
16
16
  end
@@ -21,6 +21,11 @@ ActiveRecord::Schema.define do
21
21
  t.references :role
22
22
  end
23
23
 
24
+ create_table(:strict_users_roles, :id => false) do |t|
25
+ t.references :strict_user
26
+ t.references :role
27
+ end
28
+
24
29
  create_table(:human_resources_roles, :id => false) do |t|
25
30
  t.references :human_resource
26
31
  t.references :role
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rolify
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0
4
+ version: 4.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florent Monbillard
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-12 00:00:00.000000000 Z
11
+ date: 2015-08-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ammeter
@@ -84,7 +84,6 @@ files:
84
84
  - README.md
85
85
  - Rakefile
86
86
  - UPGRADE.rdoc
87
- - circle.yml
88
87
  - gemfiles/Gemfile.rails-3.2
89
88
  - gemfiles/Gemfile.rails-4.0
90
89
  - gemfiles/Gemfile.rails-4.1
@@ -122,6 +121,9 @@ files:
122
121
  - spec/generators/rolify/rolify_mongoid_generator_spec.rb
123
122
  - spec/generators_helper.rb
124
123
  - spec/rolify/config_spec.rb
124
+ - spec/rolify/coverage/.last_run.json
125
+ - spec/rolify/coverage/.resultset.json
126
+ - spec/rolify/coverage/.resultset.json.lock
125
127
  - spec/rolify/custom_spec.rb
126
128
  - spec/rolify/matchers_spec.rb
127
129
  - spec/rolify/namespace_spec.rb
@@ -167,7 +169,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
167
169
  version: '0'
168
170
  requirements: []
169
171
  rubyforge_project: rolify
170
- rubygems_version: 2.2.2
172
+ rubygems_version: 2.4.5
171
173
  signing_key:
172
174
  specification_version: 4
173
175
  summary: Roles library with resource scoping
@@ -177,6 +179,9 @@ test_files:
177
179
  - spec/generators/rolify/rolify_mongoid_generator_spec.rb
178
180
  - spec/generators_helper.rb
179
181
  - spec/rolify/config_spec.rb
182
+ - spec/rolify/coverage/.last_run.json
183
+ - spec/rolify/coverage/.resultset.json
184
+ - spec/rolify/coverage/.resultset.json.lock
180
185
  - spec/rolify/custom_spec.rb
181
186
  - spec/rolify/matchers_spec.rb
182
187
  - spec/rolify/namespace_spec.rb
data/circle.yml DELETED
@@ -1,13 +0,0 @@
1
- machine:
2
- ruby:
3
- version: 2.1.3
4
- environment:
5
- CODECLIMATE_REPO_TOKEN: 6bd8d374b120a5449b9a4b7dfda40cc0609dbade48a1b6655f04a9bc8de3a3ee
6
- ADAPTER: active_record
7
- ADAPTER: mongoid
8
- dependencies:
9
- pre:
10
- - gem install bundler
11
- test:
12
- override:
13
- - bundle exec rake:spec_all