strongbolt 0.3.7 → 0.3.8
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/Gemfile.lock +52 -54
- data/README.md +4 -0
- data/app/controllers/strongbolt/security_controller.rb +2 -2
- data/app/controllers/strongbolt/user_groups_users_controller.rb +4 -4
- data/app/views/strongbolt/roles/_capabilities.html.erb +4 -4
- data/app/views/strongbolt/roles/_capability.html.erb +3 -3
- data/app/views/strongbolt/roles/_form.html.erb +1 -1
- data/lib/generators/strongbolt/install_generator.rb +1 -1
- data/lib/strongbolt/bolted.rb +4 -4
- data/lib/strongbolt/capabilities_role.rb +2 -2
- data/lib/strongbolt/capability.rb +3 -5
- data/lib/strongbolt/configuration.rb +1 -1
- data/lib/strongbolt/engine.rb +1 -1
- data/lib/strongbolt/role.rb +2 -4
- data/lib/strongbolt/roles_user_group.rb +2 -2
- data/lib/strongbolt/tenantable.rb +25 -13
- data/lib/strongbolt/user_abilities.rb +22 -22
- data/lib/strongbolt/user_group.rb +1 -3
- data/lib/strongbolt/user_groups_user.rb +2 -2
- data/lib/strongbolt/users_tenant.rb +0 -2
- data/lib/strongbolt/version.rb +1 -1
- data/lib/tasks/strongbolt_tasks.rake +7 -7
- data/spec/spec_helper.rb +1 -1
- data/spec/strongbolt/configuration_spec.rb +10 -10
- data/strongbolt.gemspec +2 -2
- metadata +10 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c67e76eb347b2f56147ce3ea4edb40c0abbec16c
|
4
|
+
data.tar.gz: fe67b27504d1db3bcd74cd861aee53b979dcbc84
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b456dbe25f2c8fa8a2492cff18a864b1e21f76b3b38fe9427da888d06c17e6cbab82778863d37f5e68cb878e2f3e7599abf1f8f9d3c3e15538ec4cdaeebc3cdd
|
7
|
+
data.tar.gz: f077745183044f7feb443bda2dc0d4e438b7597ad7034ed7f089a6eb088d835bf1de72c293bec8c255867a52360b6df96c630e35a4a220d18594e2845ad551b5
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
ruby-2.1
|
1
|
+
ruby-2.3.1
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
strongbolt (0.3.
|
4
|
+
strongbolt (0.3.7)
|
5
5
|
awesome_nested_set (~> 3.0.0)
|
6
6
|
grant (~> 3.0)
|
7
7
|
simple_form (~> 3.0)
|
@@ -9,27 +9,27 @@ PATH
|
|
9
9
|
GEM
|
10
10
|
remote: https://rubygems.org/
|
11
11
|
specs:
|
12
|
-
actionmailer (4.1.
|
13
|
-
actionpack (= 4.1.
|
14
|
-
actionview (= 4.1.
|
12
|
+
actionmailer (4.1.15)
|
13
|
+
actionpack (= 4.1.15)
|
14
|
+
actionview (= 4.1.15)
|
15
15
|
mail (~> 2.5, >= 2.5.4)
|
16
|
-
actionpack (4.1.
|
17
|
-
actionview (= 4.1.
|
18
|
-
activesupport (= 4.1.
|
16
|
+
actionpack (4.1.15)
|
17
|
+
actionview (= 4.1.15)
|
18
|
+
activesupport (= 4.1.15)
|
19
19
|
rack (~> 1.5.2)
|
20
20
|
rack-test (~> 0.6.2)
|
21
|
-
actionview (4.1.
|
22
|
-
activesupport (= 4.1.
|
21
|
+
actionview (4.1.15)
|
22
|
+
activesupport (= 4.1.15)
|
23
23
|
builder (~> 3.1)
|
24
24
|
erubis (~> 2.7.0)
|
25
|
-
activemodel (4.1.
|
26
|
-
activesupport (= 4.1.
|
25
|
+
activemodel (4.1.15)
|
26
|
+
activesupport (= 4.1.15)
|
27
27
|
builder (~> 3.1)
|
28
|
-
activerecord (4.1.
|
29
|
-
activemodel (= 4.1.
|
30
|
-
activesupport (= 4.1.
|
28
|
+
activerecord (4.1.15)
|
29
|
+
activemodel (= 4.1.15)
|
30
|
+
activesupport (= 4.1.15)
|
31
31
|
arel (~> 5.0.0)
|
32
|
-
activesupport (4.1.
|
32
|
+
activesupport (4.1.15)
|
33
33
|
i18n (~> 0.6, >= 0.6.9)
|
34
34
|
json (~> 1.7, >= 1.7.7)
|
35
35
|
minitest (~> 5.1)
|
@@ -39,51 +39,52 @@ GEM
|
|
39
39
|
awesome_nested_set (3.0.3)
|
40
40
|
activerecord (>= 4.0.0, < 5)
|
41
41
|
builder (3.2.2)
|
42
|
+
concurrent-ruby (1.0.2)
|
42
43
|
diff-lcs (1.2.5)
|
43
44
|
erubis (2.7.0)
|
44
|
-
fabrication (2.
|
45
|
+
fabrication (2.15.2)
|
45
46
|
fuubar (2.0.0)
|
46
47
|
rspec (~> 3.0)
|
47
48
|
ruby-progressbar (~> 1.4)
|
48
49
|
grant (3.0.0)
|
49
50
|
activerecord (>= 4.0.0)
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
rack (1.5.
|
59
|
-
rack-test (0.6.
|
51
|
+
i18n (0.7.0)
|
52
|
+
json (1.8.3)
|
53
|
+
mail (2.6.4)
|
54
|
+
mime-types (>= 1.16, < 4)
|
55
|
+
mime-types (3.0)
|
56
|
+
mime-types-data (~> 3.2015)
|
57
|
+
mime-types-data (3.2016.0221)
|
58
|
+
minitest (5.8.4)
|
59
|
+
rack (1.5.5)
|
60
|
+
rack-test (0.6.3)
|
60
61
|
rack (>= 1.0)
|
61
|
-
rails (4.1.
|
62
|
-
actionmailer (= 4.1.
|
63
|
-
actionpack (= 4.1.
|
64
|
-
actionview (= 4.1.
|
65
|
-
activemodel (= 4.1.
|
66
|
-
activerecord (= 4.1.
|
67
|
-
activesupport (= 4.1.
|
62
|
+
rails (4.1.15)
|
63
|
+
actionmailer (= 4.1.15)
|
64
|
+
actionpack (= 4.1.15)
|
65
|
+
actionview (= 4.1.15)
|
66
|
+
activemodel (= 4.1.15)
|
67
|
+
activerecord (= 4.1.15)
|
68
|
+
activesupport (= 4.1.15)
|
68
69
|
bundler (>= 1.3.0, < 2.0)
|
69
|
-
railties (= 4.1.
|
70
|
+
railties (= 4.1.15)
|
70
71
|
sprockets-rails (~> 2.0)
|
71
|
-
railties (4.1.
|
72
|
-
actionpack (= 4.1.
|
73
|
-
activesupport (= 4.1.
|
72
|
+
railties (4.1.15)
|
73
|
+
actionpack (= 4.1.15)
|
74
|
+
activesupport (= 4.1.15)
|
74
75
|
rake (>= 0.8.7)
|
75
76
|
thor (>= 0.18.1, < 2.0)
|
76
|
-
rake (
|
77
|
+
rake (11.1.2)
|
77
78
|
rspec (3.1.0)
|
78
79
|
rspec-core (~> 3.1.0)
|
79
80
|
rspec-expectations (~> 3.1.0)
|
80
81
|
rspec-mocks (~> 3.1.0)
|
81
|
-
rspec-core (3.1.
|
82
|
+
rspec-core (3.1.7)
|
82
83
|
rspec-support (~> 3.1.0)
|
83
84
|
rspec-expectations (3.1.2)
|
84
85
|
diff-lcs (>= 1.2.0, < 2.0)
|
85
86
|
rspec-support (~> 3.1.0)
|
86
|
-
rspec-mocks (3.1.
|
87
|
+
rspec-mocks (3.1.3)
|
87
88
|
rspec-support (~> 3.1.0)
|
88
89
|
rspec-rails (3.1.0)
|
89
90
|
actionpack (>= 3.0)
|
@@ -93,26 +94,23 @@ GEM
|
|
93
94
|
rspec-expectations (~> 3.1.0)
|
94
95
|
rspec-mocks (~> 3.1.0)
|
95
96
|
rspec-support (~> 3.1.0)
|
96
|
-
rspec-support (3.1.
|
97
|
-
ruby-progressbar (1.
|
97
|
+
rspec-support (3.1.2)
|
98
|
+
ruby-progressbar (1.8.1)
|
98
99
|
shoulda-matchers (2.7.0)
|
99
100
|
activesupport (>= 3.0.0)
|
100
101
|
simple_form (3.2.1)
|
101
102
|
actionpack (> 4, < 5.1)
|
102
103
|
activemodel (> 4, < 5.1)
|
103
|
-
sprockets (
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
tilt (~> 1.1, != 1.3.0)
|
108
|
-
sprockets-rails (2.2.2)
|
104
|
+
sprockets (3.6.0)
|
105
|
+
concurrent-ruby (~> 1.0)
|
106
|
+
rack (> 1, < 3)
|
107
|
+
sprockets-rails (2.3.3)
|
109
108
|
actionpack (>= 3.0)
|
110
109
|
activesupport (>= 3.0)
|
111
110
|
sprockets (>= 2.8, < 4.0)
|
112
|
-
sqlite3 (1.3.
|
111
|
+
sqlite3 (1.3.11)
|
113
112
|
thor (0.19.1)
|
114
|
-
thread_safe (0.3.
|
115
|
-
tilt (1.4.1)
|
113
|
+
thread_safe (0.3.5)
|
116
114
|
tzinfo (1.2.2)
|
117
115
|
thread_safe (~> 0.1)
|
118
116
|
|
@@ -126,9 +124,9 @@ DEPENDENCIES
|
|
126
124
|
rails (~> 4.1.0)
|
127
125
|
rake
|
128
126
|
rspec-rails (~> 3.1.0)
|
129
|
-
shoulda-matchers
|
130
|
-
sqlite3
|
127
|
+
shoulda-matchers (~> 2.7.0)
|
128
|
+
sqlite3
|
131
129
|
strongbolt!
|
132
130
|
|
133
131
|
BUNDLED WITH
|
134
|
-
1.
|
132
|
+
1.12.3
|
data/README.md
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
RBAC framework for model-level authorization gem with very granular control on permissions, using Capabilities, Roles and UserGroups.
|
4
4
|
|
5
|
+
Checkout our [minimal example app](https://github.com/AnalyticsMediaGroup/strongbolt_example) to try it out without the need to set it up yourself.
|
6
|
+
|
5
7
|
Only works with Rails 4.
|
6
8
|
|
7
9
|
## Installation
|
@@ -30,6 +32,8 @@ If you plan on using the built-in view to manage user groups, roles and permissi
|
|
30
32
|
|
31
33
|
You will need to have jQuery or a similar library with Ajax to make it work
|
32
34
|
|
35
|
+
There is a minimal example app using Strongbolt made available [here](https://github.com/AnalyticsMediaGroup/strongbolt_example). If you experience any issues setting Strongbolt up or configuring it, this example app is already setup for you and might be able to resolve some issues.
|
36
|
+
|
33
37
|
## Usage
|
34
38
|
|
35
39
|
### Configuration
|
@@ -1,12 +1,12 @@
|
|
1
1
|
module Strongbolt
|
2
2
|
class UserGroupsUsersController < ::StrongboltController
|
3
3
|
|
4
|
-
self.model_for_authorization = "UserGroup"
|
4
|
+
self.model_for_authorization = "Strongbolt::UserGroup"
|
5
5
|
|
6
6
|
def create
|
7
7
|
@user_group = UserGroup.find(params[:user_group_id])
|
8
8
|
@user = Strongbolt.user_class_constant.find(params[:id])
|
9
|
-
|
9
|
+
|
10
10
|
@user_group.users << @user unless @user_group.users.include?(@user)
|
11
11
|
|
12
12
|
redirect_to request.referrer || user_group_path(@user_group)
|
@@ -15,7 +15,7 @@ module Strongbolt
|
|
15
15
|
def destroy
|
16
16
|
@user_group = UserGroup.find(params[:user_group_id])
|
17
17
|
@user = Strongbolt.user_class_constant.find(params[:id])
|
18
|
-
|
18
|
+
|
19
19
|
@user_group.users.delete @user
|
20
20
|
|
21
21
|
redirect_to request.referrer || user_group_path(@user_group)
|
@@ -32,4 +32,4 @@ module Strongbolt
|
|
32
32
|
end
|
33
33
|
|
34
34
|
end
|
35
|
-
end
|
35
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<%= simple_form_for(Capability.new, url: role_capabilities_path(@role), as: :capability) do |f| %>
|
1
|
+
<%= simple_form_for(Strongbolt::Capability.new, url: role_capabilities_path(@role), as: :capability) do |f| %>
|
2
2
|
<table class="table table-striped table-condensed" id="role-capabilities" data-url="<%= role_capabilities_path(@role) %>">
|
3
3
|
|
4
4
|
<thead>
|
@@ -12,7 +12,7 @@
|
|
12
12
|
|
13
13
|
<tbody>
|
14
14
|
<% @keys.each do |key| %>
|
15
|
-
|
15
|
+
|
16
16
|
<tr>
|
17
17
|
<td><%= key[:model] %></td>
|
18
18
|
<td>
|
@@ -32,7 +32,7 @@
|
|
32
32
|
|
33
33
|
<tfoot>
|
34
34
|
<tr>
|
35
|
-
<td><%= f.input_field :model, collection: Capability.models, include_blank: false %></td>
|
35
|
+
<td><%= f.input_field :model, collection: Strongbolt::Capability.models, include_blank: false %></td>
|
36
36
|
<td><%= f.input_field :require_ownership, as: :select, include_blank: false %></td>
|
37
37
|
<td><%= f.input_field :require_tenant_access, as: :select, include_blank: false %></td>
|
38
38
|
<td colspan="4">
|
@@ -44,4 +44,4 @@
|
|
44
44
|
|
45
45
|
</table>
|
46
46
|
|
47
|
-
<% end %>
|
47
|
+
<% end %>
|
@@ -2,8 +2,8 @@
|
|
2
2
|
data-model="<%= key[:model] %>"
|
3
3
|
data-require-ownership=<%= key[:require_ownership] %>
|
4
4
|
data-require-tenant-access=<%= key[:require_tenant_access] %>>
|
5
|
-
|
6
|
-
<% Capability::Actions.each do |action| %>
|
5
|
+
|
6
|
+
<% Strongbolt::Capability::Actions.each do |action| %>
|
7
7
|
<% if inherited_capability[action.to_sym] %>
|
8
8
|
<button type="button" disabled class="btn btn-xs btn-success" title="Inherited">
|
9
9
|
<%= action.capitalize %>
|
@@ -18,4 +18,4 @@
|
|
18
18
|
<% end %>
|
19
19
|
<% end %>
|
20
20
|
|
21
|
-
</div>
|
21
|
+
</div>
|
@@ -4,7 +4,7 @@
|
|
4
4
|
method: params[:action].to_sym == :new ? :post : :put) do |f| %>
|
5
5
|
|
6
6
|
<%= f.input :name %>
|
7
|
-
<%= f.input :parent_id, collection: Role.where.not(id: @role.id).order('parent_id IS NOT NULL', :parent_id, :name) %>
|
7
|
+
<%= f.input :parent_id, collection: Strongbolt::Role.where.not(id: @role.id).order('parent_id IS NOT NULL', :parent_id, :name) %>
|
8
8
|
<%= f.input :description %>
|
9
9
|
|
10
10
|
<%= f.button :submit, class: 'btn-primary', value: 'Save' %>
|
data/lib/strongbolt/bolted.rb
CHANGED
@@ -73,7 +73,7 @@ module Strongbolt
|
|
73
73
|
end
|
74
74
|
|
75
75
|
end
|
76
|
-
|
76
|
+
|
77
77
|
module InstanceMethods
|
78
78
|
#
|
79
79
|
# Asks permission to performa an operation on the current instance
|
@@ -91,7 +91,7 @@ module Strongbolt
|
|
91
91
|
send self.class.owner_attribute
|
92
92
|
end
|
93
93
|
end
|
94
|
-
|
94
|
+
|
95
95
|
def self.included(receiver)
|
96
96
|
receiver.extend ClassMethods
|
97
97
|
receiver.send :include, InstanceMethods
|
@@ -115,11 +115,11 @@ module Strongbolt
|
|
115
115
|
unless granted
|
116
116
|
Strongbolt.access_denied user, instance, action, $request.try(:fullpath)
|
117
117
|
end
|
118
|
-
|
118
|
+
|
119
119
|
granted
|
120
120
|
end # End Grant
|
121
121
|
|
122
122
|
end
|
123
123
|
end
|
124
124
|
end
|
125
|
-
end
|
125
|
+
end
|
@@ -5,11 +5,11 @@ module Strongbolt
|
|
5
5
|
belongs_to :role,
|
6
6
|
:class_name => "Strongbolt::Role",
|
7
7
|
:inverse_of => :capabilities_roles
|
8
|
-
|
8
|
+
|
9
9
|
belongs_to :capability,
|
10
10
|
:class_name => "Strongbolt::Capability",
|
11
11
|
:inverse_of => :capabilities_roles
|
12
12
|
|
13
13
|
validates_presence_of :role, :capability
|
14
14
|
end
|
15
|
-
end
|
15
|
+
end
|
@@ -12,7 +12,7 @@ module Strongbolt
|
|
12
12
|
:class_name => "Strongbolt::CapabilitiesRole",
|
13
13
|
:dependent => :restrict_with_exception,
|
14
14
|
:inverse_of => :capability
|
15
|
-
|
15
|
+
|
16
16
|
has_many :roles, :through => :capabilities_roles
|
17
17
|
|
18
18
|
has_many :users, through: :roles
|
@@ -57,7 +57,7 @@ module Strongbolt
|
|
57
57
|
! (table.last[:model] == capability.model &&
|
58
58
|
table.last[:require_ownership] == capability.require_ownership &&
|
59
59
|
table.last[:require_tenant_access] == capability.require_tenant_access)
|
60
|
-
|
60
|
+
|
61
61
|
table << {
|
62
62
|
model: capability.model,
|
63
63
|
require_ownership: capability.require_ownership,
|
@@ -87,7 +87,7 @@ module Strongbolt
|
|
87
87
|
require_ownership: capability.require_ownership,
|
88
88
|
require_tenant_access: capability.require_tenant_access
|
89
89
|
}
|
90
|
-
|
90
|
+
|
91
91
|
hash[key] ||= {
|
92
92
|
find: false,
|
93
93
|
create: false,
|
@@ -161,5 +161,3 @@ module Strongbolt
|
|
161
161
|
end
|
162
162
|
end
|
163
163
|
end
|
164
|
-
|
165
|
-
Capability = Strongbolt::Capability unless defined? Capability
|
data/lib/strongbolt/engine.rb
CHANGED
data/lib/strongbolt/role.rb
CHANGED
@@ -10,7 +10,7 @@ module Strongbolt
|
|
10
10
|
:dependent => :restrict_with_exception,
|
11
11
|
:inverse_of => :role
|
12
12
|
has_many :user_groups, :through => :roles_user_groups
|
13
|
-
|
13
|
+
|
14
14
|
has_many :users, through: :user_groups
|
15
15
|
|
16
16
|
has_many :capabilities_roles,
|
@@ -31,7 +31,7 @@ module Strongbolt
|
|
31
31
|
Strongbolt::Capability.joins(:roles)
|
32
32
|
.where("strongbolt_roles.lft < :lft AND strongbolt_roles.rgt > :rgt", lft: lft, rgt: rgt)
|
33
33
|
.distinct
|
34
|
-
|
34
|
+
end
|
35
35
|
|
36
36
|
private
|
37
37
|
|
@@ -42,5 +42,3 @@ module Strongbolt
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
end
|
45
|
-
|
46
|
-
Role = Strongbolt::Role unless defined? Role
|
@@ -5,11 +5,11 @@ module Strongbolt
|
|
5
5
|
belongs_to :user_group,
|
6
6
|
:class_name => "Strongbolt::UserGroup",
|
7
7
|
:inverse_of => :roles_user_groups
|
8
|
-
|
8
|
+
|
9
9
|
belongs_to :role,
|
10
10
|
:class_name => "Strongbolt::Role",
|
11
11
|
:inverse_of => :roles_user_groups
|
12
12
|
|
13
13
|
validates_presence_of :user_group, :role
|
14
14
|
end
|
15
|
-
end
|
15
|
+
end
|
@@ -91,30 +91,30 @@ module Strongbolt
|
|
91
91
|
else
|
92
92
|
raise DirectAssociationNotConfigured, "Class #{klass.name} is 1 degree from #{self.name} but the association isn't configured, you should implement it before using tenant method"
|
93
93
|
end
|
94
|
-
|
94
|
+
|
95
95
|
# The coming class has a relationship to the tenant
|
96
96
|
else
|
97
97
|
# If already created, we don't need to go further
|
98
98
|
return singular_association_name if klass.new.respond_to?(singular_association_name)
|
99
99
|
return plural_association_name if klass.new.respond_to?(plural_association_name)
|
100
|
-
|
100
|
+
|
101
101
|
# Inverse association
|
102
102
|
inverse = inverse_of(association)
|
103
|
-
|
103
|
+
|
104
104
|
# If no inverse, we cannot go further
|
105
105
|
if inverse.nil?
|
106
106
|
raise InverseAssociationNotConfigured, "Assocation #{association.name} on #{association.klass.name} could not be configured correctly as no inverse has been found"
|
107
107
|
elsif inverse.options.has_key? :polymorphic
|
108
108
|
return nil
|
109
109
|
end
|
110
|
-
|
110
|
+
|
111
111
|
|
112
112
|
# Common options
|
113
113
|
options = {
|
114
114
|
through: inverse.name,
|
115
115
|
autosave: false
|
116
116
|
}
|
117
|
-
|
117
|
+
|
118
118
|
# If the target is linked through some sort of has_many
|
119
119
|
if link == plural_association_name || inverse.collection?
|
120
120
|
# Has many
|
@@ -123,7 +123,7 @@ module Strongbolt
|
|
123
123
|
# Setup the scope with_name_of_plural_associations
|
124
124
|
# Current tenant table name
|
125
125
|
klass.has_many assoc, options
|
126
|
-
|
126
|
+
|
127
127
|
Strongbolt.logger.debug "#{klass.name} has_many #{plural_association_name} through: #{options[:through]}\n\n"
|
128
128
|
|
129
129
|
# Otherwise, it's linked through a has one
|
@@ -133,7 +133,7 @@ module Strongbolt
|
|
133
133
|
# Setup the association
|
134
134
|
# Setup the scope with_name_of_plural_associations
|
135
135
|
klass.has_one assoc, options
|
136
|
-
|
136
|
+
|
137
137
|
Strongbolt.logger.debug "#{klass.name} has_one #{singular_association_name} through: #{options[:through]}\n\n"
|
138
138
|
end
|
139
139
|
end
|
@@ -177,7 +177,7 @@ module Strongbolt
|
|
177
177
|
#
|
178
178
|
#
|
179
179
|
def create_users_tenant_subclass
|
180
|
-
unless Strongbolt.const_defined?(
|
180
|
+
unless Strongbolt.const_defined?(users_tenants_subclass_name)
|
181
181
|
users_tenant_subclass = Class.new(Strongbolt::UsersTenant)
|
182
182
|
users_tenant_subclass.class_eval <<-RUBY
|
183
183
|
# Ensures permissions on UsersTenant are applied here
|
@@ -194,7 +194,7 @@ module Strongbolt
|
|
194
194
|
|
195
195
|
validates :#{singular_association_name}, :presence => true
|
196
196
|
RUBY
|
197
|
-
Strongbolt.const_set
|
197
|
+
Strongbolt.const_set users_tenants_subclass_name, users_tenant_subclass
|
198
198
|
end
|
199
199
|
end #/create_users_tenant_subclass
|
200
200
|
|
@@ -208,7 +208,7 @@ module Strongbolt
|
|
208
208
|
# Setup the association
|
209
209
|
# The first one should never be there before
|
210
210
|
user_class.has_many :"users_#{plural_association_name}",
|
211
|
-
:class_name => "Strongbolt
|
211
|
+
:class_name => "Strongbolt::#{users_tenants_subclass_name}",
|
212
212
|
:inverse_of => :user,
|
213
213
|
:dependent => :delete_all,
|
214
214
|
:foreign_key => :user_id
|
@@ -241,6 +241,18 @@ module Strongbolt
|
|
241
241
|
end
|
242
242
|
end #/setup_association_on_user
|
243
243
|
|
244
|
+
#
|
245
|
+
# returns the name of the subclass of Strongbolt::UsersTenant, containing
|
246
|
+
# the associations between users and the tenant model this is running in.
|
247
|
+
#
|
248
|
+
def users_tenants_subclass_name
|
249
|
+
# If the name is something like Strongbolt::UserGroup, we have to remove the double colons.
|
250
|
+
# This results to 'StrongboltUserGroup'.
|
251
|
+
# The module name is left in the name, so that we won't have any collisions
|
252
|
+
# with the same class names in different modules.
|
253
|
+
"Users#{self.name.gsub('::', '')}"
|
254
|
+
end #/users_tenants_subclass_name
|
255
|
+
|
244
256
|
#
|
245
257
|
# Returns the inverse of specified association, using what's given
|
246
258
|
# as inverse_of or trying to guess it
|
@@ -292,13 +304,13 @@ module Strongbolt
|
|
292
304
|
end
|
293
305
|
|
294
306
|
end
|
295
|
-
|
307
|
+
|
296
308
|
module InstanceMethods
|
297
309
|
end
|
298
|
-
|
310
|
+
|
299
311
|
def self.included(receiver)
|
300
312
|
receiver.extend ClassMethods
|
301
313
|
receiver.send :include, InstanceMethods
|
302
314
|
end
|
303
315
|
end
|
304
|
-
end
|
316
|
+
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
module Strongbolt
|
2
2
|
module UserAbilities
|
3
3
|
module ClassMethods
|
4
|
-
|
4
|
+
|
5
5
|
end
|
6
|
-
|
6
|
+
|
7
7
|
module InstanceMethods
|
8
8
|
#----------------------------------------------------------#
|
9
9
|
# #
|
@@ -33,16 +33,16 @@ module Strongbolt
|
|
33
33
|
#
|
34
34
|
def can? action, instance, attrs = :any, all_instance = false
|
35
35
|
without_grant do
|
36
|
-
|
36
|
+
|
37
37
|
# Get the actual instance if we were given AR
|
38
38
|
instance = instance.try(:first) if instance.is_a?(ActiveRecord::Relation)
|
39
39
|
return false if instance.nil?
|
40
|
-
|
40
|
+
|
41
41
|
# We require this to be an *existing* user, that the action and attribute be symbols
|
42
42
|
# and that the instance is a class or a String
|
43
|
-
raise ArgumentError, "Action must be a symbol and instance must be Class, String, Symbol or AR" unless self.id.present? && action.is_a?(Symbol) &&
|
43
|
+
raise ArgumentError, "Action must be a symbol and instance must be Class, String, Symbol or AR" unless self.id.present? && action.is_a?(Symbol) &&
|
44
44
|
(instance.is_a?(ActiveRecord::Base) || instance.is_a?(Class) || instance.is_a?(String)) && attrs.is_a?(Symbol)
|
45
|
-
|
45
|
+
|
46
46
|
# Pre-populate all the capabilities into a results cache for quick lookup. Permissions for all "non-owned" objects are
|
47
47
|
# immediately available; additional lookups are required for owned objects (e.g. User, CheckoutBag, etc.).
|
48
48
|
# The results cache key is formatted as "action model attribute" (attribute can be any, all or an actual attribute)
|
@@ -61,11 +61,11 @@ module Strongbolt
|
|
61
61
|
# if we don't need it, so just defer until we determine there's an actual need
|
62
62
|
model_name = instance
|
63
63
|
end
|
64
|
-
|
64
|
+
|
65
65
|
# Look up the various possible valid entries in the cache that would allow us to see this
|
66
66
|
return capability_in_cache?(action, instance, model_name, attrs, all_instance)
|
67
67
|
|
68
|
-
end #end w/o grant
|
68
|
+
end #end w/o grant
|
69
69
|
end
|
70
70
|
|
71
71
|
#
|
@@ -93,14 +93,14 @@ module Strongbolt
|
|
93
93
|
#
|
94
94
|
def populate_capabilities_cache
|
95
95
|
beginning = Time.now
|
96
|
-
|
96
|
+
|
97
97
|
@results_cache ||= {}
|
98
98
|
@model_ancestor_cache ||= {}
|
99
99
|
|
100
100
|
# User can find itself by default
|
101
101
|
@results_cache["findUserany-any"] = true
|
102
102
|
@results_cache["findUserany-#{id}"] = true
|
103
|
-
|
103
|
+
|
104
104
|
#
|
105
105
|
# Store every capability fetched
|
106
106
|
#
|
@@ -108,7 +108,7 @@ module Strongbolt
|
|
108
108
|
|
109
109
|
k = "#{capability.action}#{capability.model}"
|
110
110
|
attr_k = capability.attr || 'all'
|
111
|
-
|
111
|
+
|
112
112
|
@results_cache["#{k}#{attr_k}-any"] = true
|
113
113
|
@results_cache["#{k}any-any"] = true
|
114
114
|
|
@@ -137,7 +137,7 @@ module Strongbolt
|
|
137
137
|
end # End each capability
|
138
138
|
|
139
139
|
Strongbolt.logger.info "Populated capabilities in #{(Time.now - beginning)*1000}ms"
|
140
|
-
|
140
|
+
|
141
141
|
@results_cache
|
142
142
|
end # End Populate capabilities Cache
|
143
143
|
|
@@ -150,10 +150,10 @@ module Strongbolt
|
|
150
150
|
# Checks if the user can perform 'action' on 'instance' #
|
151
151
|
# #
|
152
152
|
#----------------------------------------------------------#
|
153
|
-
|
153
|
+
|
154
154
|
def capability_in_cache?(action, instance, model_name, attrs = :any, all_instance = false)
|
155
155
|
action_model = "#{action}#{model_name}"
|
156
|
-
|
156
|
+
|
157
157
|
Strongbolt.logger.warn "User has no results cache" if @results_cache.empty?
|
158
158
|
Strongbolt.logger.debug { "Authorizing user to perform #{action} on #{instance.inspect}" }
|
159
159
|
|
@@ -162,13 +162,13 @@ module Strongbolt
|
|
162
162
|
# First, check if we have a hash/cache hit for User being able to do this action to every instance of the model/class
|
163
163
|
return true if @results_cache["#{action_model}all-all"] #Access to all attributes on ENTIRE class?
|
164
164
|
return true if @results_cache["#{action_model}#{attrs}-all"] #Access to this specific attribute on ENTIRE class?
|
165
|
-
|
165
|
+
|
166
166
|
# If we're checking on a specific instance of the class, not the general model,
|
167
167
|
# append the id to the key
|
168
168
|
id = instance.try(:id)
|
169
169
|
return true if @results_cache["#{action_model}all-#{id}"] # Access to all this instance's attributes?
|
170
170
|
return true if @results_cache["#{action_model}#{attrs}-#{id}"] #Access to this instance's attribute?
|
171
|
-
|
171
|
+
|
172
172
|
# Checking ownership and tenant access
|
173
173
|
# Block access for non tenanted instance
|
174
174
|
valid_tenants = has_access_to_tenants?(instance)
|
@@ -209,14 +209,14 @@ module Strongbolt
|
|
209
209
|
return true if @results_cache["#{action_model}#{attrs}-any"] && ! all_instance #Access to this specific attribute on at least once instance?
|
210
210
|
end
|
211
211
|
#logger.info "Cache miss for checking access to #{key}"
|
212
|
-
|
212
|
+
|
213
213
|
return false
|
214
214
|
end
|
215
215
|
|
216
216
|
#
|
217
217
|
# Checks if the instance given fulfills tenant management rules
|
218
218
|
#
|
219
|
-
def has_access_to_tenants? instance, tenants = nil
|
219
|
+
def has_access_to_tenants? instance, tenants = nil
|
220
220
|
# If no tenants list given, we take all
|
221
221
|
tenants ||= Strongbolt.tenants
|
222
222
|
# Populate the cache if needed
|
@@ -256,7 +256,7 @@ module Strongbolt
|
|
256
256
|
return if @tenants_cache.present?
|
257
257
|
|
258
258
|
Strongbolt.logger.debug "Populating tenants cache for user #{self.id}"
|
259
|
-
|
259
|
+
|
260
260
|
@tenants_cache = {}
|
261
261
|
# Go over each tenants
|
262
262
|
Strongbolt.tenants.each do |tenant|
|
@@ -267,7 +267,7 @@ module Strongbolt
|
|
267
267
|
|
268
268
|
|
269
269
|
end # End InstanceMethods
|
270
|
-
|
270
|
+
|
271
271
|
def self.included(receiver)
|
272
272
|
receiver.extend ClassMethods
|
273
273
|
receiver.send :include, InstanceMethods
|
@@ -279,7 +279,7 @@ module Strongbolt
|
|
279
279
|
:inverse_of => :user,
|
280
280
|
:foreign_key => :user_id
|
281
281
|
has_many :user_groups, :through => :user_groups_users
|
282
|
-
|
282
|
+
|
283
283
|
has_many :roles, through: :user_groups
|
284
284
|
end
|
285
285
|
|
@@ -289,4 +289,4 @@ module Strongbolt
|
|
289
289
|
end
|
290
290
|
end
|
291
291
|
end
|
292
|
-
end
|
292
|
+
end
|
@@ -6,7 +6,7 @@ module Strongbolt
|
|
6
6
|
:dependent => :restrict_with_exception,
|
7
7
|
:inverse_of => :user_group
|
8
8
|
has_many :users, :through => :user_groups_users
|
9
|
-
|
9
|
+
|
10
10
|
has_many :roles_user_groups,
|
11
11
|
:class_name => "Strongbolt::RolesUserGroup",
|
12
12
|
:dependent => :delete_all,
|
@@ -20,5 +20,3 @@ module Strongbolt
|
|
20
20
|
|
21
21
|
end
|
22
22
|
end
|
23
|
-
|
24
|
-
UserGroup = Strongbolt::UserGroup unless defined? UserGroup
|
@@ -5,7 +5,7 @@ module Strongbolt
|
|
5
5
|
belongs_to :user_group,
|
6
6
|
:class_name => "Strongbolt::UserGroup",
|
7
7
|
:inverse_of => :user_groups_users
|
8
|
-
|
8
|
+
|
9
9
|
belongs_to :user,
|
10
10
|
:class_name => Configuration.user_class,
|
11
11
|
:foreign_key => :user_id,
|
@@ -13,4 +13,4 @@ module Strongbolt
|
|
13
13
|
|
14
14
|
validates_presence_of :user_group, :user
|
15
15
|
end
|
16
|
-
end
|
16
|
+
end
|
data/lib/strongbolt/version.rb
CHANGED
@@ -7,23 +7,23 @@ namespace :strongbolt do
|
|
7
7
|
#
|
8
8
|
# Creates capabilities for all models/actions
|
9
9
|
#
|
10
|
-
Capability.models.each do |model|
|
11
|
-
Capability::Actions.each do |action|
|
12
|
-
Capability.where(model: model, action: action,
|
10
|
+
Strongbolt::Capability.models.each do |model|
|
11
|
+
Strongbolt::Capability::Actions.each do |action|
|
12
|
+
Strongbolt::Capability.where(model: model, action: action,
|
13
13
|
require_tenant_access: false).first_or_create
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
17
|
# The role
|
18
|
-
role = Role.create! name: "FULL ACCESS (TEMPORARY)"
|
19
|
-
role.capabilities = Capability.all
|
18
|
+
role = Strongbolt::Role.create! name: "FULL ACCESS (TEMPORARY)"
|
19
|
+
role.capabilities = Strongbolt::Capability.all
|
20
20
|
|
21
21
|
# The user group
|
22
|
-
ug = UserGroup.create! name: "FULL ACCESS USERS (TEMPORARY)"
|
22
|
+
ug = Strongbolt::UserGroup.create! name: "FULL ACCESS USERS (TEMPORARY)"
|
23
23
|
ug.roles << role
|
24
24
|
|
25
25
|
# Assign to all users
|
26
26
|
User.all.each { |user| user.user_groups << ug }
|
27
27
|
end
|
28
28
|
end
|
29
|
-
end
|
29
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe Strongbolt::Configuration do
|
4
|
-
|
4
|
+
|
5
5
|
|
6
6
|
#
|
7
7
|
# User class
|
8
8
|
#
|
9
9
|
describe "user class" do
|
10
|
-
|
10
|
+
|
11
11
|
it "should default to User" do
|
12
12
|
expect(Strongbolt::Configuration.user_class).to eq "User"
|
13
13
|
end
|
@@ -29,7 +29,7 @@ describe Strongbolt::Configuration do
|
|
29
29
|
# Setting up tenants
|
30
30
|
#
|
31
31
|
describe 'tenants=' do
|
32
|
-
|
32
|
+
|
33
33
|
before do
|
34
34
|
define_model "Model" do
|
35
35
|
self.table_name = "models"
|
@@ -59,11 +59,11 @@ describe Strongbolt::Configuration do
|
|
59
59
|
Strongbolt::Configuration.models = "OtherModel", "Model"
|
60
60
|
end
|
61
61
|
after do
|
62
|
-
Capability.models = nil
|
62
|
+
Strongbolt::Capability.models = nil
|
63
63
|
end
|
64
64
|
|
65
65
|
it "should set Capability::Models" do
|
66
|
-
expect(Capability.models).to eq ["Model", "OtherModel", "Strongbolt::Capability", "Strongbolt::Role", "Strongbolt::UserGroup", "Strongbolt::UsersTenant"]
|
66
|
+
expect(Strongbolt::Capability.models).to eq ["Model", "OtherModel", "Strongbolt::Capability", "Strongbolt::Role", "Strongbolt::UserGroup", "Strongbolt::UsersTenant"]
|
67
67
|
end
|
68
68
|
|
69
69
|
context "when adding other models" do
|
@@ -72,7 +72,7 @@ describe Strongbolt::Configuration do
|
|
72
72
|
end
|
73
73
|
|
74
74
|
it "should merge with current models" do
|
75
|
-
expect(Capability.models).to eq ["LastModel", "Model", "OtherModel", "Strongbolt::Capability", "Strongbolt::Role", "Strongbolt::UserGroup", "Strongbolt::UsersTenant"]
|
75
|
+
expect(Strongbolt::Capability.models).to eq ["LastModel", "Model", "OtherModel", "Strongbolt::Capability", "Strongbolt::Role", "Strongbolt::UserGroup", "Strongbolt::UsersTenant"]
|
76
76
|
end
|
77
77
|
end
|
78
78
|
|
@@ -82,7 +82,7 @@ describe Strongbolt::Configuration do
|
|
82
82
|
end
|
83
83
|
|
84
84
|
it "should merge with current models" do
|
85
|
-
expect(Capability.models).to eq ["BottomModel", "Model", "OtherModel", "Strongbolt::Capability", "Strongbolt::Role", "Strongbolt::UserGroup", "Strongbolt::UsersTenant"]
|
85
|
+
expect(Strongbolt::Capability.models).to eq ["BottomModel", "Model", "OtherModel", "Strongbolt::Capability", "Strongbolt::Role", "Strongbolt::UserGroup", "Strongbolt::UsersTenant"]
|
86
86
|
end
|
87
87
|
end
|
88
88
|
end #/models=
|
@@ -93,7 +93,7 @@ describe Strongbolt::Configuration do
|
|
93
93
|
# Setting default permissions
|
94
94
|
#
|
95
95
|
describe "default_capabilities=" do
|
96
|
-
|
96
|
+
|
97
97
|
before do
|
98
98
|
Strongbolt::Configuration.default_capabilities = [
|
99
99
|
{:model => "User", :actions => :all},
|
@@ -110,10 +110,10 @@ describe Strongbolt::Configuration do
|
|
110
110
|
|
111
111
|
it "should return Capability" do
|
112
112
|
Strongbolt::Configuration.default_capabilities.each do |c|
|
113
|
-
expect(c).to be_a Capability
|
113
|
+
expect(c).to be_a Strongbolt::Capability
|
114
114
|
end
|
115
115
|
end
|
116
116
|
|
117
117
|
end
|
118
118
|
|
119
|
-
end
|
119
|
+
end
|
data/strongbolt.gemspec
CHANGED
@@ -25,8 +25,8 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.add_development_dependency "rails", "~> 4.1.0"
|
26
26
|
spec.add_development_dependency "bundler", "> 1.7.0"
|
27
27
|
spec.add_development_dependency "rake"
|
28
|
-
spec.add_development_dependency 'sqlite3'
|
29
|
-
spec.add_development_dependency 'shoulda-matchers'
|
28
|
+
spec.add_development_dependency 'sqlite3'
|
29
|
+
spec.add_development_dependency 'shoulda-matchers', '~> 2.7.0'
|
30
30
|
spec.add_development_dependency 'fuubar'
|
31
31
|
spec.add_development_dependency 'rspec-rails', '~> 3.1.0'
|
32
32
|
spec.add_development_dependency 'fabrication'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: strongbolt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thomas Césaré-Herriau
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-
|
12
|
+
date: 2016-05-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: awesome_nested_set
|
@@ -99,30 +99,30 @@ dependencies:
|
|
99
99
|
name: sqlite3
|
100
100
|
requirement: !ruby/object:Gem::Requirement
|
101
101
|
requirements:
|
102
|
-
- -
|
102
|
+
- - ">="
|
103
103
|
- !ruby/object:Gem::Version
|
104
|
-
version:
|
104
|
+
version: '0'
|
105
105
|
type: :development
|
106
106
|
prerelease: false
|
107
107
|
version_requirements: !ruby/object:Gem::Requirement
|
108
108
|
requirements:
|
109
|
-
- -
|
109
|
+
- - ">="
|
110
110
|
- !ruby/object:Gem::Version
|
111
|
-
version:
|
111
|
+
version: '0'
|
112
112
|
- !ruby/object:Gem::Dependency
|
113
113
|
name: shoulda-matchers
|
114
114
|
requirement: !ruby/object:Gem::Requirement
|
115
115
|
requirements:
|
116
|
-
- - "
|
116
|
+
- - "~>"
|
117
117
|
- !ruby/object:Gem::Version
|
118
|
-
version:
|
118
|
+
version: 2.7.0
|
119
119
|
type: :development
|
120
120
|
prerelease: false
|
121
121
|
version_requirements: !ruby/object:Gem::Requirement
|
122
122
|
requirements:
|
123
|
-
- - "
|
123
|
+
- - "~>"
|
124
124
|
- !ruby/object:Gem::Version
|
125
|
-
version:
|
125
|
+
version: 2.7.0
|
126
126
|
- !ruby/object:Gem::Dependency
|
127
127
|
name: fuubar
|
128
128
|
requirement: !ruby/object:Gem::Requirement
|