sync_attr_with_auth0 0.1.7 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: cbd1d27afcb626e027d6b5d610d048e52611480e
4
- data.tar.gz: 1c0ba300b82dc2a2cb1a8da61ed0b16805967d96
2
+ SHA256:
3
+ metadata.gz: 0e0afb86d465d9c136f38d604c69f198a86a969b77301f6abf60da12aa98cf54
4
+ data.tar.gz: 237034211a5eaf258332933e8c10c3e2744b3033dd83f8f859dd578b42d06b63
5
5
  SHA512:
6
- metadata.gz: 2f8a355e4b26d652563dc2812108c13019ea5a18f1def848efdc749149e39877c3d0722780f11ae8449b2233629e130bf0fe9810943fc7a6f3c26e576e161f9c
7
- data.tar.gz: 0250be3d225041f815f7960f5fb59f25834799750b405168297bdecaea174611d8115ee5352c65d68eb58432f8a5c228585a83d3638d00c3d955259f03828b81
6
+ metadata.gz: 978bc082c1c60d5d13ba2a20a5f1d8faf5da73596e852c75d2d53aa6893a46fcfc1104029788ccc8b7320161597a3e352f365958b816b0f118bbde50e92e71d7
7
+ data.tar.gz: f87f7c4145859950ea7336adde22913c4ec1390893c57a097b77cf7147f2e18e068bf4fa3d3b4cd60f6d4e41feeae4183e3881fb471360fafce32aedab1d17ed
@@ -13,6 +13,7 @@ module SyncAttrWithAuth0
13
13
 
14
14
  module ClassMethods
15
15
 
16
+ # TODO: We should accept two arrays of fields: user_metadata (for user-managed settings) and app_metadata (for app-managed settings)
16
17
  def sync_attr_with_auth0(*fields)
17
18
  options = fields.extract_options!
18
19
 
@@ -33,9 +34,9 @@ module SyncAttrWithAuth0
33
34
 
34
35
  # Setup callbacks
35
36
  after_validation :validate_email_with_auth0
36
- after_create :save_to_auth0_on_create
37
- after_update :save_to_auth0_on_update
38
- after_commit :update_uid_from_auth0
37
+ after_create :save_to_auth0_after_create
38
+ after_update :save_to_auth0_after_update
39
+ after_commit :update_uid_and_picture_from_auth0
39
40
  end # sync_attr_with_auth0
40
41
 
41
42
  end # ClassMethods
@@ -52,18 +53,27 @@ module SyncAttrWithAuth0
52
53
  end # auth0_user_email
53
54
 
54
55
 
55
- def auth0_user_email_changed?
56
+ def auth0_user_saved_change_to_email?
56
57
  return false unless self.respond_to?(auth0_sync_configuration.email_attribute)
57
58
  # return false unless sync_email_with_auth0? # We don't care if it changed if we aren't syncing it.
58
59
 
59
- return self.send("#{auth0_sync_configuration.email_attribute}_changed?")
60
- end # auth0_email_changed?
60
+ if respond_to? :"saved_change_to_#{auth0_sync_configuration.email_attribute}?"
61
+ # Modern method
62
+ public_send :"saved_change_to_#{auth0_sync_configuration.email_attribute}?"
63
+ else
64
+ # Legacy method. Drop when no longer supporting <= Rails 5.1
65
+ public_send :"#{auth0_sync_configuration.email_attribute}_changed?"
66
+ end
67
+ end # auth0_user_saved_change_to_email?
61
68
 
62
69
 
63
70
  def auth0_user_uid
64
71
  self.send(auth0_sync_configuration.auth0_uid_attribute) if self.respond_to?(auth0_sync_configuration.auth0_uid_attribute)
65
72
  end # auth0_user_uid
66
73
 
74
+ def auth0_picture
75
+ public_send auth0_sync_configuration.picture_attribute if respond_to? auth0_sync_configuration.picture_attribute
76
+ end
67
77
 
68
78
  def auth0_user_name
69
79
  self.send(auth0_sync_configuration.name_attribute) if self.respond_to?(auth0_sync_configuration.name_attribute)
@@ -85,18 +95,21 @@ module SyncAttrWithAuth0
85
95
  end # auth0_user_password
86
96
 
87
97
 
