File: identification.rb

package info (click to toggle)
ruby-globalid 1.3.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 316 kB
  • sloc: ruby: 1,695; makefile: 6
file content (120 lines) | stat: -rw-r--r-- 4,105 bytes parent folder | download
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