rokku 0.7.0 → 2.0.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
  SHA256:
3
- metadata.gz: de9fd9e92bfea55153e2a5cc08a19f6c9f1e6a6e8955ff5f6949cbe3bf689bb2
4
- data.tar.gz: be746224f675cdbe8bbc2058ab7d1fcf1c18c9d04a9a5ef2557060ed3fdfcad5
3
+ metadata.gz: e7979320c7f0685c0a6e117a611864ab3720646f1d932262bbb8f9ad58dca169
4
+ data.tar.gz: 78806b988c5c551d0ed83987b36642beb42d260432791188c7a67abd46c04360
5
5
  SHA512:
6
- metadata.gz: f1f9f9c33fa1b2c888380a4034eaa3473d25d7b30cbc55c9bbd627bcbcedbdb8af5d7ae63e6fa4e4429f6854cd22315eedff9dce7ff7b5f5caee910c5846ae8f
7
- data.tar.gz: 0ad532c9440192d8a6a804a6a9d367674a85770cb286a3d343f09fa84f84747396a95c1f92d5cb9a663db3c8d1187cd15b1100ffb85a150340f93ee588a63de3
6
+ metadata.gz: 66263f59a47f0fb1befc22b5cefd31299c5e1aeb6230de6fa782d72cfaac6aad88d7fdf06f2e3abd1269e66a00802007b2541ee52f10a04f8629be70b7a4a80b
7
+ data.tar.gz: a20785060356177fcbfa8b457b7ac52fe90931073f9185ea386c043131ab29e47bc4e9808ff19246b129159e0ea42b879187b9f08c38636c3bfe935731f88adf
data/.gitignore CHANGED
@@ -6,3 +6,5 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ *.gem
10
+ /Gemfile.lock
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.0.0
data/.travis.yml CHANGED
File without changes
data/CODE_OF_CONDUCT.md CHANGED
File without changes
data/Gemfile CHANGED
File without changes
data/Gemfile.lock CHANGED
@@ -1,107 +1,22 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rokku (0.7.0)
5
- hanami-controller (~> 1.0)
6
- hanami-router (~> 1.0)
4
+ rokku (2.0.0)
7
5
 
8
6
  GEM
9
7
  remote: https://rubygems.org/
10
8
  specs:
11
- concurrent-ruby (1.1.7)
12
- dry-configurable (0.11.6)
13
- concurrent-ruby (~> 1.0)
14
- dry-core (~> 0.4, >= 0.4.7)
15
- dry-equalizer (~> 0.2)
16
- dry-container (0.7.2)
17
- concurrent-ruby (~> 1.0)
18
- dry-configurable (~> 0.1, >= 0.1.3)
19
- dry-core (0.4.10)
20
- concurrent-ruby (~> 1.0)
21
- dry-equalizer (0.3.0)
22
- dry-initializer (1.4.1)
23
- dry-logic (0.4.2)
24
- dry-container (~> 0.2, >= 0.2.6)
25
- dry-core (~> 0.2)
26
- dry-equalizer (~> 0.2)
27
- dry-struct (0.3.1)
28
- dry-configurable (~> 0.1)
29
- dry-core (~> 0.3)
30
- dry-equalizer (~> 0.2)
31
- dry-types (~> 0.9, >= 0.9.0)
32
- ice_nine (~> 0.11)
33
- dry-types (0.11.1)
34
- concurrent-ruby (~> 1.0)
35
- dry-configurable (~> 0.1)
36
- dry-container (~> 0.3)
37
- dry-core (~> 0.2, >= 0.2.1)
38
- dry-equalizer (~> 0.2)
39
- dry-logic (~> 0.4, >= 0.4.0)
40
- inflecto (~> 0.0.0, >= 0.0.2)
41
- hanami-controller (1.3.3)
42
- hanami-utils (~> 1.3)
43
- rack (~> 2.0)
44
- hanami-model (1.3.2)
45
- concurrent-ruby (~> 1.0)
46
- dry-logic (~> 0.4.2, < 0.5)
47
- dry-types (~> 0.11.0)
48
- hanami-utils (~> 1.3)
49
- rom (~> 3.3, >= 3.3.3)
50
- rom-repository (~> 1.4)
51
- rom-sql (~> 1.3, >= 1.3.5)
52
- hanami-router (1.3.2)
53
- hanami-utils (~> 1.3)
54
- http_router (= 0.11.2)
55
- rack (~> 2.0)
56
- hanami-utils (1.3.6)
57
- concurrent-ruby (~> 1.0)
58
- transproc (~> 1.0)
59
- http_router (0.11.2)
60
- rack (>= 1.0.0)
61
- url_mount (~> 0.2.1)
62
- ice_nine (0.11.2)
63
- inflecto (0.0.2)
64
- minitest (5.13.0)
65
- rack (2.2.3)
66
- rake (10.5.0)
67
- rom (3.3.3)
68
- concurrent-ruby (~> 1.0)
69
- dry-core (~> 0.3)
70
- dry-equalizer (~> 0.2)
71
- dry-initializer (~> 1.3)
72
- dry-types (~> 0.9, >= 0.9.4)
73
- rom-mapper (~> 0.5, >= 0.5.1)
74
- rom-mapper (0.5.1)
75
- dry-core (~> 0.2, >= 0.2.3)
76
- dry-equalizer (~> 0.2)
77
- transproc (~> 1.0)
78
- rom-repository (1.4.0)
79
- dry-core (~> 0.3, >= 0.3.1)
80
- dry-struct (~> 0.3)
81
- rom (~> 3.3)
82
- rom-mapper (~> 0.5)
83
- rom-sql (1.3.5)
84
- dry-core (~> 0.3)
85
- dry-equalizer (~> 0.2)
86
- dry-types (~> 0.11.0)
87
- rom (~> 3.2, >= 3.2.2)
88
- sequel (~> 4.43)
89
- sequel (4.49.0)
90
- transproc (1.1.1)
91
- url_mount (0.2.1)
92
- rack
9
+ minitest (5.26.1)
10
+ rake (13.3.1)
93
11
 