88
- def auth0_user_password_changed?
98
+ def auth0_user_saved_change_to_password?
89
99
  return false unless self.respond_to?(auth0_sync_configuration.password_attribute)
90
- # return false unless sync_password_with_auth0? # We don't care if it changed if we aren't syncing it.
91
100
 
92
- if self.respond_to?(:"#{auth0_sync_configuration.password_attribute.to_s}_changed?")
93
- # We have a changed method, use it
94
- return self.send(:"#{auth0_sync_configuration.password_attribute.to_s}_changed?")
95
- else
96
- # We don't have a changed method, check if the attribute was set.
97
- return !self.send(auth0_sync_configuration.password_attribute).nil?
101
+ case
102
+ when respond_to?(:"saved_change_to_#{auth0_sync_configuration.password_attribute}?")
103
+ # Prefer modern method
104
+ public_send :"saved_change_to_#{auth0_sync_configuration.password_attribute}?"
105
+ when respond_to?(:"#{auth0_sync_configuration.password_attribute}_changed?")
106
+ # Legacy method. Drop when no longer supporting <= Rails 5.1
107
+ public_send :"#{auth0_sync_configuration.password_attribute}_changed?"
108
+ else
109
+ # Neither exists so must be in-memory accessor. Just check if set.
110
+ public_send(auth0_sync_configuration.password_attribute).present?
98
111
  end
99
- end # auth0_user_password_changed?
112
+ end # auth0_user_saved_change_to_password?
100
113
 
101
114
 
102
115
  def auth0_default_password
@@ -23,40 +23,50 @@ module SyncAttrWithAuth0
23
23
  end # sync_with_auth0_on_update?
24
24
 
25
25
 
26
- def save_to_auth0_on_create
26
+ def save_to_auth0_after_create
27
27
  return true unless sync_with_auth0_on_create?
28
28
 
29
29
  save_to_auth0
30
30
 
31
31
  true # don't abort the callback chain
32
- end # save_to_auth0_on_create
32
+ end # save_to_auth0_after_create
33
33
 
34
34
 
35
- def save_to_auth0_on_update
35
+ def save_to_auth0_after_update
36
36
  return true unless sync_with_auth0_on_update?
37
- return true unless auth0_dirty?
37
+ return true unless auth0_saved_change_dirty?
38
38
 
39
39
  save_to_auth0
40
40
 
41
41
  true # don't abort the callback chain
42
- end # save_to_auth0_on_update
42
+ end # save_to_auth0_after_update
43
43
 
44
44
 
45
- def auth0_dirty?
46
- is_dirty = !!(
47
- auth0_attributes_to_sync.inject(false) do |memo, attrib|
48
- memo || self.try("#{attrib}_changed?")
45
+ def auth0_saved_change_dirty?
46
+ is_dirty = auth0_attributes_to_sync.any? do |attrib|
47
+ if respond_to? :"saved_change_to_#{attrib}?"
48
+ # Prefer modern method
49
+ public_send :"saved_change_to_#{attrib}?"
50
+ elsif respond_to? :"#{attrib}_changed?"
51
+ # Legacy method. Drop when no longer supporting <= Rails 5.1
52
+ public_send :"#{attrib}_changed?"
53
+ else
54
+ # Specs currently verify attributes specified as needing synced
55
+ # that are not defined not cause an error. I'm not sure why we
56
+ # need this. Seems like a misconfiguration and we should blow
57
+ # up. But to limit scope of change keeping with defined behavior.
58
+ false
49
59
  end
50
- )
60
+ end
51
61
 
52
62
  # If the password was changed, force is_dirty to be true
53
- is_dirty = true if auth0_user_password_changed?
63
+ is_dirty = true if auth0_user_saved_change_to_password?
54
64
 
55
65
  # If the email was changed, force is_dirty to be true
56
- is_dirty = true if auth0_user_email_changed?
66
+ is_dirty = true if auth0_user_saved_change_to_email?
57
67
 
58
68
  return is_dirty
59
- end # auth0_dirty?
69
+ end # auth0_saved_change_dirty?
60
70
 
61
71
 
62
72
  def save_to_auth0
@@ -86,8 +96,9 @@ module SyncAttrWithAuth0
86
96
 
87
97
  response = SyncAttrWithAuth0::Auth0.create_user(auth0_user_name, params, config: auth0_sync_configuration)
88
98
 
