hubssolib 3.8.0 → 3.8.1

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: 32438e5c41d655367f4bb0e8385b9d972645f2649871a09ab7b09dc5d617fe9e
4
- data.tar.gz: a999f01f88325690644675acc1b06b33b7b275374e980c6c3f2fa346c3875d93
3
+ metadata.gz: 5fea64186dc1f80987fb5b531c46ac8eb9fff78878520b38e392a91dad8de7a9
4
+ data.tar.gz: 2ebe2f6599cbd9bf9dbfbaa6ebbbb81e99fe6f4922c5f8c19e250e380222c3c9
5
5
  SHA512:
6
- metadata.gz: 881e57fa9c2e42ed8465b2faabf98cabdacf2dcea5df20d3c617836e50ff74d2255bbe1b8c11ca39b0bb3d57f2927e229ca1a390de11d0fcff9b8e4b32851ae6
7
- data.tar.gz: 15aa2e97054fe9a8a86e45d901bdfa36bff0d0a6473ba88d279ec0bf622ce8413e6bc1a7b0427bac1f0e2bc0c2b994d9a3550d48897a8efec7cf2acf0c74abfa
6
+ metadata.gz: 44b066f10c3615a752b258d85ccf5316358c33af6589c9702ab6b2ae8036f6e7eda9f99ab2a2707dc9acce9e9377ce5e73f28c3533eaec7c7312ac5e6e828fe3
7
+ data.tar.gz: 1f7ae4d9e29916eb3d14e3c057b61f95192be76954270fd8570dd596a5552495561df2bddd1f16f887ac613bbcd3292fd75228f4bbddf87faeda698c2a866067
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## 3.8.1, 09-Apr-2025
2
+
3
+ * It's been too long since I worked with DRb! Important fix for "live" (undumpable) vs copied objects which could lead to session enumeration problems in clients. Now, sessions enumerated by user ID are copies as is user data returned by HubSsoLib::Core#hubssolib_enumerate_users.
4
+ * Other data is still live, since there's a fair amount of write-back that expects to be updating objects held by the DRb server itself. This will all get replaced by database storage in HubSsoLib 4, so I'm not going to address the weaknesses present wherein a session might be expired or deleted "under the feet" of a client. The Hub gem's own write-based operations are all on a "current" session, so that could only vanish if an admin independently elected to destroy all user sessions via the Hub Rails app front-end. The implication is that the other user was probably up to no good, and I don't really mind if they just seem to be suddenly logged out, or see a 500 error due to a _very_ inconveniently-timed page fetch.
5
+
1
6
  ## 3.8.0, 03-Apr-2025
2
7
 
3
8
  * Adds helper `HubSsoLib::Core#hubssolib_flash_markup` to compliment `HubSsoLib::Core#hubssolib_flash_data` and help make Flash presentation simpler and more consistent across integrated applications.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- hubssolib (3.8.0)
4
+ hubssolib (3.8.1)
5
5
  base64 (~> 0.2)
6
6
  drb (~> 2.2)
7
7
 
@@ -178,7 +178,7 @@ GEM
178
178
  rake (13.2.1)
179
179
  rdoc (6.13.1)
180
180
  psych (>= 4.0.0)
181
- reline (0.6.0)
181
+ reline (0.6.1)
182
182
  io-console (~> 0.5)
183
183
  rspec (3.13.0)
184
184
  rspec-core (~> 3.13.0)
Binary file
data/hubssolib.gemspec CHANGED
@@ -4,7 +4,7 @@ spec = Gem::Specification.new do |s|
4
4
  s.platform = Gem::Platform::RUBY
5
5
  s.name = 'hubssolib'
6
6
 
7
- s.version = '3.8.0'
7
+ s.version = '3.8.1'
8
8
  s.author = 'Andrew Hodgkinson and others'
9
9
  s.email = 'ahodgkin@rowing.org.uk'
10
10
  s.homepage = 'http://pond.org.uk/'
data/lib/hub_sso_lib.rb CHANGED
@@ -366,17 +366,16 @@ module HubSsoLib
366
366
  # 26-Feb-2025 (ADH): Add 'trusted' concept. #
367
367
  #######################################################################
368
368
 
369
+ # This *must not* be 'undumped', since it gets passed from clients back to
370
+ # the persistent DRb server process. A client thread may disappear and be
371
+ # recreated by the web server at any time; if the user object is undumpable,
372
+ # then the DRb server has to *call back to the client* (in DRb, clients are
373
+ # also servers...!) to find out about the object. Trouble is, if the client
374
+ # thread has been recreated, the server will be trying to access to stale
375
+ # objects that only exist if the garbage collector hasn't got to them yet.
376
+ #
369
377
  class User
