ree_lib 1.3.3 → 1.3.4

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: 5c2344653424e4b4597e82d6bb4f02ba3c93e577ab81a5afad986b1b54f34bdf
4
- data.tar.gz: 8eab2fc67b9f6076fccffa8fe7cab45a0bd5b6f64bf80792d98e0d1556935c84
3
+ metadata.gz: 73ca3b1fae54a13391bda2954179e4b66a784b170b8461eddb3acb4378f03b24
4
+ data.tar.gz: 5a3fc79a3201395824ae4575fb7b2ed7bf5ec3e0755db1572b078e34d4a347fa
5
5
  SHA512:
6
- metadata.gz: 58c9002d50cab923ada784de99b8447c456145e5d0c497e1c04fec753c47652e50e912eea067dfa929156f4a0d396c36e5de068a940cd5baaa74f4564182c597
7
- data.tar.gz: 5dd9f09f9953f3b3101449225847c22dfda247bf4f60cac42c8e9d4a1dfab783b65a21d780cda6964502b454d6a279fcb0c5a22e3cce0e9a0515d28f06b6d230
6
+ metadata.gz: d0b903a2f014d8f9f2473c91df8e0d26c33bda0cbc8eb61dcf9b6d6515498b1693aa3075da58695e71b825792474747bbb54363d081d86d858e00b427c53b350
7
+ data.tar.gz: 7abbef08143f8bc981a6eabd8934937fd1ec541a52f4a44814fbe18cfdf606d4fc95ec4b28a5febd8ffd7b0842f5e19bbb282f82e00405dd9d4ec50c8b71b416
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ree_lib (1.3.3)
4
+ ree_lib (1.3.4)
5
5
  bigdecimal (~> 3.1.9)
6
6
  binding_of_caller (~> 1.0.1)
7
7
  i18n (~> 1.14.7)
@@ -58,11 +58,13 @@ class Roda
58
58
  end
59
59
  end
60
60
 
61
- routing_tree = ReeRoda::BuildRoutingTree.new.call(@ree_routes)
62
- route_tree_proc = build_traverse_tree_proc(routing_tree, context)
61
+ routing_trees = ReeRoda::BuildRoutingTree.new.call(@ree_routes)
63
62
 
64
- list << Proc.new do |r|
65
- r.instance_exec(r, &route_tree_proc)
63
+ routing_trees.each do |routing_tree|
64
+ route_tree_proc = build_traverse_tree_proc(routing_tree, context)
65
+ list << Proc.new do |r|
66
+ r.instance_exec(r, &route_tree_proc)
67
+ end
66
68
  end
67
69
 
68
70
  opts[:ree_routes_proc] = list
@@ -75,10 +77,28 @@ class Roda
75
77
  r.instance_exec(r, &route.override)
76
78
  else
77
79
  r.send(route.respond_to) do
78
- r.env["warden"].authenticate!(scope: route.warden_scope)
80
+ authenticated_user = nil
81
+ authenticated_scope = nil
82
+
83
+ route.warden_scopes.each do |scope|
84
+ if r.env["warden"].authenticate(scope: scope)
85
+ user = r.env["warden"].user(scope)
86
+ if user
87
+ authenticated_user = user
88
+ authenticated_scope = scope
89
+ break
90
+ end
91
+ end
92
+ end
93
+
94
+ # all scopes are failed, throwing failure
95
+ if authenticated_user.nil?
96
+ r.env["warden"].custom_failure!
97
+ throw(:warden, scope: route.warden_scopes.first, reason: "authentication_failed")
98
+ end
79
99
 
80
100
  if context.opts[:ree_routes_before]
81
- r.instance_exec(@_request, route.warden_scope, &r.scope.opts[:ree_routes_before])
101
+ r.instance_exec(@_request, authenticated_scope, &r.scope.opts[:ree_routes_before])
82
102
  end
83
103
 
84
104
  params = r.params
@@ -99,7 +119,7 @@ class Roda
99
119
  v.is_a?(Array) ? v.select { not_blank.call(_1) } : v
100
120
  end
101
121
 