89
- # Update the record with the uid after_commit
99
+ # Update the record with the uid and picture after_commit
90
100
  @auth0_uid = response['user_id']
101
+ @auth0_picture = response['picture']
91
102
  end # create_in_auth0
92
103
 
93
104
 
@@ -97,10 +108,11 @@ module SyncAttrWithAuth0
97
108
  params = auth0_update_params
98
109
 
99
110
  begin
100
- SyncAttrWithAuth0::Auth0.patch_user(user_uid, params, config: auth0_sync_configuration)
111
+ response = SyncAttrWithAuth0::Auth0.patch_user(user_uid, params, config: auth0_sync_configuration)
101
112
 
102
113
  # Update the record with the uid after_commit (in case it doesn't match what's on file).
103
114
  @auth0_uid = user_uid
115
+ @auth0_picture = response['picture']
104
116
  rescue ::Auth0::NotFound => e
105
117
  # For whatever reason, the passed in uid was invalid,
106
118
  # determine how to proceed.
@@ -113,10 +125,11 @@ module SyncAttrWithAuth0
113
125
  else
114
126
  # The uid was incorrect, so re-attempt with the new uid
115
127
  # and update the one on file.
116
- SyncAttrWithAuth0::Auth0.patch_user(found_user['user_id'], params, config: auth0_sync_configuration)
128
+ response = SyncAttrWithAuth0::Auth0.patch_user(found_user['user_id'], params, config: auth0_sync_configuration)
117
129
 
118
130
  # Update the record with the uid after_commit
119
131
  @auth0_uid = found_user['user_id']
132
+ @auth0_picture = response['picture']
120
133
  end
121
134
 
122
135
  rescue Exception => e
@@ -146,6 +159,10 @@ module SyncAttrWithAuth0
146
159
  'password' => password,
147
160
  'connection' => auth0_sync_configuration.connection_name,
148
161
  'email_verified' => email_verified,
162
+ 'name' => auth0_user_name,
163
+ 'nickname' => auth0_user_name,
164
+ 'given_name' => auth0_user_given_name,
165
+ 'family_name' => auth0_user_family_name,
149
166
  'user_metadata' => user_metadata,
150
167
  'app_metadata' => app_metadata
151
168
  }
@@ -159,40 +176,50 @@ module SyncAttrWithAuth0
159
176
  app_metadata = auth0_app_metadata
160
177
 
161
178
  params = {
179
+ 'name' => auth0_user_name,
180
+ 'nickname' => auth0_user_name,
181
+ 'given_name' => auth0_user_given_name,
182
+ 'family_name' => auth0_user_family_name,
162
183
  'app_metadata' => app_metadata,
163
184
  'user_metadata' => user_metadata
164
185
  }
165
186
 
166
- if auth0_user_password_changed?
187
+ if auth0_user_saved_change_to_password?
167
188
  # The password needs to be updated.
168
189
  params['password'] = auth0_user_password
169
190
  params['verify_password'] = auth0_verify_password?
170
191
  end
171
192
 
172
- if auth0_user_email_changed?
193
+ if auth0_user_saved_change_to_email?
173
194
  # The email needs to be updated.
174
195
  params['email'] = auth0_user_email
175
- params['verify_email'] = auth0_email_verified?
196
+ params['verify_email'] = !auth0_email_verified?
176
197
  end
177
198
 
178
199
  return params
179
200
  end # auth0_update_params
180
201
 
181
202
 
182
- def update_uid_from_auth0
183
- if @auth0_uid
184
- self.sync_with_auth0_on_update = false if self.respond_to?(:sync_with_auth0_on_update=)
185
- self.send("#{auth0_sync_configuration.auth0_uid_attribute}=", @auth0_uid)
203
+ def update_uid_and_picture_from_auth0
204
+ data = {}
186
205
 
187
- # Nil the instance variable to prevent an infinite loop
188
- @auth0_uid = nil
206
+ if @auth0_uid
207
+ attr = auth0_sync_configuration.auth0_uid_attribute
208
+ data[attr] = @auth0_uid if respond_to?(attr) && @auth0_uid != public_send(attr)
209
+ end
189
210
 
190
- # Save!
191
- self.save
211
+ if @auth0_picture
212
+ attr = auth0_sync_configuration.picture_attribute
213
+ data[attr] = @auth0_picture if respond_to?(attr) && @auth0_picture != public_send(attr)
192
214
  end
