blix-rest 0.7.2 → 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cf93b3d5836172b6cf1b4ac5df21dfe14e1e998e31e774f9b4fdb4bc5bdec323
4
- data.tar.gz: 622db8bf8d0052fd25f3727656ac6b641bc63a2667e97eb3f93f7dc4884e03ee
3
+ metadata.gz: 5db97b519f38052ee2b7272f3a25d6ec4d5e3ba71cae44bdcd83e25cdd6902f2
4
+ data.tar.gz: e7fb1c1da94eb622629a718bd81763d6874dc14028bed0ba8328b42cac5c2152
5
5
  SHA512:
6
- metadata.gz: 32516afd36a4a6c36c81650e50f84970cf2436b7cf682a51cae83d1300f736d4dbfe49d04d590ac8ffde841d2dac7f236d0979b3b5c1d5bec230112584eb6e0d
7
- data.tar.gz: 7f106344ec03beb691d5870c5809f379285d578ba17cb9b8edd1ea86c5c64dfa31b0a9747a75adab7730ba514cecca3a508cb36f5560343f147cd64d866ca3d4
6
+ metadata.gz: fb48999da4fffe47e1d52cb85319c7ed6473c756a55d6e87edef288a9a118f971c90d709ea73aaf566e1f927a7779056547a91d1cfae71b2cd1a157658c3d2a4
7
+ data.tar.gz: 93d06074a5b66da9099c1d1bee4fb23a00ac18f994809efb9fb28f0be7d6bf3a889fdad45a2fb349dbabeec6c816c77a34975a8cd7de70efbcce4cff2af1acb2
data/README.md CHANGED
@@ -231,6 +231,7 @@ have access to a number of methods
231
231
  method : the request method lowercase( 'get'/'post' ..)
232
232
  req : the rack request
233
233
  body : the request body as a string
234
+ path : the request path
234
235
  query_params : a hash of parameters as passed in the url as parameters
235
236
  path_params : a hash of parameters constructed from variable parts of the path
236
237
  post_params : a hash of parameters passed in the body of the request
@@ -246,7 +247,7 @@ have access to a number of methods
246
247
  render_erb : (template_name [,:layout=>name])
247
248
  server_cache : get the server cache object
248
249
  server_cache_get : retrieve/store value in cache
249
- path_for : (path) give the correct path for an internal path
250
+ path_for : (path) give the external path for an internal path
250
251
  url_for : (path) give the full url for an internal path
251
252
  h : escape html string to avoid XSS
252
253
  escape_javascript : escape a javascript string
@@ -291,22 +292,27 @@ is ok though.
291
292
 
292
293
  the `before_route` hook can be used to modify the path or options of a route.
293
294
 
294
- *NOTE* ! when manipulating the path you have to modify the string object in place.
295
-
296
295
  the verb can not be modified
297
296
 
298
297
  example:
299
298
 
300
299
  class MyController < Blix::Rest::Controller
301
300
 
302
- before_route do |verb, path, opts|
303
- opts[:level] = :visitor unless opts[:level]
304
- path.prepend('/') unless path[0] == '/'
305
- path.prepend('/app') unless path[0, 4] == '/app'
301
+ before_route do |route|
302
+ route.default_option(:level,:visitor)
303
+ route.prefix_path('/app')
306
304
  end
307
305
  ...
308
306
  end
309
307
 
308
+ the following methods are available on the route:
309
+
310
+ verb # readonly, the 'GET','POST' etc verb of the route
311
+ path # the path of the route
312
+ options # the options associated with the route eg :accept
313
+ path_prefix('/xx') # ensure the path has the given prefix
314
+ default_option(:xxx,'foo') # ensure that option has the given default value
315
+
310
316
  ### Sessions
311
317
 
312
318
  the following methods are available in the controller for managing sessions.
@@ -321,11 +327,53 @@ this will generate a new session_id and setup the relevant headers
321
327
 
322
328
  options can include:
323
329
 
324
- :secure => true # secure cookies only
325
- :http = >true # cookies for http only not javascript requests
330
+ :secure => true # secure cookies only
331
+ :http = >true # cookies for http only not javascript requests
326
332
  :samesite =>:strict # use strict x-site policy
327
333
  :samesite =>:lax # use lax x-site policy
328
334
 