102
- accessor = r.env["warden"].user(route.warden_scope)
122
+ accessor = authenticated_user
103
123
  action_result = get_cached_action(route).call(accessor, filtered_params)
104
124
 
105
125
  if route.serializer
@@ -128,98 +148,151 @@ class Roda
128
148
  end
129
149
 
130
150
  def build_traverse_tree_proc(tree, context)
131
- has_arbitrary_param = tree.values[0].start_with?(":")
132
- route_parts = has_arbitrary_param ? tree.values.map { _1.gsub(":", "") } : tree.values
133
- procs = []
151
+ return Proc.new {} if tree.nil?
134
152
 
135
- child_procs = tree.children.map do |child|
136
- build_traverse_tree_proc(child, context)
153
+ if tree.depth == 0
154
+ process_root_node(tree, context)
155
+ else
156
+ process_nested_node(tree, context)
137
157
  end
158
+ end
138
159
 
139
- route_procs = tree.routes.map do |route|
140
- route_proc(route, context)
160
+ def process_root_node(tree, context)
161
+ root_value = tree.values[0]
162
+ has_arbitrary_param = root_value.start_with?(":")
163
+
164
+ child_procs = build_child_procs(tree, context)
165
+ route_procs = build_route_procs(tree, context)
166
+
167
+ if has_arbitrary_param
168
+ build_param_root_proc(root_value, child_procs, route_procs)
169
+ else
170
+ build_string_root_proc(root_value, child_procs, route_procs)
141
171
  end
172
+ end
142
173
 
143
- procs << if tree.children.length > 0
144
- if has_arbitrary_param
145
- Proc.new do |r|
146
- r.on String do |param_val|
147
- route_parts.each do |route_part|
148
- r.params[route_part] = param_val
149
- end
174
+ def process_nested_node(tree, context)
175
+ has_arbitrary_param = tree.values[0].start_with?(":")
150
176
 
151
- child_procs.each do |child_proc|
152
- r.instance_exec(r, &child_proc)
153
- end
177
+ child_procs = build_child_procs(tree, context)
178
+ route_procs = build_route_procs(tree, context)
154
179
 
155
- r.is do
156
- route_procs.each do |route_proc|
157
- r.instance_exec(r, &route_proc)
158
- end
180
+ if has_arbitrary_param
181
+ build_param_nested_proc(tree, child_procs, route_procs)
182
+ else
183
+ build_string_nested_proc(tree, child_procs, route_procs)
184
+ end
185
+ end
186
+
187
+ def build_param_root_proc(root_value, child_procs, route_procs)
188
+ param_name = root_value.gsub(":", "")
189
+
190
+ Proc.new do |r|
191
+ r.on String do |param_val|
192
+ r.params[param_name] = param_val
193
+
194
+ child_procs.each do |child_proc|
195
+ r.instance_exec(r, &child_proc)
196
+ end
159
197
 
160
- nil
198
+ if route_procs.any?
199
+ r.is do
200
+ route_procs.each do |route_proc|
201
+ r.instance_exec(r, &route_proc)
161
202
  end
162
203
 
163
204
  nil
164
205
  end
165
206
  end
166
- else
167
- Proc.new do |r|
168
- r.on route_parts[0] do
169
- child_procs.each do |child_proc|
170
- r.instance_exec(r, &child_proc)
171
- end
172
207
 
173
- r.is do
174
- route_procs.each do |route_proc|
175
- r.instance_exec(r, &route_proc)
176
- end
208
+ nil
209
+ end
210
+ end
211
+ end
212
+
213
+ def build_string_root_proc(root_value, child_procs, route_procs)
214
+ Proc.new do |r|
215
+ r.on root_value do
216
+ child_procs.each do |child_proc|
217
+ r.instance_exec(r, &child_proc)
218
+ end
177
219
 
178
- nil
220
+ if route_procs.any?
221
+ r.is do
222
+ route_procs.each do |route_proc|
223
+ r.instance_exec(r, &route_proc)
179
224
  end
180
225
 
181
226
  nil
182
227
  end
183
228
  end