193
215
 
216
+ update_columns data unless data.empty?
217
+
218
+ remove_instance_variable :@auth0_uid if defined? @auth0_uid
219
+ remove_instance_variable :@auth0_picture if defined? @auth0_picture
220
+
194
221
  true # don't abort the callback chain
195
- end # update_uid_from_auth0
222
+ end # update_uid_and_picture_from_auth0
196
223
 
197
224
  end
198
225
  end
@@ -14,7 +14,7 @@ module SyncAttrWithAuth0
14
14
  }
15
15
  },
16
16
  'iat' => Time.now.to_i,
17
- 'jti' => UUIDTools::UUID.timestamp_create.to_s
17
+ 'jti' => UUIDTools::UUID.random_create.to_s
18
18
  }
19
19
 
20
20
  jwt = JWT.encode(payload, JWT.base64url_decode(global_client_secret))
@@ -68,7 +68,15 @@ module SyncAttrWithAuth0
68
68
  auth0 = SyncAttrWithAuth0::Auth0.create_auth0_client(config: config)
69
69
 
70
70
  # Use the Lucene search because Find by Email is case sensitive
71
- results = auth0.get('/api/v2/users', q: "email:#{email}")
71
+ query = "email:#{email}"
72
+ unless config.search_connections.empty?
73
+ conn_query = config.search_connections
74
+ .collect { |conn| %Q{identities.connection:"#{conn}"} }
75
+ .join ' OR '
76
+ query = "#{query} AND (#{conn_query})"
77
+ end
78
+
79
+ results = auth0.get('/api/v2/users', q: query, search_engine: 'v3')
72
80
 
73
81
  if exclude_user_id
74
82
  results = results.reject { |r| r['user_id'] == exclude_user_id }
@@ -31,8 +31,8 @@ module SyncAttrWithAuth0
31
31
  :auth0_client_id, :auth0_client_secret, :auth0_namespace,
32
32
  :auth0_uid_attribute, :name_attribute, :given_name_attribute,
33
33
  :family_name_attribute, :email_attribute, :password_attribute,
34
- :email_verified_attribute, :verify_password_attribute,
35
- :connection_name
34
+ :email_verified_attribute, :verify_password_attribute, :picture_attribute,
35
+ :connection_name, :search_connections
36
36
 
37
37
 
38
38
  def initialize
@@ -50,7 +50,9 @@ module SyncAttrWithAuth0
50
50
  @password_attribute = :password
51
51
  @email_verified_attribute = :email_verified
52
52
  @verify_password_attribute = :verify_password
53
+ @picture_attribute = :picture
53
54
  @connection_name = 'Username-Password-Authentication'
55
+ @search_connections = []
54
56
  end
55
57
  end
56
58
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sync_attr_with_auth0
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Patrick McGraw
@@ -29,16 +29,16 @@ dependencies:
29
29
  name: json
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
- - - "~>"
32
+ - - ">="
33
33
  - !ruby/object:Gem::Version
34
- version: 1.8.1
34
+ version: '0'
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
- - - "~>"
39
+ - - ">="
40
40
  - !ruby/object:Gem::Version
41
- version: 1.8.1
41
+ version: '0'
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: activerecord
44
44
  requirement: !ruby/object:Gem::Requirement
@@ -99,14 +99,14 @@ dependencies:
99
99
  name: jwt
100
100
  requirement: !ruby/object:Gem::Requirement
101
101
  requirements:
102
- - - '='
102
+ - - "~>"
103
103
  - !ruby/object:Gem::Version
104
104
  version: 1.5.0
105
105
  type: :runtime
106
106
  prerelease: false
107
107
  version_requirements: !ruby/object:Gem::Requirement
108
108
  requirements:
109
- - - '='
109
+ - - "~>"
110
110
  - !ruby/object:Gem::Version
111
111
  version: 1.5.0
112
112
  - !ruby/object:Gem::Dependency
@@ -169,8 +169,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
169
169
  - !ruby/object:Gem::Version
170
170
  version: '0'
171
171
  requirements: []
172
- rubyforge_project:
173
- rubygems_version: 2.6.13
172
+ rubygems_version: 3.1.2
174
173
  signing_key:
175
174
  specification_version: 4
176
175
  summary: Synchronize attributes on a local ActiveRecord user model with the user metadata