335
+ For more complete session management:
336
+
337
+ class MyController < Blix::Rest::Controller
338
+ include Blix::Rest::Session
339
+
340
+ session_name :xxx # optional default'blix'
341
+ session_opts :http=>true # optional
342
+ session_manager: MyManager.new # optional , default Blix::Redis::Store
343
+
344
+
345
+ def myroutine
346
+ @xxx = session['xxx']
347
+
348
+ session['yyy'] = true
349
+ end
350
+
351
+ end
352
+
353
+ options can include:
354
+
355
+ :secure # false
356
+ :http # false
357
+ :samesite # lax
358
+ :path # '/'
359
+ :expire_secs # 30 mins
360
+ :cleanup_every_secs # 5 minutes
361
+ :max_age # nil
362
+
363
+ the following methods are available:
364
+
365
+ reset_session # gen new session id
366
+ session # session hash
367
+ csrf_token # the session csrf token
368
+
369
+ route options that affect sessions:
370
+
371
+ :nosession=>true # no session will be set/retrieved
372
+ :cache=>true # no session will be set/retrieved
373
+ :csrf=>true # request will be validated for calid csrf token.
374
+ # token must be in header X_CSRF_TOKEN field
375
+
376
+ session configuration is inherited from superclass controllers unless overridden.
329
377
 
330
378
  ## Cache
331
379
 
@@ -400,6 +448,31 @@ the cache is not used in development/testmode , only in production mode.
400
448
 
401
449
  only cache pages with **HEADERS** and **CONTENT** that is not user specific.
402
450
 
451
+ ## CORS
452
+
453
+ cross origin site requests
454
+
455
+ MyController < Blix::Rest::Controller
456
+
457
+ get '/info/crosssite' do
458
+ set_accept_cors
459
+ {:data=>'foo'}
460
+ end
461
+
462
+ options '/info/' crosssite' do
463
+ set_accept_cors, :headers=>'Content-Type',
464
+ end
465
+
466
+ end
467
+
468
+ within an `options` response the following parameters can be passes.
469
+
470
+ :origin=>'www.othersite.com' # specify specific allowed origin.
471
+ :methods => [:get] # allowed methods
472
+ :max_age => 86400 # maximum age this auth is valid
473
+ :headers => ['Content-Type','X-OTHER'] # allow additional headers
474
+ :credentials => true # allow requests with credentials
475
+
403
476
  ## Views
404
477
 
405
478
  the location of your views defaults to `app/views` otherwise set it manually with:
@@ -488,6 +561,9 @@ NOTE : if you need to set up your database with users then you can use the follo
488
561
 
489
562
  in features/support/world.rb .........
490
563
 
564
+
565
+ require 'blix/rest/cucumber'
566
+
491
567
  class RestWorld
492
568
 
493
569
  # add a hook to create the user in the database -
@@ -94,6 +94,7 @@ module Blix::Rest
94
94
  end
95
95
  end
96
96
 
97
+
97
98
  def form_hash
98
99
  StringHash.new(req.POST)
99
100
  end
@@ -166,6 +167,14 @@ module Blix::Rest
166
167
  @_parameters
167
168
  end
168
169
 
170
+ def route_params
171
+ @_parameters
172
+ end
173
+
174
+ def route_options
175
+ @_parameters
176
+ end
177
+
169
178
  def response
170
179
  @_response
171
180
  end
@@ -232,6 +241,30 @@ module Blix::Rest
232
241
  [login, password]
233
242
  end
234
243
 
244
+ # set the cors headers
245
+ def set_accept_cors(opts={})
246
+ origin = opts[:origin] || env['HTTP_ORIGIN'] || '*'
247
+ origin = origin.to_s
248
+ if method=='options'
249
+ methods = [opts[:methods] || []].to_a.flatten
250
+ max_age = opts[:max_age] || 86400
251
+ headers = [opts[:headers] || []].to_a.flatten
252
+ credentials = opts.key?(:credentials) ? !!opts[:credentials] : true
253
+ methods = [:get] if methods.empty?
254
+ methods = methods.map{|m| m.to_s.upcase}
255
+ headers = ['Content-Type'] if headers.empty?
256
+ max_age = max_age.to_i
257
+
258
+ add_headers 'Access-Control-Allow-Origin' => origin,
259
+ 'Access-Control-Allow-Methods'=>methods.join(', '),
260
+ 'Access-Control-Allow-Headers'=>headers,
261
+ 'Access-Control-Max-Age'=>max_age, #86400,
262
+ 'Access-Control-Allow-Credentials'=>'true'
263
+ else
264
+ add_headers 'Access-Control-Allow-Origin' => origin
265
+ end
266
+ end
267
+
235
268
  def set_status(value)