229
+
230
+ nil
184
231
  end
185
- else
186
- Proc.new do |r|
187
- if has_arbitrary_param
188
- r.is String do |param_val|
189
- route_parts.each do |route_part|
190
- r.params[route_part] = param_val
191
- end
232
+ end
233
+ end
192
234
 
193
- r.is do
194
- route_procs.each do |route_proc|
195
- r.instance_exec(r, &route_proc)
196
- end
235
+ def build_param_nested_proc(tree, child_procs, route_procs)
236
+ route_parts = tree.values.map { |v| v.gsub(":", "") }
237
+
238
+ Proc.new do |r|
239
+ r.on String do |param_val|
240
+ route_parts.each do |route_part|
241
+ r.params[route_part] = param_val
242
+ end
197
243
 
198
- nil
244
+ child_procs.each do |child_proc|
245
+ r.instance_exec(r, &child_proc)
246
+ end
247
+
248
+ if route_procs.any?
249
+ r.is do
250
+ route_procs.each do |route_proc|
251
+ r.instance_exec(r, &route_proc)
199
252
  end
200
253
 
201
254
  nil
202
255
  end
203
- else
204
- r.is route_parts[0] do
205
- r.is do
206
- route_procs.each do |route_proc|
207
- r.instance_exec(r, &route_proc)
208
- end
256
+ end
209
257
 
210
- nil
258
+ nil
259
+ end
260
+ end
261
+ end
262
+
263
+ def build_string_nested_proc(tree, child_procs, route_procs)
264
+ route_part = tree.values[0]
265
+
266
+ Proc.new do |r|
267
+ r.on route_part do
268
+ child_procs.each do |child_proc|
269
+ r.instance_exec(r, &child_proc)
270
+ end
271
+
272
+ if route_procs.any?
273
+ r.is do
274
+ route_procs.each do |route_proc|
275
+ r.instance_exec(r, &route_proc)
211
276
  end
212
277
 
213
278
  nil
214
279
  end
215
280
  end
281
+
282
+ nil
216
283
  end
217
284
  end
285
+ end
218
286
 
219
- Proc.new do |r|
220
- procs.each do |proc|
221
- r.instance_exec(r, &proc)
222
- end
287
+ def build_child_procs(tree, context)
288
+ tree.children.map do |child|
289
+ build_traverse_tree_proc(child, context)
290
+ end
291
+ end
292
+
293
+ def build_route_procs(tree, context)
294
+ tree.routes.map do |route|
295
+ route_proc(route, context)
223
296
  end
224
297
  end
225
298
  end
@@ -251,4 +324,4 @@ class Roda
251
324
 
252
325
  register_plugin(:ree_routes, Roda::RodaPlugins::ReeRoutes)
253
326
  end
254
- end
327
+ end
@@ -59,7 +59,24 @@ class ReeRoda::BuildRoutingTree
59
59
  end
60
60
 
61
61
  def print_tree(tree = self)
62
- puts "#{get_offset(tree.depth)}#{tree.values.inspect} - #{tree.depth}"
62
+ if tree.is_a?(Array)
63
+ puts "Multiple trees:"
64
+ tree.each_with_index do |t, i|
65
+ puts "\nTree #{i + 1}:"
66
+ print_tree(t)
67
+ end
68
+ return nil
69
+ end
70
+
71
+ puts "#{get_offset(tree.depth)}#{tree.values.inspect} - depth: #{tree.depth}, type: #{tree.type}"
72
+
73
+ if tree.routes.any?
74
+ tree.routes.each do |route|
75
+ puts "#{get_offset(tree.depth + 1)}- #{route.request_method} #{route.path}"
76
+ puts "#{get_offset(tree.depth + 2)} summary: #{route.summary}"
77
+ puts "#{get_offset(tree.depth + 2)} override: #{route.override ? 'YES' : 'NO'}"
78
+ end
79
+ end
63
80
 
64
81
  if tree.children.length > 0
65
82
  tree.children.each do |child|
@@ -70,48 +87,76 @@ class ReeRoda::BuildRoutingTree
70
87
  nil