94
12
  PLATFORMS
95
- ruby
13
+ x86_64-linux
96
14
 
97
15
  DEPENDENCIES
98
16
  bundler (~> 2.0)
99
- hanami-controller (~> 1.0)
100
- hanami-model (~> 1.0)
101
- hanami-router (~> 1.0)
102
- minitest (~> 5.0)
103
- rake (~> 10.0)
17
+ minitest (~> 5.25)
18
+ rake (~> 13.0)
104
19
  rokku!
105
20
 
106
21
  BUNDLED WITH
107
- 2.0.2
22
+ 2.2.3
data/LICENSE.txt CHANGED
File without changes
data/README.md CHANGED
@@ -6,8 +6,10 @@ Rokku (ロック - lock) offers authorization for [Hanami web applications](http
6
6
 
7
7
  Authorization was setup as inspired by [this blog post](http://billpatrianakos.me/blog/2013/10/22/authorize-users-based-on-roles-and-permissions-without-a-gem/). It supports the generation of policy files for each controller where authorized roles are specified for each action.
8
8
 
9
+ **Note:** For Hanami 1.3 support, see the [0.7.0 branch](https://github.com/sebastjan-hribar/rokku/tree/0.7.0) or install Rokku 0.7.0.
9
10
 
10
- ## Installation
11
+
12
+ ## 1. Installation
11
13
 
12
14
  Add this line to your application's Gemfile:
13
15
 
@@ -24,34 +26,73 @@ Or install it yourself as:
24
26
  $ gem install rokku
25
27
 
26
28
 
27
- Rokku is already setup to be included by your Hanami application:
29
+ Rokku 2.0 needs to be included in the action:
28
30
 
29
31
  ```ruby
30
- ::Hanami::Controller.configure do
31
- prepare do
32
+ # auto_register: false
33
+ # frozen_string_literal: true
34
+
35
+ require "hanami/action"
36
+ require "dry/monads"
37
+ require "rokku"
38
+
39
+ module MyApplication
40
+ class Action < Hanami::Action
41
+ # Provide `Success` and `Failure` for pattern matching on operation results
42
+ include Dry::Monads[:result]
32
43
  include Hanami::Rokku
44
+
45
+ handle_exception "ROM::TupleCountMismatchError" => :handle_not_found
46
+
47
+ private
48
+
49
+ def handle_not_found(request, response, exception)
50
+ response.status = 404
51
+ response.format = :html
52
+ response.body = "Not found"
53
+ end
33
54
  end
34
55
  end
35
56
  ```
36
57
 
37
- ## Usage
58
+ ## 2. Usage
38
59
 
39
- ### Role based authorization
60
+ ### 2.1 Role based authorization
40
61
 
41
- #### Prerequisites
42
- The current user must be stored in the `@user` variable and must have the attribute of `roles`. Rokku supports `roles` both as a type of `Array` and `String`.
43
- For example, the `@user.roles` could either be a simple string like 'admin' or an array of roles like `['level_1', 'level_2', 'level_3']`.
62
+ #### 2.1.1 Prerequisites
63
+ Prior to authorizing the user, retrieve the entity from the database and assign it to a variable `user` so it can be passed to the `authorized?` method. Rokku supports `roles` both as a type of `Array` and `String`.
64
+ For example, the `user.roles` could either be a simple string like 'admin' or an array of roles like `['level_1', 'level_2', 'level_3']`.
65
+
66
+ ### 2.2 Policy creation
67
+ Rokku supports policy creation for either the main application or for a specific slice. Application policies are created in the `app/policies` folder, while the slice policies are created in the `slices/'slice name'/policies`. See the two command examples below.
44
68
 
45
69
  ```ruby
46
- rokku -n mightyPoster -p post
70
+ rokku -p tasks -a myapp #=> app/policies/tasks_policy.rb
47
71
  ```
48
- The above CLI command will generate a policy file for the application mightyPoster (not the project) and the controller post. The file will be generated as `myProject/lib/mightyPoster/policies/PostPolicy.rb`
49
72
 
50
- Each application will have its own `app/policies` folders.
73
+ ```ruby
74
+ rokku -p tasks -s admin #=> app/slices/admin/policies/tasks_policy.rb
75
+ ```
51
76
 
52
77
  **The command must be run in the project root folder.**
53
78
 
79
+ **Flags:**
80
+ * -p, --policy => policy
81
+ * -s, --slice => slice
82
+ * -a, --app => application
83
+
84
+
85
+ #### 2.2.1 Naming requirements
86
+ For multi part names snake case must be used.
87
+
88
+ ```ruby
89
+ rokku -p admin_tasks -s admin_tickets #=> app/slices/admin_tickets/policies/admin_tasks_policy.rb
90
+ ```
91
+
92
+
93
+ ### 2.3 Verifying authorization
54
94
  Once the file is generated, the authorized roles variables in the initialize block for required actions need to be uncommented and supplied with specific roles.
95
+
55
96
  For example:
56
97
 
57
98
  ```ruby
@@ -61,17 +102,116 @@ For example:
61
102
  @authorized_roles_for_update = ['admin']
62
103
  ```
63
104
 
64
- Then we can check if a user is authorized for the `mightyPoster` application, `Post` controller and `Update`action.
105
+ Then we can check if a user is authorized for the `AdminTickets` slice, `AdminTasks` resources and the `Update`action.
65
106
 
66
107
  ```ruby
67
- authorized?("mightyposter", "post", "update")
108
+ authorized?(user)
68
109
  ```
69
110
 
70
- A complete example of using Rokku in a Hanami 1.3 applications is available [here](https://sebastjan-hribar.github.io/programming/2022/01/08/rokku-with-hanami.html).
111
+ The `authorized?` method checks if the specified user has the required role and permission to access the action. It returns true or false and provides the basis for further actions in either case.
112
+
113
+ Rokku supports 2 modes of arguments specification: automatic and manual.
114
+ Automatic fits most cases, since the app or slice name, resource name and action are automatically extracted.
115
+
116
+ With manual it's possible to do cross-namespace authorization checks and multiple permission checks. For example it's possible to check for authorization for `EndGames` in
117
+ an action for `ChessOpenings`.
118
+
119
+ * Automatic
120
+
121
+ `authorized?(current_user)`
122
+
123
+ * Manual
124
+
125
+ `authorized?(current_user, namespace: "ChessBase", resource: "ChessOpenings", action: "destroy")`
126
+
127
+ The namespace argument can either be the main application name or s slice name.
128
+
129
+ #### 2.2.1 Naming requirements
130
+ For multi part names PascalCase must be used as shown in the above example for **Manual**.
131
+
132
+
133
+ ## 2.4 Authorization verification in a share code module
134
+ It is possible to enable session handling in a share code module as provided by Hanami.
135
+ To do this, create an authentication module in **app/actions/authentication.rb**.
136
+ The example below shows also how to custom values to replace default values in
137
+ actions.
138
+
139
+ ```ruby
140
+ module ChessBase
141
+ module Actions
142
+ module Authorization
143
+
144
+ def self.included(action_class)
145
+ action_class.class_eval do
146
+ include Deps["repos.user_repo"]
147
+ before :check_authorization
148
+ end
149
+ end
150
+
151
+ private
152
+
153
+ def check_authorization(request, response)
154
+ user_id = request.session[:current_user]
155
+ user = user_repo.find_by_id(user_id) if user_id
156
+
157
+ if authorized?(user) == false
158
+ response.flash[:failed_notice] = "You tried to visit an URL you are not authorized for."
159
+ response.redirect_to '/'
160
+ end
161
+ end
162
+ end
163
+ end
164
+ end
165
+ ```
166
+
167
+ We can then simply include the `Authorization` module in actions, where required.
168
+
169
+ However, if we include this in the base action class, it will be available in all
170
+ actions and there is no need for separate includes in actions:
171
+
172
+ ```ruby
173
+ #
174
+ #
175
+ module MyApplication
176
+ class Action < Hanami::Action
177
+ # Provide `Success` and `Failure` for pattern matching on operation results
178
+ include Dry::Monads[:result]
179
+ include Hanami::Rokku
180
+ include Xpresstube::Actions::Authorization
181
+
182
+ handle_exception "ROM::TupleCountMismatchError" => :handle_not_found
183
+
184
+ private
185
+ #
186
+ #
187
+ ```
188
+
189
+ **_Disabling the authorization shared module in specific actions_**
190
+
191
+ Sometimes we might not want to check for authorized user. For example,
192
+ doing so in the `login` action will cause an infinite loop. There we can
193
+ disable the module by overwriting the desired methods in the action:
194
+
195
+ ```ruby
196
+ private
197
+
198
+ def check_authorization; end
199
+ ```
71
200
 
72
201
 
73
202
  ### Changelog
74
203
 
204
+ #### 2.0.0
205
+
206
+ **Breaking Changes:**
207
+ - Supports Hanami ~> 2.0 applications only.
208
+ - Application policies are now created in `app/policies`.
209
+ - Slice policies are now created in `slices/my_slice/policies`.
210
+ - Rokku must be explicitly included in the base action: `include Hanami::Rokku`.
211
+ - Rokku 2.0.0 doesn't rely on instance variable like `@user` anymore. Instead, a `user` variable must be passed as an argument to a method.
212
+
213
+ For Hanami 1.3 support, use Rokku 0.7.0.
214
+
75
215
  #### 0.7.0
76
216
 
77
217
  * Policies are now scoped under application module so it is possible to have two `Dashboard` policies for two different applications.
data/Rakefile CHANGED
File without changes
@@ -5,20 +5,27 @@ module Commands
5
5
  def self.run
6
6
  options = {}
7
7
  optparse = OptionParser.new do |opts|
8
- opts.banner = "\nHanami authorization policy generator
9
- Usage: rokku -n myapp -p user
10
- Flags:
11
- \n"
12
-
13
- opts.on("-n", "--app_name APP", "Specify the application name for the policy") do |app_name|
14
- options[:app_name] = app_name
8
+ opts.banner = "\nHanami 2.x authorization policy generator
9
+
10
+ Usage:
11
+ rokku -p tasks -a myapp # Main app: app/policies/tasks_policy.rb
12
+ rokku -p tasks -s admin # Slice: slices/admin/policies/tasks_policy.rb
13
+ Flags:
14
+ \n"
15
+
16
+ opts.on("-p", "--policy POLICY", "Specify a policy name (e.g., tasks, users, posts) - REQUIRED.") do |policy|
17
+ options[:policy] = policy
15
18
  end
16
-
17
- opts.on("-p", "--policy POLICY", "Specify the policy name") do |policy|
18
- options[:policy] = policy
19
+
20
+ opts.on("-a", "--app APP", "Specify the main app name (e.g., myapp, mytasks) - used for main app policies.") do |app|
21
+ options[:app] = app
19
22
  end
20
-
21
- opts.on("-h", "--help", "Displays help") do
23
+
24
+ opts.on("-s", "--slice SLICE", "Specify a slice name (e.g., admin, api) - used for slice policies.") do |slice|
25
+ options[:slice] = slice
26
+ end
27
+
28
+ opts.on("-h", "--help", "Display help.") do
22
29
  puts opts
23
30
  exit
24
31
  end
@@ -26,82 +33,123 @@ module Commands
26
33
 
27
34
  begin
28
35
  optparse.parse!
29
- puts "Add flag -h or --help to see usage instructions." if options.empty?
30
- mandatory = [:app_name, :policy]
31
- missing = mandatory.select{ |arg| options[arg].nil? }
32
- unless missing.empty?
33
- raise OptionParser::MissingArgument.new(missing.join(', '))
34
- end
35
- rescue OptionParser::InvalidOption, OptionParser::MissingArgument
36
- puts $!.to_s
37
- puts optparse
38
- exit
39
- end
40
36
 
41
- puts "Performing task with options: #{options.inspect}"
42
- generate_policy("#{options[:app_name]}", "#{options[:policy]}") if options[:policy]
43
- end
37
+ if options.empty?
38
+ puts "Error: no options prodived."
39
+ puts optparse
40
+ exit 1
41
+ end
44
42
 
45
- private
46
- # The generate_policy method creates the policy file for specified
47
- # application and controller. By default all actions to check against
48
- # are commented out.
49
- # Uncomment the needed actions and define appropriate user roles.
43
+ unless options[:policy]
44
+ puts "Error: Policy name is required (-p or --policy)."
45
+ puts optparse
46
+ exit 1
47
+ end
50
48
 
51
- def self.generate_policy(app_name, controller_name)
52
- app_name = app_name.downcase.capitalize
53
- controller = controller_name.downcase.capitalize
54
- policy_txt = <<-TXT
55
- module #{app_name}
56
- class #{controller}Policy
57
- def initialize(roles)
58
- @user_roles = roles
59
- # Uncomment the required roles and add the
60
- # appropriate user role to the @authorized_roles* array.
61
- # @authorized_roles_for_new = []
62
- # @authorized_roles_for_create = []
63
- # @authorized_roles_for_show = []
64
- # @authorized_roles_for_index = []
65
- # @authorized_roles_for_edit = []
66
- # @authorized_roles_for_update = []
67
- # @authorized_roles_for_destroy = []
68
- end
49
+ if options[:app] && options[:slice]
50
+ puts "Error: Cannot specify both --app and --slice."
51
+ puts "Use --app for main app policies, --slice for slice policies."
52
+ puts optparse
53
+ exit 1
54
+ end
69
55
 
70
- def new?
71
- (@authorized_roles_for_new & @user_roles).any?
72
- end
56
+ unless options[:app] || options[:slice]
57
+ puts "Error: Must specify either --app or --slice."
58
+ puts "Use --app for main app policies, --slice for slice policies."
59
+ puts optparse
60
+ exit 1
61
+ end
73
62
 
74
- def create?
75
- (@authorized_roles_for_create & @user_roles).any?
76
- end
63
+ rescue OptionParser::InvalidOption, OptionParser::MissingArgument => e
64
+ puts "Error: #{e.message}"
65
+ puts optparse
66
+ exit 1
67
+ end
77
68
 
78
- def show?
79
- (@authorized_roles_for_show & @user_roles).any?
80
- end
69
+ puts "Generating policy: #{options.inspect}"
70
+ generate_policy(options[:policy], app_name: options[:app], slice_name: options[:slice])
71
+ end
81
72
 
82
- def index?
83
- (@authorized_roles_for_index & @user_roles).any?
84
- end
73
+ private
74
+ # The generate_policy method creates the policy file at the main
75
+ # application or slice level for Hanami 2.x applications.
76
+ # By default all actions to check against are commented out.
85
77
 
86
- def edit?
87
- (@authorized_roles_for_edit & @user_roles).any?
88
- end
78
+ # Uncomment the needed actions and define appropriate user roles.
89
79
 
90
- def update?
91
- (@authorized_roles_for_update & @user_roles).any?
92
- end
80
+ def self.generate_policy(policy_name, app_name: nil, slice_name: nil)
81
+ if slice_name
82
+ namespace = slice_name.split("_").map(&:downcase).map(&:capitalize).join
83
+ folder_namespace = slice_name.split("_").map(&:downcase).join("_")
84
+ policies_dir = "slices/#{folder_namespace}/policies"
85
+ elsif app_name
86
+ namespace = app_name.split("_").map(&:downcase).map(&:capitalize).join
87
+ policies_dir = "app/policies"
88
+ else
89
+ raise ArgumentError, "Please specify either app_name or slice_name."
90
+ end
93
91
 
94
- def destroy?
95
- (@authorized_roles_for_destroy & @user_roles).any?
92
+ policy_class_name = "#{policy_name.split("_").map(&:downcase).map(&:capitalize).join}Policy"
93
+
94
+ policy_content = <<~RUBY
95
+ # frozen_string_literal: true
96
+
97
+ module #{namespace}
98
+ class #{policy_class_name}
99
+ def initialize(roles)
100
+ @user_roles = roles
101
+ # Uncomment the required roles and add the
102
+ # appropriate user role to the @authorized_roles* array.
103
+ # @authorized_roles_for_new = []
104
+ # @authorized_roles_for_create = []
105
+ # @authorized_roles_for_show = []
106
+ # @authorized_roles_for_index = []
107
+ # @authorized_roles_for_edit = []
108
+ # @authorized_roles_for_update = []
109
+ # @authorized_roles_for_destroy = []
110
+ end
111
+
112
+ def new?
113
+ (@authorized_roles_for_new & @user_roles).any?
114
+ end
115
+
116
+ def create?
117
+ (@authorized_roles_for_create & @user_roles).any?
118
+ end
119
+
120
+ def show?
121
+ (@authorized_roles_for_show & @user_roles).any?
122
+ end
123
+
124
+ def index?
125
+ (@authorized_roles_for_index & @user_roles).any?
126
+ end
127
+
128
+ def edit?
129
+ (@authorized_roles_for_edit & @user_roles).any?
130
+ end
131
+
132
+ def update?
133
+ (@authorized_roles_for_update & @user_roles).any?
134
+ end
135
+
136
+ def destroy?
137
+ (@authorized_roles_for_destroy & @user_roles).any?
138
+ end
96
139
  end
97
140
  end
141
+ RUBY
142
+
143
+ FileUtils.mkdir_p(policies_dir) unless File.directory?(policies_dir)
144
+ policy_file = "#{policies_dir}/#{policy_name.downcase}_policy.rb"
145
+
146
+ if File.exist?(policy_file)
147
+ puts "Policy already exists: #{policy_file}."
148
+ puts "Skipping generation."
149
+ else
150
+ File.write(policy_file, policy_content)
151
+ puts "✓ Generated policy: #{policy_file}."
152
+ puts " Namespace: #{namespace}::#{policy_class_name}."
98
153
  end
99
- TXT
100
-
101
- FileUtils.mkdir_p "lib/#{app_name.downcase}/policies" unless File.directory?("lib/#{app_name.downcase}/policies")
102
- unless File.file?("lib/#{app_name.downcase}/policies/#{controller}Policy.rb")
103
- File.open("lib/#{app_name.downcase}/policies/#{controller}Policy.rb", 'w') { |file| file.write(policy_txt) }
104
- end
105
- puts("Generated policy: lib/#{app_name.downcase}/policies/#{controller}Policy.rb") if File.file?("lib/#{app_name.downcase}/policies/#{controller}Policy.rb")
106
154
  end
107
155
  end
data/lib/rokku/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Rokku
2
- VERSION = "0.7.0"
2
+ VERSION = "2.0.0"
3
3
  end
data/lib/rokku.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  require 'rokku/version'
2
- require 'hanami/controller'
3
2
 
4
3
  module Hanami
5
4
  module Rokku
@@ -10,23 +9,29 @@ module Hanami
10
9
  # and permission to access the action. It returns true or false and
11
10
  # provides the basis for further actions in either case.
12
11
  #
13
- # Example: redirect_to "/" unless authorized?("post", create")
12
+ # There are 2 modes of arguments specification possible: automatic and manual.
13
+ # Automatic fits most cases. With manual it's possible to do
14
+ # cross-namespace authorization checks and multiple permission checks.
14
15
 
15
- def authorized?(application, controller, action)
16
- input_roles = @user.roles
17
- roles = []
18
- if input_roles.class == String
19
- roles << input_roles
20
- else
21
- roles = input_roles
16
+ # Automatic
17
+ # authorized?(current_user)
18
+ #
19
+ # Manual
20
+ # authorized?(current_user, namespace: "ChessBase", resource: "ChessOpenings", action: "destroy")
21
+ #
22
+ # The namespace argument can either be the main application name or s slice name.
23
+
24
+ def authorized?(user, namespace: nil, resource: nil, action: nil)
25
+ if namespace.nil? || resource.nil? || action.nil?
26
+ namespace = self.class.to_s.split("::")[0]
27
+ resource = self.class.to_s.split("::")[2]
28
+ action = self.class.to_s.split("::")[3]
22
29
  end
23
- Object.const_get("#{application}::#{controller.downcase.capitalize}Policy").new(roles).send("#{action.downcase}?")
24
- end
25
- end
26
- end
27
30
 
28
- ::Hanami::Controller.configure do
29
- prepare do
30
- include Hanami::Rokku
31
+ input_roles = user.roles
32
+ roles = input_roles.is_a?(String) ? [input_roles] : input_roles
33
+
34
+ Object.const_get("#{namespace}::#{resource}Policy").new(roles).send("#{action.downcase}?")
35
+ end
31
36
  end
32
- end
37
+ end
data/rokku.gemspec CHANGED
@@ -25,12 +25,6 @@ Gem::Specification.new do |spec|
25
25
  spec.require_paths = ["lib"]
26
26
 
27
27
  spec.add_development_dependency "bundler", "~> 2.0"
28
- spec.add_development_dependency "rake", "~> 10.0"
29
- spec.add_development_dependency "minitest", "~> 5.0"
30
- spec.add_development_dependency 'hanami-model', '~> 1.0'
31
- spec.add_development_dependency 'hanami-controller', "~> 1.0"
32
- spec.add_development_dependency 'hanami-router', "~> 1.0"
33
-
34
- spec.add_runtime_dependency 'hanami-controller', "~> 1.0"
35
- spec.add_runtime_dependency 'hanami-router', "~> 1.0"
28
+ spec.add_development_dependency "rake", "~> 13.0"
29
+ spec.add_development_dependency "minitest", "~> 5.25"
36
30
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rokku
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sebastjan Hribar
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-08 00:00:00.000000000 Z
11
+ date: 2026-03-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -30,99 +30,29 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: '13.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: '13.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: minitest
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '5.0'
47
+ version: '5.25'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '5.0'
55
- - !ruby/object:Gem::Dependency
56
- name: hanami-model
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '1.0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '1.0'
69
- - !ruby/object:Gem::Dependency
70
- name: hanami-controller
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: '1.0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '1.0'
83
- - !ruby/object:Gem::Dependency
84
- name: hanami-router
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: '1.0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: '1.0'
97
- - !ruby/object:Gem::Dependency
98
- name: hanami-controller
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - "~>"
102
- - !ruby/object:Gem::Version
103
- version: '1.0'
104
- type: :runtime
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - "~>"
109
- - !ruby/object:Gem::Version
110
- version: '1.0'
111
- - !ruby/object:Gem::Dependency
112
- name: hanami-router
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - "~>"
116
- - !ruby/object:Gem::Version
117
- version: '1.0'
118
- type: :runtime
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - "~>"
123
- - !ruby/object:Gem::Version
124
- version: '1.0'
125
- description:
54
+ version: '5.25'
55
+ description:
126
56
  email:
127
57
  - sebastjan.hribar@gmail.com
128
58
  executables:
@@ -133,6 +63,7 @@ extensions: []
133
63
  extra_rdoc_files: []
134
64
  files:
135
65
  - ".gitignore"
66
+ - ".ruby-version"
136
67
  - ".travis.yml"
137
68
  - CODE_OF_CONDUCT.md
138
69
  - Gemfile
@@ -152,7 +83,7 @@ licenses:
152
83
  - MIT
153
84
  metadata:
154
85
  homepage_uri: https://github.com/sebastjan-hribar/rokku
155
- post_install_message:
86
+ post_install_message:
156
87
  rdoc_options: []
157
88
  require_paths:
158
89
  - lib
@@ -167,9 +98,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
167
98
  - !ruby/object:Gem::Version
168
99
  version: '0'
169
100
  requirements: []
170
- rubyforge_project:
171
- rubygems_version: 2.7.7
172
- signing_key:
101
+ rubygems_version: 3.2.3
102
+ signing_key:
173
103
  specification_version: 4
174
104
  summary: Rokku is a small authorization library for Hanami projects.
175
105
  test_files: []