236
269
  @_response.status = value.to_i
237
270
  end
@@ -392,6 +425,9 @@ module Blix::Rest
392
425
  response
393
426
  end
394
427
 
428
+ def session_before(opts); end # empty session before hooh
429
+ def session_after; end # empty session after hook
430
+
395
431
  #----------------------------------------------------------------------------------------------------------
396
432
 
397
433
  def _setup(context, _verb, _path, _parameters)
@@ -524,16 +560,18 @@ module Blix::Rest
524
560
  raise ServiceError, 'invalid format for this request' unless accept.index format
525
561
  end
526
562
 
527
- def _do_route_hook(verb, path, opts)
563
+ def _do_route_hook(route)
528
564
  if @_route_hook
529
- superclass._do_route_hook(verb, path, opts) if superclass.respond_to? :_do_route_hook
530
- @_route_hook.call(verb, path, opts)
565
+ superclass._do_route_hook(route) if superclass.respond_to? :_do_route_hook
566
+ @_route_hook.call(route)
531
567
  end
532
568
  end
533
569
 
534
570
  def route(verb, path, opts = {}, &blk)
571
+ path = '/' + path unless path[0] == '/'
535
572
  path = String.new(path) # in case frozen.
536
- _do_route_hook(verb.dup, path, opts)
573
+ route = Route.new(verb, path, opts)
574
+ _do_route_hook(route)
537
575
  proc = lambda do |context|
538
576
  unless opts[:force] && (opts[:accept] == :*)
539
577
  check_format(opts[:accept], context.format)
@@ -541,6 +579,7 @@ module Blix::Rest
541
579
  app = new
542
580
  app._setup(context, verb, path, opts)
543
581
  begin
582
+ app.session_before(opts)
544
583
  app.before(opts)
545
584
  app.__before
546
585
  context.response = app.instance_eval( &blk )
@@ -549,6 +588,7 @@ module Blix::Rest
549
588
  ensure
550
589
  app.__after
551
590
  app.after(opts, context.response)
591
+ app.session_after
552
592
  context.response
553
593
  end
554
594
  end
