Consider adding a request-specific expires_at
DaanVanVugt opened this issue · comments
Daan van Vugt commented
This way signed global IDs can be compared even if generated in different places (we get this issue with html select elements, and with ids generated across the app).
Example code to add to ApplicationController
:
before_action :set_sgid_expiry
# Set a default expiry for SGIDs which means that any ids generated within this request will have the same value
# and can thus be matched on the frontend
def set_sgid_expiry
SignedGlobalID.expires_at 1.week.from_now
end
Would this be something viable?
Daan van Vugt commented
I have created a solution using ActiveSupport::CurrentAttributes
instead, fearing thread-safety issues with the approach mentioned above.
# app/models/current.rb
class Current < ActiveSupport::CurrentAttributes
attribute :signed_global_id_expires_at
end
# app/controllers/application_controller.rb
before_action :set_sgid_expiry
# Set a default expiry for SGIDs which means that any ids generated within this request will have the same value
# and can thus be matched on the frontend
def set_sgid_expiry
Current.signed_global_id_expires_at = 1.week.from_now
end
# config/initializers/monkey_patches.rb
# Require all Ruby files in the core_extensions directory
Dir[Rails.root.join('lib', 'patches', '*.rb')].each { |f| require f }
SignedGlobalID.prepend Patches::SignedGlobalID
# lib/patches/signed_global_id.rb
module Patches
module SignedGlobalID
def pick_expiration(options)
return options[:expires_at] if options.key?(:expires_at)
return options[:expires_in].from_now if options.key?(:expires_in)
Current.signed_global_id_expires_at || self.class.expires_in&.from_now
end
end
end
which succesfully generates the same signed ID on two subsequent calls.