71
88
  end
72
89
 
73
- def print_proc_tree(tree = self)
74
- param_value = tree.values[0].start_with?(":") ? String : "\"#{tree.values[0]}\""
90
+ def print_proc_tree(tree = self, is_root_array: false)
91
+ if tree.is_a?(Array)
92
+ puts "Multiple root trees found:"
93
+ tree.each_with_index do |t, i|
94
+ puts "\nTree #{i + 1}:"
95
+ print_proc_tree(t)
96
+ end
97
+ return nil
98
+ end
75
99
 
76
- if tree.routes.length == 0
77
- if tree.children.length > 0
78
- puts "#{get_offset(tree.depth)}r.on #{param_value} do"
100
+ if tree.depth == 0
101
+ param_value = tree.values[0].start_with?(":") ? String : "\"#{tree.values[0]}\""
79
102
 
80
- tree.children.each do |child|
81
- print_proc_tree(child)
82
- end
103
+ puts "r.on #{param_value} do"
83
104
 
84
- puts "#{get_offset(tree.depth)}end"
105
+ tree.children.each do |child|
106
+ print_proc_tree(child)
85
107
  end
86
108
 
87
- nil
109
+ if tree.routes.any?
110
+ puts " r.is do"
111
+ tree.routes.each do |route|
112
+ puts " r.#{route.request_method} do"
113
+ if route.override
114
+ puts " # OVERRIDE: custom logic"
115
+ puts " # Summary: #{route.summary}"
116
+ else
117
+ puts " # Action: #{route.action&.name}"
118
+ puts " # Serializer: #{route.serializer&.name}" if route.serializer
119
+ puts " # Warden scope: #{route.warden_scope}"
120
+ end
121
+ puts " end"
122
+ end
123
+ puts " end"
124
+ end
125
+
126
+ puts "end"
127
+
88
128
  else
89
- if tree.children.length > 0
90
- puts "#{get_offset(tree.depth)}r.on #{param_value} do"
129
+ has_arbitrary_param = tree.values[0].start_with?(":")
130
+ param_value = has_arbitrary_param ? String : "\"#{tree.values[0]}\""
131
+
132
+ indent = " " * tree.depth
133
+
134
+ if tree.children.length > 0 || tree.routes.length > 0
135
+ puts "#{indent}r.on #{param_value} do"
136
+
91
137
 
92
138
  tree.children.each do |child|
93
139
  print_proc_tree(child)
94
140
  end
95
141
 
96
- puts "#{get_offset(tree.depth + 1)}r.is do"
97
- tree.routes.each do |route|
98
- puts "#{get_offset(tree.depth + 2)}r.#{route.request_method} do"
99
- puts "#{get_offset(tree.depth + 2)}end"
100
- end
101
- puts "#{get_offset(tree.depth + 1)}end"
102
-
103
- puts "#{get_offset(tree.depth)}end"
104
- else
105
- puts "#{get_offset(tree.depth)}r.is #{param_value} do"
106
-
107
- puts "#{get_offset(tree.depth + 1)}r.is do"
108
- tree.routes.each do |route|
109
- puts "#{get_offset(tree.depth + 2)}r.#{route.request_method} do"
110
- puts "#{get_offset(tree.depth + 2)}end"
142
+ if tree.routes.any?
143
+ puts "#{indent} r.is do"
144
+ tree.routes.each do |route|
145
+ puts "#{indent} r.#{route.request_method} do"
146
+ if route.override
147
+ puts "#{indent} # OVERRIDE: custom logic"
148
+ puts "#{indent} # Summary: #{route.summary}"
149
+ else
150
+ puts "#{indent} # Action: #{route.action&.name}"
151
+ puts "#{indent} # Serializer: #{route.serializer&.name}" if route.serializer
152
+ puts "#{indent} # Warden scope: #{route.warden_scope}"
153
+ end
154
+ puts "#{indent} end"
155
+ end
156
+ puts "#{indent} end"
111
157
  end
112
- puts "#{get_offset(tree.depth + 1)}end"
113
158
 
114
- puts "#{get_offset(tree.depth)}end"
159
+ puts "#{indent}end"
115
160
  end
116
161
  end
117
162
 
@@ -125,46 +170,54 @@ class ReeRoda::BuildRoutingTree
125
170
  end
126
171
  end
127
172
 
128
- contract(ArrayOf[ReeRoutes::Route] => Nilor[RoutingTree])
173
+ contract(ArrayOf[ReeRoutes::Route] => ArrayOf[RoutingTree])
129
174
  def call(routes)
130
- tree = nil
175
+ trees = []
131
176
 
132
177
  routes.each do |route|
133
- splitted = route.path.split("/")
134
- parent_tree = tree
135
-
136
- splitted.each_with_index do |v, j|
137
- if tree.nil?
138
- tree = RoutingTree.new([v], j, :string)
139
- parent_tree = tree
140
- next
178
+ splitted = route.path.split("/").reject(&:empty?)
179
+ matched_tree = nil
180
+
181
+ root_part = splitted[0]
182
+
183
+ # find tree for root segment
184
+ trees.each do |tree|
185
+ if tree.values.include?(root_part)
186
+ matched_tree = tree
187
+ break
141
188
  end
189
+ end
190
+
191
+ if matched_tree.nil?
192
+ # create new tree for root
193
+ matched_tree = RoutingTree.new([root_part], 0, :string)
194
+ trees << matched_tree
195
+ end
196
+
197
+ parent_tree = matched_tree
142
198
 
143
- current = parent_tree.find_by_value(value: v, depth: j)
199
+ # process other parts
200
+ splitted[1..-1].each_with_index do |v, i|
201
+ current = parent_tree.find_by_value(value: v, depth: i+1)
144
202
 
145
203
  if current
146
204
  parent_tree = current
147
- current.add_route(route) if j == (splitted.length - 1)
148
205
  else
149
- if !parent_tree.any_child_has_value?(v)
150
- if parent_tree.children.any? { |c| c.type == :param } && v.start_with?(":")
151
- param_child = parent_tree.children.find { |c| c.type == :param }
152
- param_child.values << v if !param_child.values.include?(v)
153
- param_child.add_route(route) if j == (splitted.length - 1)
154
- parent_tree = param_child
155
-
156
- next
157
- end
158
-
159
- new_tree = parent_tree.add_child(v, j, v.start_with?(":") ? :param : :string)
206
+ # check if we can add it to existing param node
207
+ if parent_tree.children.any? { |c| c.type == :param } && v.start_with?(":")
208
+ param_child = parent_tree.children.find { |c| c.type == :param }
209
+ param_child.values << v if !param_child.values.include?(v)
210
+ parent_tree = param_child
211
+ else
212
+ new_tree = parent_tree.add_child(v, i+1, v.start_with?(":") ? :param : :string)
160
213
  parent_tree = new_tree
161
214
  end
162
-
163
- parent_tree.add_route(route) if j == (splitted.length - 1)
164
215
  end
165
216
  end
217
+
218
+ parent_tree.add_route(route)
166
219
  end
167
220
 
168
- tree
221
+ trees
169
222
  end
170
- end
223
+ end
@@ -75,6 +75,21 @@ RSpec.describe ReeRoda::App do
75
75
  end
76
76
  end
77
77
 
78
+ class ReeRodaTest::WardenScopeCmd
79
+ include ReeActions::DSL
80
+
81
+ action :warden_scope_cmd
82
+
83
+ ActionCaster = build_mapper.use(:cast) do
84
+ string? :user
85
+ string? :another_user
86
+ end
87
+
88
+ def call(access, attrs)
89
+ {result: access.to_s}
90
+ end
91
+ end
92
+
78
93
  class ReeRodaTest::ActionCmd
79
94
  include ReeActions::DSL
80
95
 
@@ -110,6 +125,19 @@ RSpec.describe ReeRoda::App do
110
125
  default_warden_scope :identity
111
126
  opts = {from: :ree_roda_test}
112
127
 