@@ -0,0 +1,33 @@
1
+ module Blix::Rest
2
+
3
+ # class used to represent a route and to allow manipulation of the
4
+ # options and path of the route before registrATION
5
+
6
+ class Route
7
+
8
+ attr_reader :verb, :path, :opts
9
+ alias_method :method, :verb
10
+ alias_method :options, :opts
11
+
12
+ def initialize(verb, path, opts)
13
+ @verb = verb.dup
14
+ @path = path
15
+ @opts = opts
16
+ end
17
+
18
+ def default_option(key, val)
19
+ opts[key.to_sym] = val unless opts.key?(key) || opts.key?(key.to_sym)
20
+ end
21
+
22
+ def path_prefix(prefix)
23
+ prefix = prefix.to_s
24
+ prefix = '/' + prefix unless prefix[0] == '/'
25
+ path.replace( prefix + path) unless path.start_with?(prefix)
26
+ end
27
+
28
+ def path=(val)
29
+ path.replace(val.to_s)
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,138 @@
1
+ module Blix::Rest
2
+
3
+ module Session
4
+ #----------------------------------------------------------------------------
5
+ #
6
+ # manage the session and authorization
7
+ #
8
+ #----------------------------------------------------------------------------
9
+
10
+ DAY = 24 * 60 * 60
11
+ MIN = 60
12
+ SESSION_NAME = 'blix'
13
+
14
+ SESSION_OPTS = {
15
+ #:secure=>true,
16
+ :http => false,
17
+ :samesite => :lax,
18
+ :path => Blix::Rest.full_path('/'),
19
+ :expire_secs => 30 * MIN, # 30 mins
20
+ :cleanup_every_secs => 5 * 60 # 5 minutes
21
+ #:max_age => nil # session cookie
22
+ }.freeze
23
+
24
+
25
+ def session_manager
26
+ self.class.get_session_manager
27
+ end
28
+
29
+ def session_name
30
+ self.class.get_session_name
31
+ end
32
+
33
+ def session_opts
34
+ self.class.get_session_opts
35
+ end
36
+
37
+ def session
38
+ @__session
39
+ end
40
+
41
+ def csrf_token
42
+ @__session['csrf'] ||= SecureRandom.hex(32)
43
+ end
44
+
45
+ def reset_session
46
+ raise 'login_session missing' unless @__session && @__session_id
47
+ session_manager.delete_session(@__session_id)
48
+ @__session_id = refresh_session_id(session_name, session_opts)
49
+ @__session['csrf'] = SecureRandom.hex(32)
50
+ session_manager.store_session(@__session_id, @__session)
51
+ end
52
+
53
+ # get a session id and use this to retrieve the session information - if any.
54
+ #
55
+ def session_before(opts)
56
+ @__session = {}
57
+
58
+ # do not set session on pages. that will be cached.
59
+ unless opts[:nosession] || opts[:cache]
60
+ @__session_id = get_session_id(session_name, session_opts)
61
+ @__session =
62
+ begin
63
+ session_manager.get_session(@__session_id)
64
+ rescue SessionExpiredError
65
+ @__session_id = refresh_session_id(session_name, session_opts)
66
+ session_manager.get_session(@__session_id)
67
+ end
68
+ end
69
+
70
+ if opts[:csrf]
71
+ if env["HTTP_X_CSRF_TOKEN"] != csrf_token
72
+ send_error("invalid csrf token")
73
+ end
74
+ end
75
+
76
+ end
77
+
78
+ # save the session hash before we go.
79
+ def session_after
80
+ session_manager.store_session(@__session_id, @__session) if @__session_id
81
+ end
82
+
83
+ private
84
+
85
+ def self.included(mod)
86
+ mod.extend Session::ClassMethods
87
+ end
88
+
89
+ module ClassMethods
90
+
91
+ def session_name(name)
92
+ @_sess_name = name.to_s
93
+ end
94
+
95
+ def session_opts(opts)
96
+ @_sess_custom_opts = opts
97
+ end
98
+
99
+ def session_manager(man)
100
+ raise ArgumentError, "incompatible session store" unless man.respond_to?(:get_session)
101
+ raise ArgumentError, "incompatible session store" unless man.respond_to?(:store_session)
102
+ raise ArgumentError, "incompatible session store" unless man.respond_to?(:delete_session)
103
+ @_sess_manager= man
104
+ end
105
+
106
+ def get_session_name
107
+ @_sess_name ||= begin
108
+ if superclass.respond_to?(:get_session_name)
109
+ superclass.get_session_name
110
+ else
111
+ SESSION_NAME
112
+ end
113
+ end
114
+ end
115
+
116
+ def get_session_opts
117
+ @_session_opts ||= begin
118
+ if superclass.respond_to?(:get_session_opts)
119
+ superclass.get_session_opts.merge(@_sess_custom_opts || {})
120
+ else
121
+ SESSION_OPTS.merge(@_sess_custom_opts || {})
122
+ end
123
+ end
124
+ end
125
+
126
+ def get_session_manager
127
+ @_sess_manager ||= begin
128
+ if superclass.respond_to?(:get_session_manager)
129
+ superclass.get_session_manager
130
+ else
131
+ Blix::RedisStore.new(get_session_opts)
132
+ end
133
+ end
134
+ end
135
+
136
+ end # ClassMethods
137
+ end # Session
138
+ end # Blix::Rest
@@ -1,5 +1,5 @@
1
1
  module Blix
2
2
  module Rest
3
- VERSION = "0.7.2"
3
+ VERSION = "0.8.2"
4
4
  end
5
5
  end
data/lib/blix/rest.rb CHANGED
@@ -150,7 +150,7 @@ require 'blix/rest/format_parser'
150
150
  require 'blix/rest/request_mapper'
151
151
  require 'blix/rest/cache'
152
152
  require 'blix/rest/server'
153
- # require 'blix/rest/provider'
153
+ require 'blix/rest/route'
154
154
  require 'blix/rest/controller'
155
155
  # require 'blix/rest/provider_controller'
156
156
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blix-rest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.2
4
+ version: 0.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Clive Andrews
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-09-12 00:00:00.000000000 Z
11
+ date: 2023-09-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httpclient
@@ -109,7 +109,9 @@ files:
109
109
  - lib/blix/rest/request_mapper.rb
110
110
  - lib/blix/rest/resource_cache.rb
111
111
  - lib/blix/rest/response.rb
112
+ - lib/blix/rest/route.rb
112
113
  - lib/blix/rest/server.rb
114
+ - lib/blix/rest/session.rb
113
115
  - lib/blix/rest/string_hash.rb
114
116
  - lib/blix/rest/version.rb
115
117
  - lib/blix/utils.rb