1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
|
class GlobalID
# Mix `GlobalID::Identification` into any model with a `#find(id)` class
# method. Support is automatically included in Active Record.
#
# class Person
# include ActiveModel::Model
# include GlobalID::Identification
#
# attr_accessor :id
#
# def self.find(id)
# new id: id
# end
#
# def ==(other)
# id == other.try(:id)
# end
# end
#
# person_gid = Person.find(1).to_global_id
# # => #<GlobalID ...
# person_gid.uri
# # => #<URI ...
# person_gid.to_s
# # => "gid://app/Person/1"
# GlobalID::Locator.locate person_gid
# # => #<Person:0x007fae94bf6298 @id="1">
module Identification
# Returns the Global ID of the model.
#
# model = Person.new id: 1
# global_id = model.to_global_id
# global_id.model_class # => Person
# global_id.model_id # => "1"
# global_id.to_param # => "Z2lkOi8vYm9yZGZvbGlvL1BlcnNvbi8x"
def to_global_id(options = {})
GlobalID.create(self, options)
end
alias to_gid to_global_id
# Returns the Global ID parameter of the model.
#
# model = Person.new id: 1
# model.to_gid_param # => ""Z2lkOi8vYm9yZGZvbGlvL1BlcnNvbi8x"
def to_gid_param(options = {})
to_global_id(options).to_param
end
# Returns the Signed Global ID of the model.
# Signed Global IDs ensure that the data hasn't been tampered with.
#
# model = Person.new id: 1
# signed_global_id = model.to_signed_global_id
# signed_global_id.model_class # => Person
# signed_global_id.model_id # => "1"
# signed_global_id.to_param # => "BAh7CEkiCGdpZAY6BkVUSSIiZ2..."
#
# ==== Expiration
#
# Signed Global IDs can expire some time in the future. This is useful if
# there's a resource people shouldn't have indefinite access to, like a
# share link.
#
# expiring_sgid = Document.find(5).to_sgid(expires_in: 2.hours, for: 'sharing')
# # => #<SignedGlobalID:0x008fde45df8937 ...>
# # Within 2 hours...
# GlobalID::Locator.locate_signed(expiring_sgid.to_s, for: 'sharing')
# # => #<Document:0x007fae94bf6298 @id="5">
# # More than 2 hours later...
# GlobalID::Locator.locate_signed(expiring_sgid.to_s, for: 'sharing')
# # => nil
#
# In Rails, an auto-expiry of 1 month is set by default.
#
# You need to explicitly pass `expires_in: nil` to generate a permanent
# SGID that will not expire,
#
# never_expiring_sgid = Document.find(5).to_sgid(expires_in: nil)
# # => #<SignedGlobalID:0x008fde45df8937 ...>
#
# # Any time later...
# GlobalID::Locator.locate_signed never_expiring_sgid
# # => #<Document:0x007fae94bf6298 @id="5">
#
# It's also possible to pass a specific expiry time
#
# explicit_expiring_sgid = SecretAgentMessage.find(5).to_sgid(expires_at: Time.now.advance(hours: 1))
# # => #<SignedGlobalID:0x008fde45df8937 ...>
#
# # 1 hour later...
# GlobalID::Locator.locate_signed explicit_expiring_sgid.to_s
# # => nil
#
# Note that an explicit `:expires_at` takes precedence over a relative `:expires_in`.
#
# ==== Purpose
#
# You can even bump the security up some more by explaining what purpose a
# Signed Global ID is for. In this way evildoers can't reuse a sign-up
# form's SGID on the login page. For example.
#
# signup_person_sgid = Person.find(1).to_sgid(for: 'signup_form')
# # => #<SignedGlobalID:0x007fea1984b520
# GlobalID::Locator.locate_signed(signup_person_sgid.to_s, for: 'signup_form')
# => #<Person:0x007fae94bf6298 @id="1">
def to_signed_global_id(options = {})
SignedGlobalID.create(self, options)
end
alias to_sgid to_signed_global_id
# Returns the Signed Global ID parameter.
#
# model = Person.new id: 1
# model.to_sgid_param # => "BAh7CEkiCGdpZAY6BkVUSSIiZ2..."
def to_sgid_param(options = {})
to_signed_global_id(options).to_param
end
end
end
|