lifen 1.5.1 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -1
- data/Gemfile.lock +2 -2
- data/README.md +24 -0
- data/lib/lifen/token.rb +2 -2
- data/lib/lifen/user.rb +22 -3
- data/lib/lifen/version.rb +1 -1
- data/spec/token_spec.rb +1 -1
- data/spec/users_spec.rb +59 -0
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6f1aef95bf44e742592d04b253e4b19f6bdb9eb7
|
|
4
|
+
data.tar.gz: 9ff4e2c43626c1bc379e31de7b65dd97e125aaeb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b3cc34906d28323e88bbf86c336cd278a04ee9565e01631c08fc038f68c57066b4427ba41a6aba0f1c35ca1a462a2f1d47fe1ff613eed02cfdf4760290f2c106
|
|
7
|
+
data.tar.gz: 694710ae26fc1cc8f59a974c883da5cee4a80e6a0d2cb892f665271a657d187a7592d2a3654ee4acde76c237d70722673bbafcc0e6e54431757bf65e18b25b02
|
data/CHANGELOG.md
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
1.5.2
|
|
2
|
+
-----
|
|
3
|
+
|
|
4
|
+
- Threadsafe strategy for the user creation to include the persistence strategy
|
|
5
|
+
|
|
1
6
|
1.5.1
|
|
2
7
|
-----
|
|
3
8
|
|
|
4
|
-
- Threadsafe strategy
|
|
9
|
+
- Threadsafe strategy for the token refresh to include the persistence strategy
|
|
5
10
|
|
|
6
11
|
1.5.0
|
|
7
12
|
-----
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -54,6 +54,30 @@ other_user.save
|
|
|
54
54
|
other_user.reload
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
+
### Creating a user in a threadsafe way
|
|
58
|
+
|
|
59
|
+
Assuming the lifen `uuid` is stored on the `User` model as `lifen_uuid`, you can simply change the `create` method to became threadsafe:
|
|
60
|
+
|
|
61
|
+
```ruby
|
|
62
|
+
lifen_user.create(
|
|
63
|
+
persisted_lifen_uuid: ->(internal_user) {
|
|
64
|
+
user.reload
|
|
65
|
+
|
|
66
|
+
current_uuid = user.lifen_uuid
|
|
67
|
+
|
|
68
|
+
if current_uuid.blank?
|
|
69
|
+
nil
|
|
70
|
+
else
|
|
71
|
+
current_uuid
|
|
72
|
+
end
|
|
73
|
+
},
|
|
74
|
+
save_to_db: ->(lifen_user) {
|
|
75
|
+
user.lifen_uuid = lifen_user.uuid
|
|
76
|
+
user.save!
|
|
77
|
+
}
|
|
78
|
+
)
|
|
79
|
+
```
|
|
80
|
+
|
|
57
81
|
### Managing users' settings
|
|
58
82
|
|
|
59
83
|
```ruby
|
data/lib/lifen/token.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Lifen
|
|
2
2
|
class Token
|
|
3
3
|
|
|
4
|
-
@@
|
|
4
|
+
@@refresh_lock = Mutex.new
|
|
5
5
|
|
|
6
6
|
include Virtus.model(finalize: false)
|
|
7
7
|
|
|
@@ -45,7 +45,7 @@ module Lifen
|
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
def refresh_once_if_needed
|
|
48
|
-
@@
|
|
48
|
+
@@refresh_lock.synchronize do
|
|
49
49
|
|
|
50
50
|
load_from_db.call(self) if load_from_db.is_a? Proc
|
|
51
51
|
|
data/lib/lifen/user.rb
CHANGED
|
@@ -12,16 +12,35 @@ module Lifen
|
|
|
12
12
|
attribute :first_name, String
|
|
13
13
|
attribute :profile_picture_url, String
|
|
14
14
|
|
|
15
|
+
@@create_lock = Mutex.new
|
|
16
|
+
|
|
15
17
|
def flows
|
|
16
18
|
Lifen::Flows.new(user: self).all
|
|
17
19
|
end
|
|
18
20
|
|
|
19
|
-
def create
|
|
21
|
+
def create(persisted_lifen_uuid: ->(user) {}, save_to_db: ->(user) {})
|
|
22
|
+
|
|
20
23
|
params = {emailAddress: email, lastName: last_name, firstName: first_name, profilePicUrl: profile_picture_url}
|
|
21
24
|
|
|
22
|
-
|
|
25
|
+
@@create_lock.synchronize do
|
|
26
|
+
|
|
27
|
+
exisiting_uuid = persisted_lifen_uuid.call(self)
|
|
28
|
+
|
|
29
|
+
if exisiting_uuid.nil?
|
|
30
|
+
|
|
31
|
+
json = application_client.post("authentication/api/register/third_party", params)
|
|
32
|
+
|
|
33
|
+
self.uuid = json["accountUuid"]
|
|
34
|
+
|
|
35
|
+
else
|
|
36
|
+
|
|
37
|
+
self.uuid = exisiting_uuid
|
|
38
|
+
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
save_to_db.call(self)
|
|
42
|
+
end
|
|
23
43
|
|
|
24
|
-
self.uuid = json["accountUuid"]
|
|
25
44
|
end
|
|
26
45
|
|
|
27
46
|
def self.find(uuid)
|
data/lib/lifen/version.rb
CHANGED
data/spec/token_spec.rb
CHANGED
|
@@ -94,7 +94,7 @@ describe Lifen::Token do
|
|
|
94
94
|
token.expires_at = persisted_user.token_expires_at
|
|
95
95
|
},
|
|
96
96
|
save_to_db: ->(token) {
|
|
97
|
-
#
|
|
97
|
+
# Saving data to DB
|
|
98
98
|
|
|
99
99
|
persisted_user.token_value = token.value
|
|
100
100
|
persisted_user.token_expires_at = token.expires_at
|
data/spec/users_spec.rb
CHANGED
|
@@ -64,6 +64,65 @@ describe Lifen::User do
|
|
|
64
64
|
|
|
65
65
|
expect(user.uuid).to_not be_nil
|
|
66
66
|
end
|
|
67
|
+
|
|
68
|
+
describe 'thread safe' do
|
|
69
|
+
|
|
70
|
+
class PersistedUser < Struct.new(:lifen_uuid) ; end
|
|
71
|
+
|
|
72
|
+
let(:storage) { double("Storage") }
|
|
73
|
+
|
|
74
|
+
let(:marc) { Lifen::User.new(email: "existing-user@domain.tld", first_name: "Existing", last_name: "User") }
|
|
75
|
+
let(:antoine) { Lifen::User.new(email: "existing-user@domain.tld", first_name: "Existing", last_name: "Marc") }
|
|
76
|
+
|
|
77
|
+
before do
|
|
78
|
+
allow(storage).to receive(:find_by) do
|
|
79
|
+
PersistedUser.new(nil)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it 'queues refresh calls' do
|
|
84
|
+
|
|
85
|
+
threads = []
|
|
86
|
+
|
|
87
|
+
threads << Thread.new do
|
|
88
|
+
VCR.use_cassette "users/create/valid_attributes" do
|
|
89
|
+
marc.create(
|
|
90
|
+
persisted_lifen_uuid: ->(user) {
|
|
91
|
+
# Loading data from DB
|
|
92
|
+
storage.find_by(email: user.email).lifen_uuid
|
|
93
|
+
},
|
|
94
|
+
save_to_db: ->(user) {
|
|
95
|
+
# saving data to DB
|
|
96
|
+
|
|
97
|
+
allow(storage).to receive(:find_by) do
|
|
98
|
+
PersistedUser.new(user.uuid)
|
|
99
|
+
end
|
|
100
|
+
}
|
|
101
|
+
)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
sleep 0.1 # Making sure the mocked call is received first
|
|
106
|
+
|
|
107
|
+
threads << Thread.new do
|
|
108
|
+
|
|
109
|
+
# No cassette, should raise an issue if HTTP call is needed
|
|
110
|
+
antoine.create(
|
|
111
|
+
persisted_lifen_uuid: ->(user) {
|
|
112
|
+
# Loading data from DB
|
|
113
|
+
|
|
114
|
+
storage.find_by(email: user.email).lifen_uuid
|
|
115
|
+
}
|
|
116
|
+
)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
threads.map { |t| t.join } # waiting for all threads to finish
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
67
126
|
end
|
|
68
127
|
|
|
69
128
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lifen
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.5.
|
|
4
|
+
version: 1.5.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Etienne Depaulis
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2017-01-
|
|
11
|
+
date: 2017-01-19 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -222,7 +222,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
222
222
|
version: '0'
|
|
223
223
|
requirements: []
|
|
224
224
|
rubyforge_project:
|
|
225
|
-
rubygems_version: 2.
|
|
225
|
+
rubygems_version: 2.6.8
|
|
226
226
|
signing_key:
|
|
227
227
|
specification_version: 4
|
|
228
228
|
summary: Lifen JSON API ruby client
|