370
378
 
371
- # This *must not* be 'undumped', since it gets passed from clients
372
- # back to the persistent DRb server process. A client thread may
373
- # disappear and be recreated by the web server at any time; if the
374
- # user object is undumpable, then the DRb server has to *call back
375
- # to the client* (in DRb, clients are also servers...!) to find out
376
- # about the object. Trouble is, if the client thread has been
377
- # recreated, the server will be trying to access to stale objects
378
- # that only exist if the garbage collector hasn't got to them yet.
379
-
380
379
  attr_accessor :user_salt
381
380
  attr_accessor :user_roles
382
381
  attr_accessor :user_updated_at
@@ -397,8 +396,8 @@ module HubSsoLib
397
396
  end # User class
398
397
 
399
398
  #######################################################################
400
- # Class: Session #
401
- # (C) Hipposoft 2006 #
399
+ # Class: Session family #
400
+ # (C) Hipposoft 2006-2025 #
402
401
  # #
403
402
  # Purpose: Session support object, used to store session metadata in #
404
403
  # an insecure cross-application cookie. #
@@ -406,37 +405,67 @@ module HubSsoLib
406
405
  # Author: A.D.Hodgkinson #
407
406
  # #
408
407
  # History: 22-Oct-2006 (ADH): Created. #
408
+ # 09-Apr-2025 (ADH): Dumpable/undumpable variants created. #
409
409
  #######################################################################
410
410
 
411
- class Session
412
-
413
- # Unlike a User, this *is* undumpable since it only gets passed from
414
- # server to client. The server's always here to service requests
415
- # from the client and used sessions are never garbage collected
416
- # since the DRb server's front object, a SessionFactory, keeps them
417
- # in a hash held within an instance variable.
418
-
419
- include DRb::DRbUndumped
420
-
421
- attr_accessor :session_last_used
422
- attr_reader :session_return_to # DEPRECATED
423
- attr_accessor :session_flash
424
- attr_accessor :session_user
425
- attr_accessor :session_rotated_key
426
-
427
- def initialize
428
- @session_last_used = Time.now.utc
429
- @session_return_to = nil
430
- @session_flash = {}
431
- @session_user = HubSsoLib::User.new
432
- @session_rotated_key = nil
411
+ # A dumpable base class that can be used for undumpable proxies, where a
412
+ # change made in an object passed to a client is reflected on the server
413
+ # where the object actually lives; or for dumpable clones of sessions sent
414
+ # as read-only copies to clients which won't disppear due to server side
415
+ # deletion from key rotation, expiry or admin-driven deletion.
416
+ #
417
+ class SessionBase
418
+
419
+ ATTRIBUTES = %i{
420
+ session_last_used
421
+ session_flash
422
+ session_user
423
+ session_rotated_key
424
+ }
425
+
426
+ ATTRIBUTES.each { | attr | attr_accessor(attr) }
427
+ attr_reader :session_return_to # DEPRECATED
428
+
429
+ def initialize(copying_session: nil)
430
+ if copying_session.nil?
431
+ self.session_last_used = Time.now.utc
432
+ self.session_flash = {}
433
+ self.session_user = HubSsoLib::User.new
434
+ self.session_rotated_key = nil
435
+ else
436
+ ATTRIBUTES.each do | attr |
437
+ self.send("#{attr}=", copying_session.send(attr))
438
+ end
439
+ end
433
440
 
434
441
  rescue => e
435
442
  Sentry.capture_exception(e) if defined?(Sentry) && Sentry.respond_to?(:capture_exception)
436
443
  raise
437
444
  end
445
+
446
+ end # SessionBase class
447
+
448
+ # Unlike a User, this *is* undumpable since it only gets passed from server
449
+ # to client. The server's always here to service requests from the client and
450
+ # used sessions are never garbage collected since the DRb server's front
451
+ # object, a SessionFactory, keeps them in a hash held within an instance
452
+ # variable.
453
+ #
454
+ # A recognised weakness here is that a session might disappear from under the
455
+ # feet of an accessing application, due to key rotation or explicit deletion.
456
+ #
457
+ class Session < SessionBase
458
+ include DRb::DRbUndumped
438
459
  end # Session class
439
460
 
461
+ # No special conditions - this is just a dumpable session. You should usually
462
+ # create it based on an undumpable, 'live' session thus:
463
+ #
464
+ # SessionCopy.new(copying_session: undumpable_session)
465
+ #
466
+ class SessionCopy < SessionBase
467
+ end # SessionCopy class
468
+
440
469
  #######################################################################
