action_sentinel 0.1.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +19 -5
- data/lib/action_sentinel/authorization.rb +2 -2
- data/lib/action_sentinel/permissible.rb +9 -9
- data/lib/action_sentinel/version.rb +1 -1
- data/lib/generators/action_sentinel/access_permission_generator.rb +30 -8
- data/lib/generators/action_sentinel/templates/access_permission.rb +1 -1
- data/lib/generators/action_sentinel/templates/migration.rb +4 -4
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0e32f9fe1d318938091c07167a07ff9b4e8584f0ed712df14b29cbec36819a6e
|
4
|
+
data.tar.gz: a91742b5c786cd20650583bb9eb6dc1fab4ba3b12067958e930b519851917cda
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fb4ff67b1fc12d024c50d80758109c09158d60a22f3d2d1435bf0daa6b47faacd5cb41cf837c7a48fbdc7e088b69ffb80459f4e73e7611b90f3131e853ec0667
|
7
|
+
data.tar.gz: 82533ced4780a2b942fae90aca15203b730638af6301155dcbc9fb52777cf9d149b917c41ae6b95184fd5f4cd7d86f2bf0785a61fa234db4646d87f5442987f1
|
data/CHANGELOG.md
CHANGED
@@ -3,3 +3,13 @@
|
|
3
3
|
## [0.1.0] - 2023-12-04
|
4
4
|
|
5
5
|
- Initial release
|
6
|
+
|
7
|
+
## [0.2.0] - 2023-12-27
|
8
|
+
|
9
|
+
- Changed `controller_name` attribute to `controller_path` in `AccessPermission` model
|
10
|
+
- Allow to create actions permissions to scoped controllers
|
11
|
+
|
12
|
+
## [0.3.0] - 2024-01-05
|
13
|
+
|
14
|
+
- Fixed errors when revoking `AccessPermissionGenerator` methods
|
15
|
+
- Added logger to `AccessPermissionGenerator`
|
data/README.md
CHANGED
@@ -40,7 +40,7 @@ The generator will create the AccessPermission model and a migration, and insert
|
|
40
40
|
class AccessPermission < ApplicationRecord
|
41
41
|
belongs_to :user
|
42
42
|
|
43
|
-
validates :
|
43
|
+
validates :controller_path, uniqueness: { scope: :user_id }
|
44
44
|
end
|
45
45
|
|
46
46
|
# User model with permissions added
|
@@ -79,9 +79,9 @@ user.add_permissions_to 'show', 'users'
|
|
79
79
|
# Adding permissions to access create and update actions in UsersController
|
80
80
|
user.add_permissions_to 'create', 'update', 'users'
|
81
81
|
```
|
82
|
-
|
82
|
+
The arguments must be related to the actions of a controller, and the last argument is the name of the controller. The actions arguments must be in downcase format and must be equal to the actions methods of the controller. The controller argument, must be in downcase and plural format, ignoring the "Controller" suffix.
|
83
83
|
|
84
|
-
|
84
|
+
For example, a controller called `UsersController` must be passed just as `users`.
|
85
85
|
|
86
86
|
Also is possible to pass the arguments as symbols:
|
87
87
|
```ruby
|
@@ -108,6 +108,21 @@ To check if the user has permission to access an action from a controller, you j
|
|
108
108
|
user.has_permission_to? 'create', 'users'
|
109
109
|
```
|
110
110
|
|
111
|
+
### Scoped Controllers
|
112
|
+
|
113
|
+
For controllers that are scoped in a module, its argument also must be informed in the same downcase and plural format, but with the prefix of the module separated by a slash. For example, a controller called `Api::UsersController` must be passed as `api/users`:
|
114
|
+
|
115
|
+
```ruby
|
116
|
+
# Adding permissions
|
117
|
+
user.add_permissions_to 'create', 'update', 'api/users'
|
118
|
+
|
119
|
+
# Removing permissions
|
120
|
+
user.remove_permissions_to 'create', 'update', 'api/users'
|
121
|
+
|
122
|
+
# Checking permission
|
123
|
+
user.has_permission_to? 'create', 'api/users'
|
124
|
+
```
|
125
|
+
|
111
126
|
## Authorization
|
112
127
|
|
113
128
|
To authorize the actions in a controller, you must call `authorize_action!`. Action Sentinel will authorize the access if the current user has permission to access the action.
|
@@ -143,7 +158,6 @@ end
|
|
143
158
|
```
|
144
159
|
|
145
160
|
### Rescuing an UnauthorizedAction in ApplicationController
|
146
|
-
---
|
147
161
|
|
148
162
|
Action Sentinel raises an `ActionSentinel::UnauthorizedAction` if the user does not have the permission to access an action. You can rescue this error and respond in your customized format using `rescue_from` in your `ApplicationController`:
|
149
163
|
|
@@ -163,7 +177,7 @@ end
|
|
163
177
|
|
164
178
|
## Contributing
|
165
179
|
|
166
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
180
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/denisstael/action_sentinel.
|
167
181
|
|
168
182
|
## License
|
169
183
|
|
@@ -10,9 +10,9 @@ module ActionSentinel
|
|
10
10
|
# @raise [UnauthorizedAction] if the user is not authorized.
|
11
11
|
# @return [void]
|
12
12
|
def authorize_action!
|
13
|
-
return if action_user.has_permission_to?(action_name,
|
13
|
+
return if action_user.has_permission_to?(action_name, controller_path)
|
14
14
|
|
15
|
-
raise UnauthorizedAction, "Not allowed to access '#{action_name}' action in #{
|
15
|
+
raise UnauthorizedAction, "Not allowed to access '#{action_name}' action in #{controller_path.camelize}Controller"
|
16
16
|
end
|
17
17
|
|
18
18
|
# Retrieve the user associated with the current action.
|
@@ -28,10 +28,10 @@ module ActionSentinel
|
|
28
28
|
# Add permissions to the access_permissions association for a specific controller.
|
29
29
|
#
|
30
30
|
# @param actions [Array<Symbol, String>] The actions to add permissions for.
|
31
|
-
# @param
|
31
|
+
# @param controller_path [String] The name of the controller.
|
32
32
|
# @return [Boolean] true if the permission was saved, false otherwise.
|
33
|
-
def add_permissions_to(*actions,
|
34
|
-
permission = access_permissions.find_or_initialize_by(
|
33
|
+
def add_permissions_to(*actions, controller_path)
|
34
|
+
permission = access_permissions.find_or_initialize_by(controller_path: controller_path)
|
35
35
|
permission.assign_attributes(actions: (permission.actions + sanitize_actions_array(actions)).uniq)
|
36
36
|
permission.save
|
37
37
|
end
|
@@ -39,11 +39,11 @@ module ActionSentinel
|
|
39
39
|
# Remove permissions from the access_permissions association for a specific controller.
|
40
40
|
#
|
41
41
|
# @param actions [Array<Symbol, String>] The actions to remove permissions for.
|
42
|
-
# @param
|
42
|
+
# @param controller_path [String] The name of the controller.
|
43
43
|
# @return [Boolean, nil] true if the permission was saved, false if it was not or nil
|
44
44
|
# if the permission was not found.
|
45
|
-
def remove_permissions_to(*actions,
|
46
|
-
permission = access_permissions.find_by(
|
45
|
+
def remove_permissions_to(*actions, controller_path)
|
46
|
+
permission = access_permissions.find_by(controller_path: controller_path)
|
47
47
|
permission&.update(actions: (permission.actions - sanitize_actions_array(actions)))
|
48
48
|
end
|
49
49
|
|
@@ -52,10 +52,10 @@ module ActionSentinel
|
|
52
52
|
# Check if the model has permission to perform a specific action in a controller.
|
53
53
|
#
|
54
54
|
# @param action [Symbol, String] The action to check permission for.
|
55
|
-
# @param
|
55
|
+
# @param controller_path [String] The name of the controller.
|
56
56
|
# @return [Boolean] true if the model has permission, false otherwise.
|
57
|
-
def has_permission_to?(action,
|
58
|
-
query = access_permissions.where(
|
57
|
+
def has_permission_to?(action, controller_path)
|
58
|
+
query = access_permissions.where(controller_path: controller_path)
|
59
59
|
|
60
60
|
query = if %w[sqlite sqlite3].include? self.class.connection.adapter_name.downcase
|
61
61
|
query.where("actions LIKE ?", "%#{action}%")
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "rails/generators"
|
4
4
|
require "rails/generators/active_record"
|
5
|
+
require "logger"
|
5
6
|
|
6
7
|
module ActionSentinel
|
7
8
|
class AccessPermissionGenerator < Rails::Generators::Base
|
@@ -18,21 +19,39 @@ module ActionSentinel
|
|
18
19
|
end
|
19
20
|
|
20
21
|
def create_access_pemission_and_migration
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
model_file = File.join("app", "models", "#{singular_model_name}.rb")
|
23
|
+
|
24
|
+
if File.exist?(model_file) || revoke_process?
|
25
|
+
inject_action_permissible_into_model(model_file)
|
26
|
+
generate_access_permission
|
27
|
+
generate_migration
|
28
|
+
else
|
29
|
+
logger.info("The file #{model_file} does not appear to exist")
|
30
|
+
end
|
24
31
|
end
|
25
32
|
|
26
33
|
private
|
27
34
|
|
35
|
+
def logger
|
36
|
+
Logger.new($stdout)
|
37
|
+
end
|
38
|
+
|
39
|
+
def revoke_process?
|
40
|
+
behavior == :revoke
|
41
|
+
end
|
42
|
+
|
28
43
|
def generate_access_permission
|
29
44
|
template "access_permission.rb", File.join("app", "models", "access_permission.rb")
|
30
45
|
end
|
31
46
|
|
32
|
-
def
|
47
|
+
def primary_key_type
|
33
48
|
options.uuid? ? ", id: :uuid" : ""
|
34
49
|
end
|
35
50
|
|
51
|
+
def foreign_key_type
|
52
|
+
options.uuid? ? ", type: :uuid" : ""
|
53
|
+
end
|
54
|
+
|
36
55
|
def generate_migration
|
37
56
|
migration_template "migration.rb", "db/migrate/create_access_permissions.rb"
|
38
57
|
end
|
@@ -49,10 +68,13 @@ module ActionSentinel
|
|
49
68
|
"[#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}]"
|
50
69
|
end
|
51
70
|
|
52
|
-
def inject_action_permissible_into_model
|
53
|
-
|
54
|
-
|
55
|
-
|
71
|
+
def inject_action_permissible_into_model(model_file)
|
72
|
+
if File.exist?(model_file)
|
73
|
+
inject_into_class(model_file, model_class) do
|
74
|
+
"\taction_permissible\n"
|
75
|
+
end
|
76
|
+
else
|
77
|
+
logger.info("The file #{model_file} does not appear to exist")
|
56
78
|
end
|
57
79
|
end
|
58
80
|
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
class CreateAccessPermissions < ActiveRecord::Migration<%= migration_version %>
|
2
2
|
def change
|
3
|
-
create_table :access_permissions<%=
|
4
|
-
t.string :
|
3
|
+
create_table :access_permissions<%= primary_key_type %> do |t|
|
4
|
+
t.string :controller_path, null: false
|
5
5
|
t.string :actions, null: false, array: true, default: []
|
6
|
-
t.references :<%= singular_model_name %>, null: false<%=
|
6
|
+
t.references :<%= singular_model_name %>, null: false<%= foreign_key_type %>
|
7
7
|
|
8
8
|
t.timestamps
|
9
9
|
end
|
10
10
|
|
11
|
-
add_index :access_permissions, [:
|
11
|
+
add_index :access_permissions, [:controller_path, :<%= singular_model_name %>_id], unique: true
|
12
12
|
end
|
13
13
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: action_sentinel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Denis Stael
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-01-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -55,7 +55,7 @@ dependencies:
|
|
55
55
|
description: " This gem enables access authorization control, based on the access
|
56
56
|
permission settings for \n each controller and its actions, at the model level.\n"
|
57
57
|
email:
|
58
|
-
-
|
58
|
+
- denissantistael@gmail.com
|
59
59
|
executables: []
|
60
60
|
extensions: []
|
61
61
|
extra_rdoc_files: []
|
@@ -76,12 +76,13 @@ files:
|
|
76
76
|
- lib/generators/action_sentinel/access_permission_generator.rb
|
77
77
|
- lib/generators/action_sentinel/templates/access_permission.rb
|
78
78
|
- lib/generators/action_sentinel/templates/migration.rb
|
79
|
-
homepage: https://github.com/
|
79
|
+
homepage: https://github.com/denisstael/action_sentinel
|
80
80
|
licenses:
|
81
81
|
- MIT
|
82
82
|
metadata:
|
83
|
-
homepage_uri: https://github.com/
|
84
|
-
source_code_uri: https://github.com/
|
83
|
+
homepage_uri: https://github.com/denisstael/action_sentinel
|
84
|
+
source_code_uri: https://github.com/denisstael/action_sentinel
|
85
|
+
changelog_uri: https://github.com/denisstael/action_sentinel/blob/main/CHANGELOG.md
|
85
86
|
post_install_message:
|
86
87
|
rdoc_options: []
|
87
88
|
require_paths:
|