128
+ get "some_other_route" do
129
+ summary "Another route"
130
+ warden_scope :visitor
131
+ sections "some_action"
132
+ action :cmd, **opts
133
+ override do |r|
134
+ r.json do
135
+ r.response.status = 200
136
+ "hello"
137
+ end
138
+ end
139
+ end
140
+
113
141
  get "api/action/:id" do
114
142
  summary "Some action"
115
143
  warden_scope :visitor
@@ -187,6 +215,13 @@ RSpec.describe ReeRoda::App do
187
215
  action :serializer_error_cmd, **opts
188
216
  serializer :serializer, **opts
189
217
  end
218
+
219
+ get "check_warden" do
220
+ summary "Action to check Warden scopes"
221
+ warden_scope :user, :another_user
222
+ sections "some_action"
223
+ action :warden_scope_cmd, **opts
224
+ end
190
225
  end
191
226
  end
192
227
 
@@ -202,13 +237,43 @@ RSpec.describe ReeRoda::App do
202
237
  end
203
238
  end
204
239
 
240
+ class UserStrategy < Warden::Strategies::Base
241
+ include Ree::LinkDSL
242
+
243
+ def valid?
244
+ params = request.params
245
+ return true if !params["user"].nil?
246
+ end
247
+
248
+ def authenticate!
249
+ success!({user: "user"})
250
+ end
251
+ end
252
+
253
+ class AnotherUserStrategy < Warden::Strategies::Base
254
+ include Ree::LinkDSL
255
+
256
+ def valid?
257
+ params = request.params
258
+ return true if !params["another_user"].nil?
259
+ end
260
+
261
+ def authenticate!
262
+ success!({user: "another_user"})
263
+ end
264
+ end
265
+
205
266
  Warden::Strategies.add(:visitor, VisitorStrategy)
267
+ Warden::Strategies.add(:user, UserStrategy)
268
+ Warden::Strategies.add(:another_user, AnotherUserStrategy)
206
269
 
207
270
  class TestApp < ReeRoda::App
208
271
  use Warden::Manager do |config|
209
272
  config.default_strategies :visitor
210
273
  config.default_scope = :visitor
211
274
  config.scope_defaults :visitor, strategies: [:visitor], store: false
275
+ config.scope_defaults :user, strategies: [:user], store: false
276
+ config.scope_defaults :another_user, strategies: [:another_user], store: false
212
277
 
213
278
  config.failure_app = -> (env) {
214
279
  [
@@ -292,4 +357,24 @@ RSpec.describe ReeRoda::App do
292
357
  get "api/serializer_error"
293
358
  expect(last_response.status).to eq(500)
294
359
  }
295
- end
360
+
361
+ it {
362
+ get "some_other_route"
363
+ expect(last_response.status).to eq(200)
364
+ expect(last_response.status).not_to eq(404)
365
+ }
366
+
367
+ it {
368
+ # first scope is passed
369
+ get "check_warden?user=hello"
370
+ expect(last_response.status).to eq(200)
371
+
372
+ # second scope is passed
373
+ get "check_warden?another_user=hello"
374
+ expect(last_response.status).to eq(200)
375
+
376
+ # all scopes failed
377
+ get "check_warden"
378
+ expect(last_response.status).to eq(401)
379
+ }
380
+ end
@@ -231,8 +231,9 @@ RSpec.describe :build_routing_tree do
231
231
  }
232
232
 
233
233
  it {
234
- tree = build_routing_tree(routes)
234
+ trees = build_routing_tree(routes)
235
235
 
236
+ tree = trees.first
236
237
  # check that all end nodes have routes
237
238
  # and that not end nodes don't have route
238
239
  id_nodes = [*tree.find_by_value(value: ":id", depth: 2), *tree.find_by_value(value: ":id", depth: 4)]
@@ -273,4 +274,4 @@ RSpec.describe :build_routing_tree do
273
274
  res = TestErrorApp.app.call(env)
274
275
  expect(res).to eq [404, {"content-length"=>"0", "content-type"=>"text/html"}, []]
275
276
  }
276
- end
277
+ end
@@ -44,8 +44,8 @@ module ReeRoutes
44
44
  Ree.container.compile(@dsl.package, name)