441
470
  # Class: SessionFactory #
442
471
  # (C) Hipposoft 2006 #
@@ -611,6 +640,16 @@ module HubSsoLib
611
640
  # given session key. No key rotation occurs. Returns +nil+ if no entry is
612
641
  # found for that key.
613
642
  #
643
+ # This returns a *LIVE OBJECT* owned by the DRb server. Writes made to this
644
+ # object will affect the live session state. However, the session might be
645
+ # invalidated at any time by actions such as key rotation, expiration or
646
+ # explicit user deletion. Attempts to read or write properties would then
647
+ # lead to exceptions such as:
648
+ #
649
+ # "424" is not id value (RangeError)
650
+ #
651
+ # ...where 424 is the internal object ID of meaning only to the DRb system.
652
+ #
614
653
  def retrieve_session_by_key(key)
615
654
  HUB_MUTEX.synchronize { @hub_sessions[key] }
616
655
  end
@@ -622,15 +661,24 @@ module HubSsoLib
622
661
  # values yielding HubSsoLib::Session instances as values is returned.
623
662
  #
624
663
  # The array is ordered by least-recently-active first to most-recent last.
664
+ # Returned data is a copy of internal session information and should be
665
+ # considered read-only; changes made will have no effect outside your own
666
+ # application.
625
667
  #
626
668
  # IN THE CURRENT IMPLEMENTATION THIS JUST SEQUENTIALLY SCANS ALL ACTIVE
627
669
  # SESSIONS IN THE HASH and must therefore lock on mutex for the duration.
628
670
  #
629
671
  def retrieve_sessions_by_user_id(user_id)
630
672
  HUB_MUTEX.synchronize do
631
- @hub_sessions.select do | key, session |
632
- session&.session_user&.user_id == user_id
673
+ collection = {}
674
+
675
+ @hub_sessions.each do | key, session |
676
+ if session&.session_user&.user_id == user_id
677
+ collection[key] = SessionCopy.new(copying_session: session)
678
+ end
633
679
  end
680
+
681
+ collection
634
682
  end
635
683
  end
636
684
 
@@ -647,6 +695,8 @@ module HubSsoLib
647
695
  @hub_sessions.delete(key)
648
696
  end
649
697
 
698
+ return nil
699
+
650
700
  rescue => e
651
701
  Sentry.capture_exception(e) if defined?(Sentry) && Sentry.respond_to?(:capture_exception)
652
702
  raise
@@ -672,6 +722,8 @@ module HubSsoLib
672
722
  end
673
723
  end
674
724
 
725
+ return nil
726
+
675
727
  rescue => e
676
728
  Sentry.capture_exception(e) if defined?(Sentry) && Sentry.respond_to?(:capture_exception)
677
729
  raise
@@ -696,6 +748,8 @@ module HubSsoLib
696
748
  end
697
749
  end
698
750
 
751
+ return nil
752
+
699
753
  rescue => e
700
754
  Sentry.capture_exception(e) if defined?(Sentry) && Sentry.respond_to?(:capture_exception)
701
755
  raise
@@ -738,6 +792,8 @@ module HubSsoLib
738
792
  puts "Session factory: ...Destroyed #{destroyed} session(s)"
739
793
  end
740
794
 
795
+ return nil
796
+
741
797
  rescue => e
742
798
  Sentry.capture_exception(e) if defined?(Sentry) && Sentry.respond_to?(:capture_exception)
743
799
  raise
@@ -1251,8 +1307,8 @@ module HubSsoLib
1251
1307
 
1252
1308
  unless hub_session_info[:keys].nil? # (keyset too large, enumeration prohibited)
1253
1309
  hub_session_info[:keys].each do | key |
1254
- session = hubssolib_factory().retrieve_session_by_key(key)
1255
- hub_users << session.session_user unless session&.session_user&.user_id.nil?
1310
+ session_user = hubssolib_factory().retrieve_session_by_key(key)&.session_user
1311
+ hub_users << session_user unless session_user&.user_id.nil?
1256
1312
  end
1257
1313
  end
1258
1314
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hubssolib
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.8.0
4
+ version: 3.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Hodgkinson and others
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-04-04 00:00:00.000000000 Z
10
+ date: 2025-04-09 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: drb
@@ -138,6 +138,7 @@ files:
138
138
  - Gemfile
139
139
  - Gemfile.lock
140
140
  - README.md
141
+ - hubssolib-3.7.0.gem
141
142
  - hubssolib.gemspec
142
143
  - lib/hub_sso_lib.rb
143
144
  homepage: http://pond.org.uk/