rbacan 0.4.0 → 0.5.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 +4 -4
- data/CHANGELOG.md +25 -0
- data/README.md +97 -15
- data/lib/generators/install/templates/rbacan.rb +25 -25
- data/lib/rbacan/authorizable.rb +15 -0
- data/lib/rbacan/authorization.rb +37 -9
- data/lib/rbacan/host_authorization.rb +165 -0
- data/lib/rbacan/not_authorized.rb +10 -3
- data/lib/rbacan/permittable.rb +39 -28
- data/lib/rbacan/roles_and_permissions.rb +12 -4
- data/lib/rbacan/route_constraint.rb +21 -18
- data/lib/rbacan/version.rb +1 -1
- data/lib/rbacan/view_helpers.rb +13 -8
- data/lib/rbacan.rb +26 -4
- metadata +4 -12
- data/.gitignore +0 -14
- data/.rspec +0 -3
- data/.travis.yml +0 -7
- data/CLAUDE.md +0 -51
- data/Gemfile +0 -4
- data/Gemfile.lock +0 -351
- data/Rakefile +0 -6
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/rbacan.gemspec +0 -39
data/lib/rbacan/permittable.rb
CHANGED
|
@@ -14,20 +14,23 @@ module Rbacan
|
|
|
14
14
|
through: :user_roles
|
|
15
15
|
|
|
16
16
|
# Returns users that have the given role (by name).
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
scope :with_role, lambda { |role_name|
|
|
18
|
+
Rbacan.ensure_legacy_mode!(:with_role)
|
|
19
|
+
joins(:roles).where(Rbacan.role_table => { Rbacan.role_key => role_name.to_s })
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
# Returns users that have the given permission via any of their roles.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
scope :with_permission, lambda { |permission_name|
|
|
24
|
+
Rbacan.ensure_legacy_mode!(:with_permission)
|
|
25
|
+
joins(roles: { role_permissions: :permission })
|
|
26
|
+
.where(Rbacan.permission_table => { Rbacan.permission_key => permission_name.to_s })
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
# Assigns a role to the user. Idempotent — safe to call multiple times.
|
|
28
30
|
# When tenant_scoped is enabled, pass tenant_id: to scope the assignment.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
def assign_role(role_name, tenant_id: nil)
|
|
32
|
+
Rbacan.ensure_legacy_mode!(:assign_role)
|
|
33
|
+
assigned_role = Rbacan.role_class.constantize.find_by(Rbacan.role_key => role_name.to_s)
|
|
31
34
|
raise ArgumentError, "Role '#{role_name}' not found" unless assigned_role
|
|
32
35
|
|
|
33
36
|
attrs = { role_id: assigned_role.id }
|
|
@@ -37,8 +40,9 @@ module Rbacan
|
|
|
37
40
|
|
|
38
41
|
# Removes a role from the user.
|
|
39
42
|
# When tenant_scoped is enabled, pass tenant_id: to remove from a specific tenant.
|
|
40
|
-
|
|
41
|
-
|
|
43
|
+
def remove_role(role_name, tenant_id: nil)
|
|
44
|
+
Rbacan.ensure_legacy_mode!(:remove_role)
|
|
45
|
+
removed_role = Rbacan.role_class.constantize.find_by(Rbacan.role_key => role_name.to_s)
|
|
42
46
|
return unless removed_role
|
|
43
47
|
|
|
44
48
|
scope = user_roles.where(role_id: removed_role.id)
|
|
@@ -47,58 +51,65 @@ module Rbacan
|
|
|
47
51
|
end
|
|
48
52
|
|
|
49
53
|
# Returns true if the user has the named permission via any of their roles.
|
|
50
|
-
|
|
51
|
-
|
|
54
|
+
def can?(permission_name)
|
|
55
|
+
Rbacan.ensure_legacy_mode!(:can?)
|
|
56
|
+
roles
|
|
52
57
|
.joins(role_permissions: :permission)
|
|
53
|
-
|
|
58
|
+
.where(Rbacan.permission_table => { Rbacan.permission_key => permission_name.to_s })
|
|
54
59
|
.exists?
|
|
55
60
|
end
|
|
56
61
|
|
|
57
62
|
# Returns true if the user has the named permission in a specific tenant context.
|
|
58
63
|
# Checks both global role assignments (tenant_id NULL) and tenant-specific ones.
|
|
59
|
-
|
|
60
|
-
|
|
64
|
+
def can_in_tenant?(permission_name, tenant_id)
|
|
65
|
+
Rbacan.ensure_legacy_mode!(:can_in_tenant?)
|
|
66
|
+
roles
|
|
61
67
|
.joins(role_permissions: :permission)
|
|
62
|
-
|
|
68
|
+
.where(Rbacan.permission_table => { Rbacan.permission_key => permission_name.to_s })
|
|
63
69
|
.where(Rbacan.user_role_table => { tenant_id: [tenant_id, nil] })
|
|
64
70
|
.exists?
|
|
65
71
|
end
|
|
66
72
|
|
|
67
73
|
# Returns true if the user has the named role.
|
|
68
|
-
|
|
69
|
-
|
|
74
|
+
def has_role?(role_name)
|
|
75
|
+
Rbacan.ensure_legacy_mode!(:has_role?)
|
|
76
|
+
roles.where(Rbacan.role_key => role_name.to_s).exists?
|
|
70
77
|
end
|
|
71
78
|
|
|
72
79
|
# Returns true if the user has the named role in a specific tenant context.
|
|
73
80
|
# Checks both global role assignments (tenant_id NULL) and tenant-specific ones.
|
|
74
|
-
|
|
75
|
-
|
|
81
|
+
def has_role_in_tenant?(role_name, tenant_id)
|
|
82
|
+
Rbacan.ensure_legacy_mode!(:has_role_in_tenant?)
|
|
83
|
+
user_roles
|
|
76
84
|
.joins(:role)
|
|
77
|
-
|
|
85
|
+
.where(Rbacan.role_table => { Rbacan.role_key => role_name.to_s })
|
|
78
86
|
.where(Rbacan.user_role_table => { tenant_id: [tenant_id, nil] })
|
|
79
87
|
.exists?
|
|
80
88
|
end
|
|
81
89
|
|
|
82
90
|
# Returns true if the user has ANY of the listed roles.
|
|
83
|
-
|
|
84
|
-
|
|
91
|
+
def has_any_role?(*role_names)
|
|
92
|
+
Rbacan.ensure_legacy_mode!(:has_any_role?)
|
|
93
|
+
roles.where(Rbacan.role_key => role_names.map(&:to_s)).exists?
|
|
85
94
|
end
|
|
86
95
|
|
|
87
96
|
# Returns true if the user has ALL of the listed permissions.
|
|
88
|
-
|
|
89
|
-
|
|
97
|
+
def can_all?(*permission_names)
|
|
98
|
+
Rbacan.ensure_legacy_mode!(:can_all?)
|
|
99
|
+
names = permission_names.map(&:to_s)
|
|
90
100
|
roles
|
|
91
101
|
.joins(role_permissions: :permission)
|
|
92
|
-
|
|
93
|
-
|
|
102
|
+
.where(Rbacan.permission_table => { Rbacan.permission_key => names })
|
|
103
|
+
.select("#{Rbacan.permission_table}.#{Rbacan.permission_key}")
|
|
94
104
|
.distinct
|
|
95
105
|
.count == names.uniq.size
|
|
96
106
|
end
|
|
97
107
|
|
|
98
108
|
# Returns roles assigned to this user for a specific tenant.
|
|
99
109
|
# Includes global role assignments (tenant_id NULL).
|
|
100
|
-
|
|
101
|
-
|
|
110
|
+
def roles_for_tenant(tenant_id)
|
|
111
|
+
Rbacan.ensure_legacy_mode!(:roles_for_tenant)
|
|
112
|
+
roles
|
|
102
113
|
.where(Rbacan.user_role_table => { tenant_id: [tenant_id, nil] })
|
|
103
114
|
end
|
|
104
115
|
end
|
|
@@ -3,25 +3,33 @@ module Rbacan
|
|
|
3
3
|
|
|
4
4
|
# Creates roles by name. Idempotent — skips existing ones.
|
|
5
5
|
def self.create_roles(roles)
|
|
6
|
+
Rbacan.ensure_legacy_mode!(:create_roles)
|
|
7
|
+
|
|
6
8
|
roles.each do |role|
|
|
7
|
-
Rbacan.role_class.constantize.find_or_create_by(
|
|
9
|
+
Rbacan.role_class.constantize.find_or_create_by(Rbacan.role_key => role.to_s)
|
|
8
10
|
end
|
|
9
11
|
end
|
|
10
12
|
|
|
11
13
|
# Creates permissions by name. Idempotent — skips existing ones.
|
|
12
14
|
def self.create_permissions(permissions)
|
|
15
|
+
Rbacan.ensure_legacy_mode!(:create_permissions)
|
|
16
|
+
|
|
13
17
|
permissions.each do |permission|
|
|
14
|
-
Rbacan.permission_class.constantize.find_or_create_by(
|
|
18
|
+
Rbacan.permission_class.constantize.find_or_create_by(Rbacan.permission_key => permission.to_s)
|
|
15
19
|
end
|
|
16
20
|
end
|
|
17
21
|
|
|
18
22
|
# Assigns a list of permissions to a role. Idempotent — skips duplicates.
|
|
19
23
|
def self.assign_permissions_to_role(role_name, permissions)
|
|
20
|
-
|
|
24
|
+
Rbacan.ensure_legacy_mode!(:assign_permissions_to_role)
|
|
25
|
+
|
|
26
|
+
chosen_role = Rbacan.role_class.constantize.find_by(Rbacan.role_key => role_name.to_s)
|
|
21
27
|
return unless chosen_role
|
|
22
28
|
|
|
23
29
|
permissions.each do |permission|
|
|
24
|
-
given_permission = Rbacan.permission_class.constantize.
|
|
30
|
+
given_permission = Rbacan.permission_class.constantize.find_by(
|
|
31
|
+
Rbacan.permission_key => permission.to_s
|
|
32
|
+
)
|
|
25
33
|
next unless given_permission
|
|
26
34
|
|
|
27
35
|
Rbacan.role_permission_class.constantize.find_or_create_by(
|
|
@@ -1,30 +1,22 @@
|
|
|
1
1
|
module Rbacan
|
|
2
2
|
class RouteConstraint
|
|
3
|
-
|
|
4
|
-
#
|
|
5
|
-
# Usage in config/routes.rb:
|
|
6
|
-
# constraints Rbacan::RouteConstraint.new(role: :admin) do
|
|
7
|
-
# namespace :admin do
|
|
8
|
-
# resources :users
|
|
9
|
-
# end
|
|
10
|
-
# end
|
|
11
|
-
#
|
|
12
|
-
# constraints Rbacan::RouteConstraint.new(permission: :access_admin_panel) do
|
|
13
|
-
# ...
|
|
14
|
-
# end
|
|
15
|
-
def initialize(role: nil, permission: nil)
|
|
3
|
+
def initialize(role: nil, permission: nil, user_resolver: nil, context_resolver: nil)
|
|
16
4
|
if role.nil? && permission.nil?
|
|
17
|
-
raise ArgumentError,
|
|
5
|
+
raise ArgumentError, 'Provide exactly one role: or permission:'
|
|
18
6
|
end
|
|
19
7
|
if role && permission
|
|
20
|
-
raise ArgumentError,
|
|
8
|
+
raise ArgumentError, 'Provide exactly one role: or permission:, not both'
|
|
21
9
|
end
|
|
22
10
|
|
|
23
|
-
@role
|
|
11
|
+
@role = role&.to_s
|
|
24
12
|
@permission = permission&.to_s
|
|
13
|
+
@user_resolver = user_resolver
|
|
14
|
+
@context_resolver = context_resolver
|
|
25
15
|
end
|
|
26
16
|
|
|
27
17
|
def matches?(request)
|
|
18
|
+
return hardened_match?(request) unless Rbacan.legacy_mode
|
|
19
|
+
|
|
28
20
|
user = current_user_from(request)
|
|
29
21
|
return false unless user
|
|
30
22
|
|
|
@@ -33,12 +25,23 @@ module Rbacan
|
|
|
33
25
|
|
|
34
26
|
private
|
|
35
27
|
|
|
28
|
+
def hardened_match?(request)
|
|
29
|
+
return false unless @user_resolver&.respond_to?(:call) && @context_resolver&.respond_to?(:call)
|
|
30
|
+
|
|
31
|
+
Rbacan.authorized?(
|
|
32
|
+
user: @user_resolver.call(request),
|
|
33
|
+
permission: @permission,
|
|
34
|
+
role: @role,
|
|
35
|
+
context: @context_resolver.call(request)
|
|
36
|
+
)
|
|
37
|
+
rescue Rbacan::ConfigurationError, ArgumentError
|
|
38
|
+
false
|
|
39
|
+
end
|
|
40
|
+
|
|
36
41
|
def current_user_from(request)
|
|
37
|
-
# Warden (Devise) path — most common, no extra query needed.
|
|
38
42
|
warden = request.env['warden']
|
|
39
43
|
return warden.user if warden&.authenticated?
|
|
40
44
|
|
|
41
|
-
# Fallback: manual session lookup for apps not using Warden.
|
|
42
45
|
user_id = request.session[:user_id] || request.session['user_id']
|
|
43
46
|
return nil unless user_id
|
|
44
47
|
|
data/lib/rbacan/version.rb
CHANGED
data/lib/rbacan/view_helpers.rb
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
module Rbacan
|
|
2
2
|
module ViewHelpers
|
|
3
|
-
# Renders the block only
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
# Renders the block only when the host authorization adapter permits it.
|
|
4
|
+
def authorized?(permission, context: nil, &block)
|
|
5
|
+
allowed = if Rbacan.legacy_mode
|
|
6
|
+
current_user&.can?(permission.to_s)
|
|
7
|
+
else
|
|
8
|
+
Rbacan.authorized?(
|
|
9
|
+
user: current_user,
|
|
10
|
+
permission: permission,
|
|
11
|
+
context: context || rbacan_authorization_context
|
|
12
|
+
)
|
|
13
|
+
end
|
|
14
|
+
return unless allowed
|
|
15
|
+
|
|
11
16
|
capture(&block) if block_given?
|
|
12
17
|
end
|
|
13
18
|
end
|
data/lib/rbacan.rb
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
require 'rbacan/version'
|
|
2
2
|
require 'rbacan/not_authorized'
|
|
3
|
+
require 'rbacan/host_authorization'
|
|
4
|
+
require 'rbacan/authorizable'
|
|
3
5
|
require 'rbacan/permittable'
|
|
4
6
|
require 'rbacan/engine'
|
|
5
7
|
require 'rbacan/roles_and_permissions'
|
|
@@ -8,13 +10,25 @@ require 'rbacan/view_helpers'
|
|
|
8
10
|
require 'rbacan/route_constraint'
|
|
9
11
|
|
|
10
12
|
module Rbacan
|
|
13
|
+
mattr_accessor :authorization_adapter
|
|
14
|
+
@@authorization_adapter = nil
|
|
15
|
+
|
|
16
|
+
mattr_accessor :assignment_adapter
|
|
17
|
+
@@assignment_adapter = nil
|
|
18
|
+
|
|
19
|
+
# Legacy Active Record mutation/query APIs are opt-in in the hardened API.
|
|
20
|
+
mattr_accessor :legacy_mode
|
|
21
|
+
@@legacy_mode = false
|
|
22
|
+
|
|
11
23
|
mattr_accessor :permittable_class
|
|
12
24
|
@@permittable_class = 'User'
|
|
13
25
|
|
|
14
26
|
mattr_accessor :role_class
|
|
15
27
|
mattr_accessor :role_table
|
|
28
|
+
mattr_accessor :role_key
|
|
16
29
|
@@role_class = 'Rbacan::Role'
|
|
17
30
|
@@role_table = 'roles'
|
|
31
|
+
@@role_key = :name
|
|
18
32
|
|
|
19
33
|
mattr_accessor :user_role_class
|
|
20
34
|
mattr_accessor :user_role_table
|
|
@@ -23,8 +37,10 @@ module Rbacan
|
|
|
23
37
|
|
|
24
38
|
mattr_accessor :permission_class
|
|
25
39
|
mattr_accessor :permission_table
|
|
40
|
+
mattr_accessor :permission_key
|
|
26
41
|
@@permission_class = 'Rbacan::Permission'
|
|
27
42
|
@@permission_table = 'permissions'
|
|
43
|
+
@@permission_key = :name
|
|
28
44
|
|
|
29
45
|
mattr_accessor :role_permission_class
|
|
30
46
|
mattr_accessor :role_permission_table
|
|
@@ -67,16 +83,22 @@ module Rbacan
|
|
|
67
83
|
end
|
|
68
84
|
|
|
69
85
|
def self.create_role(role_name)
|
|
70
|
-
|
|
86
|
+
ensure_legacy_mode!(:create_role)
|
|
87
|
+
|
|
88
|
+
@@role_class.constantize.create(@@role_key => role_name.to_s)
|
|
71
89
|
end
|
|
72
90
|
|
|
73
91
|
def self.create_permission(permission_name)
|
|
74
|
-
|
|
92
|
+
ensure_legacy_mode!(:create_permission)
|
|
93
|
+
|
|
94
|
+
@@permission_class.constantize.create(@@permission_key => permission_name.to_s)
|
|
75
95
|
end
|
|
76
96
|
|
|
77
97
|
def self.assign_permission_to_role(role_name, permission_name)
|
|
78
|
-
|
|
79
|
-
|
|
98
|
+
ensure_legacy_mode!(:assign_permission_to_role)
|
|
99
|
+
|
|
100
|
+
chosen_role = @@role_class.constantize.find_by(@@role_key => role_name.to_s)
|
|
101
|
+
given_permission = @@permission_class.constantize.find_by(@@permission_key => permission_name.to_s)
|
|
80
102
|
@@role_permission_class.constantize.create(
|
|
81
103
|
role_id: chosen_role.id,
|
|
82
104
|
permission_id: given_permission.id
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rbacan
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- hamdi
|
|
@@ -147,24 +147,15 @@ executables: []
|
|
|
147
147
|
extensions: []
|
|
148
148
|
extra_rdoc_files: []
|
|
149
149
|
files:
|
|
150
|
-
- ".gitignore"
|
|
151
|
-
- ".rspec"
|
|
152
|
-
- ".travis.yml"
|
|
153
150
|
- CHANGELOG.md
|
|
154
|
-
- CLAUDE.md
|
|
155
151
|
- CODE_OF_CONDUCT.md
|
|
156
|
-
- Gemfile
|
|
157
|
-
- Gemfile.lock
|
|
158
152
|
- LICENSE.txt
|
|
159
153
|
- README.md
|
|
160
|
-
- Rakefile
|
|
161
154
|
- app/models/rbacan/application_record.rb
|
|
162
155
|
- app/models/rbacan/permission.rb
|
|
163
156
|
- app/models/rbacan/role.rb
|
|
164
157
|
- app/models/rbacan/role_permission.rb
|
|
165
158
|
- app/models/rbacan/user_role.rb
|
|
166
|
-
- bin/console
|
|
167
|
-
- bin/setup
|
|
168
159
|
- lib/generators/install/templates/copy_to_seeds.rb
|
|
169
160
|
- lib/generators/install/templates/create_permissions.rb
|
|
170
161
|
- lib/generators/install/templates/create_role_permissions.rb
|
|
@@ -173,15 +164,16 @@ files:
|
|
|
173
164
|
- lib/generators/install/templates/rbacan.rb
|
|
174
165
|
- lib/generators/rbacan/install_generator.rb
|
|
175
166
|
- lib/rbacan.rb
|
|
167
|
+
- lib/rbacan/authorizable.rb
|
|
176
168
|
- lib/rbacan/authorization.rb
|
|
177
169
|
- lib/rbacan/engine.rb
|
|
170
|
+
- lib/rbacan/host_authorization.rb
|
|
178
171
|
- lib/rbacan/not_authorized.rb
|
|
179
172
|
- lib/rbacan/permittable.rb
|
|
180
173
|
- lib/rbacan/roles_and_permissions.rb
|
|
181
174
|
- lib/rbacan/route_constraint.rb
|
|
182
175
|
- lib/rbacan/version.rb
|
|
183
176
|
- lib/rbacan/view_helpers.rb
|
|
184
|
-
- rbacan.gemspec
|
|
185
177
|
homepage: https://github.com/hamdi777/RBACan
|
|
186
178
|
licenses:
|
|
187
179
|
- MIT
|
|
@@ -203,7 +195,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
203
195
|
- !ruby/object:Gem::Version
|
|
204
196
|
version: '0'
|
|
205
197
|
requirements: []
|
|
206
|
-
rubygems_version:
|
|
198
|
+
rubygems_version: 4.0.16
|
|
207
199
|
specification_version: 4
|
|
208
200
|
summary: A gem to give permission access to users based on their roles
|
|
209
201
|
test_files: []
|
data/.gitignore
DELETED
data/.rspec
DELETED
data/.travis.yml
DELETED
data/CLAUDE.md
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
# CLAUDE.md
|
|
2
|
-
|
|
3
|
-
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
-
|
|
5
|
-
## Commands
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
bin/setup # install dependencies
|
|
9
|
-
rake spec # run all tests
|
|
10
|
-
bundle exec rspec spec/rbacan_spec.rb # run a single spec file
|
|
11
|
-
bundle exec rake install # install gem locally
|
|
12
|
-
bundle exec rake release # tag, push commits/tags, push .gem to RubyGems
|
|
13
|
-
gem build rbacan.gemspec # build .gem file manually
|
|
14
|
-
gem push rbacan-<version>.gem # push to RubyGems manually
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
## Architecture
|
|
18
|
-
|
|
19
|
-
This is a Rails engine gem that provides Role-Based Access Control (RBAC).
|
|
20
|
-
|
|
21
|
-
**Data model** — four tables managed by the gem's migrations:
|
|
22
|
-
- `roles` / `permissions` — named entities
|
|
23
|
-
- `role_permissions` — join table linking roles to permissions
|
|
24
|
-
- `user_roles` — join table linking the host app's user model to roles
|
|
25
|
-
|
|
26
|
-
**Entry points:**
|
|
27
|
-
- `lib/rbacan.rb` — main module; holds `mattr_accessor` config accessors and a `configure` block. All class names and table names are configurable here (defaults to `User`, `Rbacan::Role`, etc.).
|
|
28
|
-
- `lib/rbacan/permittable.rb` — `ActiveSupport::Concern` included in the host app's user model via `include Rbacan::Permittable`. Adds `assign_role`, `remove_role`, and `can?` instance methods.
|
|
29
|
-
- `lib/rbacan/roles_and_permissions.rb` — utility module (`RolesAndPermissions`) used in seeds to bulk-create roles/permissions and assign permissions to roles.
|
|
30
|
-
- `lib/rbacan/engine.rb` — Rails engine that auto-loads `app/models`.
|
|
31
|
-
|
|
32
|
-
**Generator** (`rails generate rbacan:install`) copies four migration files, `db/copy_to_seeds.rb`, and `config/initializers/rbacan.rb` into the host app.
|
|
33
|
-
|
|
34
|
-
**Configuration** (host app's `config/initializers/rbacan.rb`):
|
|
35
|
-
```ruby
|
|
36
|
-
Rbacan.configure do |config|
|
|
37
|
-
config.permittable_class = "User" # change if your user model has a different name
|
|
38
|
-
end
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
## Releasing a new version
|
|
42
|
-
|
|
43
|
-
1. Bump `lib/rbacan/version.rb`
|
|
44
|
-
2. `gem build rbacan.gemspec`
|
|
45
|
-
3. `gem push rbacan-<version>.gem`
|
|
46
|
-
|
|
47
|
-
RubyGems push host is `https://rubygems.org`. GitHub repo: `https://github.com/hamdi777/RBACan`.
|
|
48
|
-
|
|
49
|
-
## Known state
|
|
50
|
-
|
|
51
|
-
The spec suite has a placeholder test (`expect(false).to eq(true)`) in `spec/rbacan_spec.rb` that intentionally fails — it was never replaced with real tests.
|
data/Gemfile
DELETED