45
45
  end
46
46
 
47
- def default_warden_scope(method_name)
48
- @default_warden_scope = method_name
47
+ def default_warden_scope(*method_names)
48
+ @default_warden_scopes = method_names
49
49
  end
50
50
 
51
51
  [:get, :post, :put, :delete, :patch, :head, :options].each do |request_method|
@@ -66,8 +66,8 @@ module ReeRoutes
66
66
  builder = ReeRoutes::RouteBuilder.new
67
67
  builder.instance_exec(&proc)
68
68
 
69
- if @default_warden_scope && !builder.get_route.warden_scope
70
- builder.warden_scope(@default_warden_scope)
69
+ if @default_warden_scopes && (!builder.get_route.warden_scopes || builder.get_route.warden_scopes.empty?)
70
+ builder.warden_scope(*@default_warden_scopes)
71
71
  end
72
72
 
73
73
  uri = URI.parse(path) rescue nil
@@ -100,4 +100,4 @@ module ReeRoutes
100
100
  end
101
101
  end
102
102
  end
103
- end
103
+ end
@@ -2,9 +2,21 @@
2
2
 
3
3
  class ReeRoutes::Route
4
4
  attr_accessor :summary, :request_method, :serializer, :respond_to,
5
- :sections, :action, :route, :warden_scope, :path, :override
5
+ :sections, :action, :route, :warden_scopes, :path, :override
6
6
 
7
7
  def valid?
8
- !action.nil? && !summary.nil? && !warden_scope.nil?
8
+ !action.nil? && !summary.nil? && !warden_scopes.nil? && !warden_scopes.empty?
9
9
  end
10
- end
10
+
11
+ def warden_scopes=(scopes)
12
+ @warden_scopes = Array(scopes)
13
+ end
14
+
15
+ def warden_scope
16
+ @warden_scopes&.first
17
+ end
18
+
19
+ def warden_scope=(scope)
20
+ @warden_scopes = Array(scope)
21
+ end
22
+ end
@@ -10,9 +10,9 @@ class ReeRoutes::RouteBuilder
10
10
  @route.respond_to = :json
11
11
  end
12
12
 
13
- contract Symbol => Symbol
14
- def warden_scope(scope)
15
- @route.warden_scope = scope
13
+ contract SplatOf[Symbol] => ArrayOf[Symbol]
14
+ def warden_scope(*scopes)
15
+ @route.warden_scopes = scopes.flatten
16
16
  end
17
17
 
18
18
  contract Symbol => Symbol
@@ -68,4 +68,4 @@ class ReeRoutes::RouteBuilder
68
68
  @route.redirect = Redirect.new(path, code)
69
69
  nil
70
70
  end
71
- end
71
+ end
@@ -50,18 +50,20 @@ RSpec.describe ReeRoutes::DSL, type: [:autoclean] do
50
50
  include ReeRoutes::DSL
51
51
 
52
52
  routes :routes do
53
- default_warden_scope :user
53
+ default_warden_scope :identity, :user
54
54
 
55
55
  post "users" do
56
56
  summary "Test route"
57
57
  action :cmd, from: :ree_routes_test
58
58
  serializer :serializer, from: :ree_routes_test
59
+ warden_scope :identity, :user
59
60
  respond_to :json
60
61
  end
61
62
 
62
63
  get "files.csv" do
63
64
  summary "Test route"
64
65
  action :cmd, from: :ree_routes_test
66
+ warden_scope :user
65
67
  respond_to :csv
66
68
  end
67
69
  end
@@ -90,4 +92,4 @@ RSpec.describe ReeRoutes::DSL, type: [:autoclean] do
90
92
 
91
93
  expect(csv_route.respond_to).to eq(:csv)
92
94
  }
93
- end
95
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ReeLib
4
- VERSION = "1.3.3"
4
+ VERSION = "1.3.4"
5
5
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ree_lib
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.3
4
+ version: 1.3.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ruslan Gatiyatov
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-10-05 00:00:00.000000000 Z
10
+ date: 2026-02-03 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: ree