controller_policies 1.0.0 → 1.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 +4 -4
- data/README.md +36 -7
- data/controller_policies.gemspec +1 -1
- data/lib/ability.rb +15 -2
- data/lib/controller_policies/enforcement.rb +12 -3
- data/lib/controller_policies/version.rb +1 -1
- data/lib/generators/policy_definition_generator.rb +10 -6
- data/lib/generators/templates/{definitions.rb.tt → modular_definitions.rb.tt} +1 -1
- data/lib/generators/templates/root_definitions.rb.tt +22 -0
- metadata +13 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 876b65cbe173231e141e578fd2e650dcbbcbbba02b0ece615c3ddf80395ba96f
|
4
|
+
data.tar.gz: bcf69abce9066f2b99fa99d21481ecca033e2408d2ed0ec752f2b5cf080a482f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8031665a97f07ab1e47534f38376eb4b5170538ffa9da42bc69d7e6c2de847e855d64acfdc2db32bbe5fbaee6d1f709e4be147fba9912e39c0089d3d72cecd24
|
7
|
+
data.tar.gz: 2b30ca3aae95937a5625268853a9caa5697c460f1b24b7cffa5dc8dd875d5dee6005e367fb8029627227f7829b808c5f1485914869159e18e9d6545dccc1682f
|
data/README.md
CHANGED
@@ -20,6 +20,16 @@ rails g policy_definition my/namespace
|
|
20
20
|
|
21
21
|
This will generate a file: `app/policies/my/namespace/definitions.rb`
|
22
22
|
|
23
|
+
For controllers without a namespace (root-level controllers), you can generate a root-level definitions file:
|
24
|
+
|
25
|
+
```sh
|
26
|
+
rails g policy_definition root
|
27
|
+
# or simply
|
28
|
+
rails g policy_definition
|
29
|
+
```
|
30
|
+
|
31
|
+
This will generate a file: `app/policies/definitions.rb`
|
32
|
+
|
23
33
|
The developer should edit this file and add the policies for the app. **It is important to note that the location of the definitions file should reflect the namespace of the associated controllers.**
|
24
34
|
|
25
35
|
### `actions` key
|
@@ -43,16 +53,35 @@ end
|
|
43
53
|
|
44
54
|
The above definition will have enforced policies on `Base::FeatureApp::UsersController` (all actions), `Base::DataApp::ProductsController` (`index` action) and `Base::SubscriptionController`.
|
45
55
|
|
56
|
+
For root-level controllers (controllers without a namespace), you can define policies directly in the `Policies` module:
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
module Policies
|
60
|
+
DEFINITIONS = [
|
61
|
+
{
|
62
|
+
code: 'user_management',
|
63
|
+
name: 'User Management',
|
64
|
+
description: 'Allows user management operations',
|
65
|
+
actions: ['users', 'profiles#show', 'dashboard']
|
66
|
+
}
|
67
|
+
]
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
71
|
+
The above definition will have enforced policies on `UsersController` (all actions), `ProfilesController` (`show` action) and `DashboardController`.
|
72
|
+
|
46
73
|
**Do note that the `actions` array implement *Regular Expression Matching*. That means that if you have multiple controllers with the same name on their parent namespace, the parent will be matched first.** To avoid this problem, simply add the namespace to match the intended child instead.
|
47
74
|
|
48
75
|
```ruby
|
49
|
-
module
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
76
|
+
module Policies
|
77
|
+
module Base
|
78
|
+
DEFINITIONS = {
|
79
|
+
code: 'policy_code',
|
80
|
+
name: 'Policy Name',
|
81
|
+
description: 'I am a policy.',
|
82
|
+
actions: ['feature_app/users', 'another_base/data_app/products#index', 'base/subscriptions']
|
83
|
+
}
|
84
|
+
end
|
56
85
|
end
|
57
86
|
```
|
58
87
|
|
data/controller_policies.gemspec
CHANGED
@@ -27,7 +27,7 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.require_paths = ['lib']
|
28
28
|
|
29
29
|
# Uncomment to register a new dependency of your gem
|
30
|
-
spec.add_dependency 'rails', '
|
30
|
+
spec.add_dependency 'rails', '>= 7', '< 9'
|
31
31
|
|
32
32
|
# For more information and examples about making a new gem, check out our
|
33
33
|
# guide at: https://bundler.io/guides/creating_gem.html
|
data/lib/ability.rb
CHANGED
@@ -38,7 +38,12 @@ class Ability
|
|
38
38
|
queries.each do |query|
|
39
39
|
case query.class.to_s
|
40
40
|
when 'String'
|
41
|
-
|
41
|
+
# Handle empty string or root namespace
|
42
|
+
if query.empty? || query == '/'
|
43
|
+
results += all.select { |ability| ability.namespace == Policies }
|
44
|
+
else
|
45
|
+
results += all.select { |ability| ability.namespace.to_s == "Policies::#{trim(query).camelize}" }
|
46
|
+
end
|
42
47
|
when 'Module', 'Class'
|
43
48
|
results += all.select { |ability| ability.namespace == query }
|
44
49
|
end
|
@@ -82,7 +87,15 @@ class Ability
|
|
82
87
|
end
|
83
88
|
|
84
89
|
def definition_files_post_processing(file_path)
|
85
|
-
|
90
|
+
namespace_path = convert_namespace(file_path)
|
91
|
+
|
92
|
+
if namespace_path.empty?
|
93
|
+
# Handle root-level definitions.rb file
|
94
|
+
module_constant = Policies
|
95
|
+
else
|
96
|
+
module_constant = "Policies::#{namespace_path}".constantize
|
97
|
+
end
|
98
|
+
|
86
99
|
policy_definitions = module_constant::DEFINITIONS
|
87
100
|
policy_definitions.map do |policy_definition|
|
88
101
|
policy_definition[:namespace] = module_constant
|
@@ -34,9 +34,18 @@ module ControllerPolicies
|
|
34
34
|
# Method that attempts to go through policy definitions and check if it matches the current controller.
|
35
35
|
# If it finds a match, it will be an applicable definition to check abilities for.
|
36
36
|
def applicable_abilities
|
37
|
-
@applicable_abilities ||=
|
38
|
-
|
39
|
-
|
37
|
+
@applicable_abilities ||= begin
|
38
|
+
# Get abilities for the current controller namespace, or root if no namespace
|
39
|
+
namespace_abilities = if controller_namespace.empty?
|
40
|
+
Ability.where('') # This will get root-level policies
|
41
|
+
else
|
42
|
+
Ability.where(controller_namespace)
|
43
|
+
end
|
44
|
+
|
45
|
+
namespace_abilities.select do |ability|
|
46
|
+
matching_actions = ability.actions.select { |action| /#{action}/.match?("#{controller_path}##{action_name}") }
|
47
|
+
matching_actions.present?
|
48
|
+
end
|
40
49
|
end
|
41
50
|
end
|
42
51
|
end
|
@@ -3,18 +3,22 @@
|
|
3
3
|
# Generates a definition file for a namespace.
|
4
4
|
class PolicyDefinitionGenerator < Rails::Generators::Base
|
5
5
|
source_root File.expand_path('templates', __dir__)
|
6
|
-
desc 'Generates a policy definition file based on given namespace.'
|
7
|
-
argument :name, type: :string, required:
|
6
|
+
desc 'Generates a policy definition file based on given namespace. Leave empty for root-level definitions.'
|
7
|
+
argument :name, type: :string, required: false, default: '',
|
8
|
+
desc: 'The namespace for the definition file. Leave empty for root-level definitions.'
|
8
9
|
|
9
10
|
def create_policy_definition_file
|
10
|
-
|
11
|
-
|
12
|
-
|
11
|
+
if processed_name.blank?
|
12
|
+
# Generate root-level definitions.rb
|
13
|
+
template 'root_definitions.rb', 'app/policies/definitions.rb'
|
14
|
+
else
|
15
|
+
template 'modular_definitions.rb', "app/policies/#{processed_name}/definitions.rb"
|
16
|
+
end
|
13
17
|
end
|
14
18
|
|
15
19
|
private
|
16
20
|
|
17
21
|
def processed_name
|
18
|
-
@processed_name ||= name.strip.delete_prefix('/').delete_suffix('/')
|
22
|
+
@processed_name ||= name.strip.delete_prefix('/').delete_suffix('/') || ''
|
19
23
|
end
|
20
24
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Policies
|
4
|
+
DEFINITIONS = [
|
5
|
+
{
|
6
|
+
# Used as identifier for the policy.
|
7
|
+
code: 'Policy-Code',
|
8
|
+
# Readable name for the policy.
|
9
|
+
name: 'Readable Policy Name',
|
10
|
+
# Readable description for the policy.
|
11
|
+
description: 'Short description of what this policy allows',
|
12
|
+
# Controller actions the policy applies to. It works as matchers based on routes.
|
13
|
+
# It can be empty for manual policy checking.
|
14
|
+
actions: ['users', 'products#index', 'dashboard']
|
15
|
+
},
|
16
|
+
{
|
17
|
+
code: 'Another-Policy-Code',
|
18
|
+
name: 'Another Policy',
|
19
|
+
description: 'Long description.'
|
20
|
+
}
|
21
|
+
].freeze
|
22
|
+
end
|
metadata
CHANGED
@@ -1,30 +1,34 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: controller_policies
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tien
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: rails
|
15
14
|
requirement: !ruby/object:Gem::Requirement
|
16
15
|
requirements:
|
17
|
-
- - "
|
16
|
+
- - ">="
|
18
17
|
- !ruby/object:Gem::Version
|
19
18
|
version: '7'
|
19
|
+
- - "<"
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '9'
|
20
22
|
type: :runtime
|
21
23
|
prerelease: false
|
22
24
|
version_requirements: !ruby/object:Gem::Requirement
|
23
25
|
requirements:
|
24
|
-
- - "
|
26
|
+
- - ">="
|
25
27
|
- !ruby/object:Gem::Version
|
26
28
|
version: '7'
|
27
|
-
|
29
|
+
- - "<"
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: '9'
|
28
32
|
email:
|
29
33
|
- tieeeeen1994@gmail.com
|
30
34
|
executables: []
|
@@ -43,14 +47,14 @@ files:
|
|
43
47
|
- lib/controller_policies/railtie.rb
|
44
48
|
- lib/controller_policies/version.rb
|
45
49
|
- lib/generators/policy_definition_generator.rb
|
46
|
-
- lib/generators/templates/
|
50
|
+
- lib/generators/templates/modular_definitions.rb.tt
|
51
|
+
- lib/generators/templates/root_definitions.rb.tt
|
47
52
|
homepage: https://github.com/tieeeeen1994/rails-controller-policies
|
48
53
|
licenses:
|
49
54
|
- MIT
|
50
55
|
metadata:
|
51
56
|
homepage_uri: https://github.com/tieeeeen1994/rails-controller-policies
|
52
57
|
rubygems_mfa_required: 'true'
|
53
|
-
post_install_message:
|
54
58
|
rdoc_options: []
|
55
59
|
require_paths:
|
56
60
|
- lib
|
@@ -65,8 +69,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
65
69
|
- !ruby/object:Gem::Version
|
66
70
|
version: '0'
|
67
71
|
requirements: []
|
68
|
-
rubygems_version: 3.
|
69
|
-
signing_key:
|
72
|
+
rubygems_version: 3.7.1
|
70
73
|
specification_version: 4
|
71
74
|
summary: Allows the developer to define policies for controllers.
|
72
75
|
test_files: []
|