globalid 0.3.6 → 0.3.7

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of globalid might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 14fc719e31ef97f014044c96e42be88e4b563a63
4
- data.tar.gz: ab0206d64fb1aa095311f86e4be0636d447c28d7
3
+ metadata.gz: 16fab50b5f1ed999f159d4e28507577d1e240e2a
4
+ data.tar.gz: 00c55d5c1b1b3b09178e3c1e75dc343389acb92f
5
5
  SHA512:
6
- metadata.gz: fcfdb39821eb767d1b1f8d86b60813ab4c6a85f71956e294852f279252b7cb5952c5776cceaa23d578f7163ce7431e97fbc18b272254eb15a5cfd2679efc625d
7
- data.tar.gz: 2d7ac23c3a6eaf8036d2f42b12299b037438be020316622318f69c9a0df580dc87511610c55b316ba3fd0848e9f479912654979939077fb9f5aa28c712467b0d
6
+ metadata.gz: ee2a00103d0a6890701acd2674a7817335391f54e67d44746c1883711329e5707d3c26089f5fe9823322fe044d52e9b7167ae8f0b7d86af1c88ff379d269f6e1
7
+ data.tar.gz: 5da58eabadc4ddc3af4231520db1c3b09bc780ac8b842e4a93f70a6ab1523a81c7112d5377569b2643b755e4c06cb9e764b75e9b1078fa41b48f909f02ed25d3
@@ -1,4 +1,4 @@
1
- Copyright (c) 2014 David Heinemeier Hansson
1
+ Copyright (c) 2014-2016 David Heinemeier Hansson
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -0,0 +1,130 @@
1
+ # Global ID - Reference models by URI
2
+
3
+ A Global ID is an app wide URI that uniquely identifies a model instance:
4
+
5
+ gid://YourApp/Some::Model/id
6
+
7
+ This is helpful when you need a single identifier to reference different
8
+ classes of objects.
9
+
10
+ One example is job scheduling. We need to reference a model object rather than
11
+ serialize the object itself. We can pass a Global ID that can be used to locate
12
+ the model when it's time to perform the job. The job scheduler doesn't need to know
13
+ the details of model naming and IDs, just that it has a global identifier that
14
+ references a model.
15
+
16
+ Another example is a drop-down list of options, consisting of both Users and Groups.
17
+ Normally we'd need to come up with our own ad hoc scheme to reference them. With Global
18
+ IDs, we have a universal identifier that works for objects of both classes.
19
+
20
+
21
+ ## Usage
22
+
23
+ Mix `GlobalID::Identification` into any model with a `#find(id)` class method.
24
+ Support is automatically included in Active Record.
25
+
26
+ ```ruby
27
+ >> person_gid = Person.find(1).to_global_id
28
+ => #<GlobalID ...
29
+
30
+ >> person_gid.uri
31
+ => #<URI ...
32
+
33
+ >> person_gid.to_s
34
+ => "gid://app/Person/1"
35
+
36
+ >> GlobalID::Locator.locate person_gid
37
+ => #<Person:0x007fae94bf6298 @id="1">
38
+ ```
39
+
40
+ ### Signed Global IDs
41
+
42
+ For added security GlobalIDs can also be signed to ensure that the data hasn't been tampered with.
43
+
44
+ ```ruby
45
+ >> person_sgid = Person.find(1).to_signed_global_id
46
+ => #<SignedGlobalID:0x007fea1944b410
47
+
48
+ >> person_sgid = Person.find(1).to_sgid
49
+ => #<SignedGlobalID:0x007fea1944b410
50
+
51
+ >> person_sgid.to_s
52
+ => "BAhJIh5naWQ6Ly9pZGluYWlkaS9Vc2VyLzM5NTk5BjoGRVQ=--81d7358dd5ee2ca33189bb404592df5e8d11420e"
53
+
54
+ >> GlobalID::Locator.locate_signed person_sgid
55
+ => #<Person:0x007fae94bf6298 @id="1">
56
+
57
+ ```
58
+ You can even bump the security up some more by explaining what purpose a Signed Global ID is for.
59
+ In this way evildoers can't reuse a sign-up form's SGID on the login page. For example.
60
+
61
+ ```ruby
62
+ >> signup_person_sgid = Person.find(1).to_sgid(for: 'signup_form')
63
+ => #<SignedGlobalID:0x007fea1984b520
64
+
65
+ >> GlobalID::Locator.locate_signed(signup_person_sgid.to_s, for: 'signup_form')
66
+ => #<Person:0x007fae94bf6298 @id="1">
67
+ ```
68
+
69
+ You can also have SGIDs that expire some time in the future. This is useful if there's a resource,
70
+ people shouldn't have indefinite access to, like a share link.
71
+
72
+ ```ruby
73
+ >> expiring_sgid = Document.find(5).to_sgid(expires_in: 2.hours, for: 'sharing')
74
+ => #<SignedGlobalID:0x008fde45df8937
75
+
76
+ # Within 2 hours...
77
+ >> GlobalID::Locator.locate_signed(expiring_sgid.to_s, for: 'sharing')
78
+ => #<Document:0x007fae94bf6298 @id="5">
79
+
80
+ # More than 2 hours later...
81
+ >> GlobalID::Locator.locate_signed(expiring_sgid.to_s, for: 'sharing')
82
+ => nil
83
+
84
+ >> explicit_expiring_sgid = SecretAgentMessage.find(5).to_sgid(expires_at: Time.now.advance(hours: 1))
85
+ => #<SignedGlobalID:0x008fde45df8937
86
+
87
+ # 1 hour later...
88
+ >> GlobalID::Locator.locate_signed explicit_expiring_sgid.to_s
89
+ => nil
90
+ ```
91
+
92
+ ### Custom App Locator
93
+
94
+ A custom locator can be set for an app by calling `GlobalID::Locator.use` and providing an app locator to use for that app.
95
+ A custom app locator is useful when different apps collaborate and reference each others' Global IDs.
96
+ When finding a Global ID's model, the locator to use is based on the app name provided in the Global ID url.
97
+
98
+ A custom locator can either be a block or a class.
99
+
100
+ Using a block:
101
+
102
+ ```ruby
103
+ GlobalID::Locator.use :foo do |gid|
104
+ FooRemote.const_get(gid.model_name).find(gid.model_id)
105
+ end
106
+ ```
107
+
108
+ Using a class:
109
+
110
+ ```ruby
111
+ GlobalID::Locator.use :bar, BarLocator.new
112
+ class BarLocator
113
+ def locate(gid)
114
+ @search_client.search name: gid.model_name, id: gid.model_id
115
+ end
116
+ end
117
+ ```
118
+
119
+ After defining locators as above, URIs like "gid://foo/Person/1" and "gid://bar/Person/1" will now use the foo block locator and `BarLocator` respectively.
120
+ Other apps will still keep using the default locator.
121
+
122
+ ## Contributing to GlobalID
123
+
124
+ GlobalID is work of many contributors. You're encouraged to submit pull requests, propose
125
+ features and discuss issues.
126
+
127
+ See [CONTRIBUTING](CONTRIBUTING.md).
128
+
129
+ ## License
130
+ GlobalID is released under the [MIT License](http://www.opensource.org/licenses/MIT).
@@ -106,9 +106,7 @@ class GlobalID
106
106
 
107
107
  private
108
108
  def locator_for(gid)
109
- @locators.fetch(normalize_app(gid.app)) do
110
- gid.model_class.respond_to?(:unscoped) ? UNSCOPED_LOCATOR : DEFAULT_LOCATOR
111
- end
109
+ @locators.fetch(normalize_app(gid.app)) { DEFAULT_LOCATOR }
112
110
  end
113
111
 
114
112
  def find_allowed?(model_class, only = nil)
@@ -127,7 +125,7 @@ class GlobalID
127
125
  private
128
126
  @locators = {}
129
127
 
130
- class DefaultLocator
128
+ class BaseLocator
131
129
  def locate(gid)
132
130
  gid.model_class.find gid.model_id
133
131
  end
@@ -151,19 +149,26 @@ class GlobalID
151
149
  end
152
150
  end
153
151
  end
154
- DEFAULT_LOCATOR = DefaultLocator.new
155
152
 
156
- class UnscopedLocator < DefaultLocator
153
+ class UnscopedLocator < BaseLocator
157
154
  def locate(gid)
158
- gid.model_class.unscoped { super }
155
+ unscoped(gid.model_class) { super }
159
156
  end
160
157
 
161
158
  private
162
159
  def find_records(model_class, ids, options)
163
- model_class.unscoped { super }
160
+ unscoped(model_class) { super }
161
+ end
162
+
163
+ def unscoped(model_class)
164
+ if model_class.respond_to?(:unscoped)
165
+ model_class.unscoped { yield }
166
+ else
167
+ yield
168
+ end
164
169
  end
165
170
  end
166
- UNSCOPED_LOCATOR = UnscopedLocator.new
171
+ DEFAULT_LOCATOR = UnscopedLocator.new
167
172
 
168
173
  class BlockLocator
169
174
  def initialize(block)
@@ -9,11 +9,7 @@ class SignedGlobalID < GlobalID
9
9
  attr_accessor :verifier
10
10
 
11
11
  def parse(sgid, options = {})
12
- if sgid.is_a? self
13
- sgid
14
- else
15
- super verify(sgid, options), options
16
- end
12
+ super verify(sgid.to_s, options), options
17
13
  end
18
14
 
19
15
  # Grab the verifier from options and fall back to SignedGlobalID.verifier.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: globalid
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.6
4
+ version: 0.3.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-04 00:00:00.000000000 Z
11
+ date: 2016-07-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -45,6 +45,7 @@ extensions: []
45
45
  extra_rdoc_files: []
46
46
  files:
47
47
  - MIT-LICENSE
48
+ - README.md
48
49
  - lib/global_id.rb
49
50
  - lib/global_id/global_id.rb
50
51
  - lib/global_id/identification.rb
@@ -73,9 +74,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
73
74
  version: '0'
74
75
  requirements: []
75
76
  rubyforge_project:
76
- rubygems_version: 2.4.7
77
+ rubygems_version: 2.4.5.1
77
78
  signing_key:
78
79
  specification_version: 4
79
80
  summary: 'Refer to any model with a URI: gid://app/class/id'
80
81
  test_files: []
81
- has_rdoc: