volcano-sdk 0.5.3 → 0.7.0
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/README.md +20 -6
- data/lib/volcano/auth.rb +12 -4
- data/lib/volcano/auth_anonymous.rb +1 -4
- data/lib/volcano/auth_email_change.rb +1 -4
- data/lib/volcano/auth_get_user.rb +9 -4
- data/lib/volcano/auth_state.rb +13 -15
- data/lib/volcano/auth_update_user.rb +1 -4
- data/lib/volcano/client.rb +4 -0
- data/lib/volcano/models.rb +0 -1
- data/lib/volcano/session.rb +26 -0
- data/lib/volcano/version.rb +1 -1
- data/lib/volcano.rb +1 -0
- metadata +16 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a36dee9d50b8138335752de5e3fdb5007ecd5dfa66547150190de691a048052d
|
|
4
|
+
data.tar.gz: 97edb400526abafd980ec19278304f80cff3ead5010d7704da7b55128390879e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5c3e7ed134b563780e8c1d64ba26f30f7ae9563d7c2ac219a265dabbf6aa04544600ef1a963abd09f9aa3f4efc2a6e32da0adeaf9a2a45905bd793daffd4101d
|
|
7
|
+
data.tar.gz: c2abfe5361e2ccff60f6f76a77aa4e2eedc0a033d1ef7649a63c5a6fa8f1edf0996c8141cc5eede6c08e5848e24fa8159e5a550b12edc5a32d16ea6dbf4311aa
|
data/README.md
CHANGED
|
@@ -69,6 +69,20 @@ raise "session changed" unless current_session == session
|
|
|
69
69
|
`current_session` reads immutable local state. It does not refresh or validate
|
|
70
70
|
the token.
|
|
71
71
|
|
|
72
|
+
Sessions returned by authentication retain the user payload in `session.user`,
|
|
73
|
+
including metadata. The snapshot is deeply immutable and available without a
|
|
74
|
+
request. It is cached data, not proof of authentication; use `auth.user` to fetch
|
|
75
|
+
the server-validated profile. Existing three-field `Session` construction still
|
|
76
|
+
works, with `user: nil`. An adopted snapshot must have the same user ID.
|
|
77
|
+
Snapshots contain deeply frozen JSON data. Plain `Time` timestamps become UTC
|
|
78
|
+
ISO8601 strings with nanosecond precision; symbols become strings. Custom objects,
|
|
79
|
+
container/string/time subclasses, non-finite numbers, duplicate JSON keys, and
|
|
80
|
+
structures deeper than 100 levels raise `TypeError`. Use the typed `auth.user`
|
|
81
|
+
profile when you need Ruby `Time` values. Successful `user`, `update_user`,
|
|
82
|
+
`convert_anonymous`, and `confirm_email_change` calls update this snapshot
|
|
83
|
+
without changing credentials or emitting an authentication-state event.
|
|
84
|
+
Previously returned sessions remain unchanged.
|
|
85
|
+
|
|
72
86
|
### Get the current user
|
|
73
87
|
|
|
74
88
|
```ruby
|
|
@@ -78,8 +92,8 @@ raise "wrong user" unless user.id == session.user_id
|
|
|
78
92
|
|
|
79
93
|
`user` sends the active access token to Volcano and returns an immutable,
|
|
80
94
|
server-validated `Volcano::User`. The SDK recursively freezes its strings and
|
|
81
|
-
metadata
|
|
82
|
-
|
|
95
|
+
metadata and updates `current_session.user`. A session change while the request
|
|
96
|
+
is in flight raises
|
|
83
97
|
`Volcano::Error::SessionChangedError` instead of returning a stale profile.
|
|
84
98
|
`get_user` is available as a cross-SDK alias.
|
|
85
99
|
|
|
@@ -95,8 +109,8 @@ raise "wrong user" unless user.id == session.user_id
|
|
|
95
109
|
|
|
96
110
|
`update_user` changes the current user's password, metadata, or both. Metadata
|
|
97
111
|
is a shallow patch: omitted keys remain unchanged, and a `nil` value removes
|
|
98
|
-
that key. The method returns an immutable `Volcano::User`
|
|
99
|
-
|
|
112
|
+
that key. The method returns an immutable `Volcano::User` and updates the local
|
|
113
|
+
user snapshot. It rejects a response if another authentication operation
|
|
100
114
|
replaces the session while the request is in flight.
|
|
101
115
|
|
|
102
116
|
### Request a password reset email
|
|
@@ -159,8 +173,8 @@ user = client.auth.confirm_email_change(token: "email-change-token")
|
|
|
159
173
|
puts user.email
|
|
160
174
|
```
|
|
161
175
|
|
|
162
|
-
The method returns the immutable updated user
|
|
163
|
-
|
|
176
|
+
The method returns the immutable updated user and updates the local user
|
|
177
|
+
snapshot. A successful stale response is rejected if another authentication
|
|
164
178
|
operation replaces that session in flight.
|
|
165
179
|
|
|
166
180
|
### List sessions
|
data/lib/volcano/auth.rb
CHANGED
|
@@ -86,14 +86,21 @@ module Volcano
|
|
|
86
86
|
owned_session(
|
|
87
87
|
access_token: payload.fetch('access_token'),
|
|
88
88
|
refresh_token: payload.fetch('refresh_token'),
|
|
89
|
-
user_id: payload.fetch('user').fetch('id')
|
|
89
|
+
user_id: payload.fetch('user').fetch('id'),
|
|
90
|
+
user: payload.fetch('user')
|
|
90
91
|
)
|
|
91
92
|
end
|
|
92
93
|
|
|
93
94
|
def complete_session?(session)
|
|
94
95
|
return false unless session.is_a?(Session)
|
|
95
96
|
|
|
96
|
-
|
|
97
|
+
values = [session.access_token, session.refresh_token, session.user_id]
|
|
98
|
+
values.all? { |value| value.is_a?(String) && !value.strip.empty? } &&
|
|
99
|
+
matching_session_user?(session)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def matching_session_user?(session)
|
|
103
|
+
session.user.nil? || (session.user.is_a?(Hash) && session.user['id'] == session.user_id)
|
|
97
104
|
end
|
|
98
105
|
|
|
99
106
|
def owned_complete_session(session)
|
|
@@ -102,11 +109,12 @@ module Volcano
|
|
|
102
109
|
owned_session(**session.to_h)
|
|
103
110
|
end
|
|
104
111
|
|
|
105
|
-
def owned_session(access_token:, refresh_token:, user_id:)
|
|
112
|
+
def owned_session(access_token:, refresh_token:, user_id:, user: nil)
|
|
106
113
|
Session.new(
|
|
107
114
|
access_token: access_token.dup.freeze,
|
|
108
115
|
refresh_token: refresh_token.dup.freeze,
|
|
109
|
-
user_id: user_id.dup.freeze
|
|
116
|
+
user_id: user_id.dup.freeze,
|
|
117
|
+
user: user
|
|
110
118
|
)
|
|
111
119
|
end
|
|
112
120
|
end
|
|
@@ -20,10 +20,7 @@ module Volcano
|
|
|
20
20
|
anonymous_conversion_response(current.access_token, email, password, metadata),
|
|
21
21
|
200
|
|
22
22
|
)
|
|
23
|
-
|
|
24
|
-
raise Error::SessionChangedError unless @client.capture_session.first == generation
|
|
25
|
-
|
|
26
|
-
user
|
|
23
|
+
cache_current_user(payload, generation)
|
|
27
24
|
end
|
|
28
25
|
|
|
29
26
|
private
|
|
@@ -30,10 +30,7 @@ module Volcano
|
|
|
30
30
|
raise Error::AuthenticationError, 'No active session' unless current
|
|
31
31
|
|
|
32
32
|
payload = Transport.body(confirm_email_change_response(current.access_token, token), 200)
|
|
33
|
-
|
|
34
|
-
raise Error::SessionChangedError unless @client.capture_session.first == generation
|
|
35
|
-
|
|
36
|
-
user
|
|
33
|
+
cache_current_user(payload, generation)
|
|
37
34
|
end
|
|
38
35
|
|
|
39
36
|
private
|
|
@@ -19,16 +19,21 @@ module Volcano
|
|
|
19
19
|
raise Error::AuthenticationError, 'No active session' unless current
|
|
20
20
|
|
|
21
21
|
payload = Transport.body(get_user_response(current.access_token), 200)
|
|
22
|
-
|
|
23
|
-
raise Error::SessionChangedError unless @client.capture_session.first == generation
|
|
24
|
-
|
|
25
|
-
user
|
|
22
|
+
cache_current_user(payload, generation)
|
|
26
23
|
end
|
|
27
24
|
|
|
28
25
|
alias get_user user
|
|
29
26
|
|
|
30
27
|
private
|
|
31
28
|
|
|
29
|
+
def cache_current_user(payload, generation)
|
|
30
|
+
profile = user_payload(payload)
|
|
31
|
+
user = build_user(profile)
|
|
32
|
+
raise Error::SessionChangedError unless @client.update_session_user_if_current?(profile, generation)
|
|
33
|
+
|
|
34
|
+
user
|
|
35
|
+
end
|
|
36
|
+
|
|
32
37
|
def get_user_response(access_token)
|
|
33
38
|
Transport.invoke do
|
|
34
39
|
@transport.auth_get_user(authorization: access_token)
|
data/lib/volcano/auth_state.rb
CHANGED
|
@@ -50,10 +50,9 @@ module Volcano
|
|
|
50
50
|
|
|
51
51
|
def store_if_current?(session, generation, event: :signed_in, notifications: nil)
|
|
52
52
|
dispatch = @mutex.synchronize do
|
|
53
|
-
|
|
54
|
-
return false unless callbacks
|
|
53
|
+
return false unless generation == @generation
|
|
55
54
|
|
|
56
|
-
enqueue_notification(
|
|
55
|
+
enqueue_notification(replace(session, event), event, session)
|
|
57
56
|
end
|
|
58
57
|
return true unless dispatch
|
|
59
58
|
|
|
@@ -61,6 +60,16 @@ module Volcano
|
|
|
61
60
|
true
|
|
62
61
|
end
|
|
63
62
|
|
|
63
|
+
def update_user_if_current?(user, generation)
|
|
64
|
+
@mutex.synchronize do
|
|
65
|
+
return false unless generation == @generation && @session
|
|
66
|
+
raise Error::AuthenticationError, 'Profile belongs to a different user' unless user['id'] == @session.user_id
|
|
67
|
+
|
|
68
|
+
@session = Session.new(**@session.to_h, user: user)
|
|
69
|
+
true
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
64
73
|
def subscribe(&callback)
|
|
65
74
|
callback_id, dispatch = @mutex.synchronize do
|
|
66
75
|
id, current = register(callback)
|
|
@@ -79,12 +88,6 @@ module Volcano
|
|
|
79
88
|
@callbacks.keys
|
|
80
89
|
end
|
|
81
90
|
|
|
82
|
-
def replace_if_current(session, generation, event)
|
|
83
|
-
return unless generation == @generation
|
|
84
|
-
|
|
85
|
-
replace(session, event)
|
|
86
|
-
end
|
|
87
|
-
|
|
88
91
|
def register(callback)
|
|
89
92
|
callback_id = @next_callback_id
|
|
90
93
|
@next_callback_id += 1
|
|
@@ -130,7 +133,7 @@ module Volcano
|
|
|
130
133
|
def notify(callback_ids, event, session)
|
|
131
134
|
failure = nil
|
|
132
135
|
callback_ids.each do |callback_id|
|
|
133
|
-
|
|
136
|
+
@mutex.synchronize { @callbacks[callback_id] }&.call(event, session)
|
|
134
137
|
rescue StandardError => e
|
|
135
138
|
Warning.warn("Volcano auth-state callback failed (#{e.class})\n")
|
|
136
139
|
rescue *CALLBACK_FAILURES => e
|
|
@@ -139,10 +142,5 @@ module Volcano
|
|
|
139
142
|
end
|
|
140
143
|
failure
|
|
141
144
|
end
|
|
142
|
-
|
|
143
|
-
def notify_callback(callback_id, event, session)
|
|
144
|
-
callback = @mutex.synchronize { @callbacks[callback_id] }
|
|
145
|
-
callback&.call(event, session)
|
|
146
|
-
end
|
|
147
145
|
end
|
|
148
146
|
end
|
|
@@ -11,10 +11,7 @@ module Volcano
|
|
|
11
11
|
update_user_response(current.access_token, password:, metadata:),
|
|
12
12
|
200
|
|
13
13
|
)
|
|
14
|
-
|
|
15
|
-
raise Error::SessionChangedError unless @client.capture_session.first == generation
|
|
16
|
-
|
|
17
|
-
user
|
|
14
|
+
cache_current_user(payload, generation)
|
|
18
15
|
end
|
|
19
16
|
|
|
20
17
|
private
|
data/lib/volcano/client.rb
CHANGED
data/lib/volcano/models.rb
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Volcano
|
|
4
|
-
Session = Data.define(:access_token, :refresh_token, :user_id)
|
|
5
4
|
AUTH_SESSION_ATTRIBUTES = %i[
|
|
6
5
|
id user_id provider expires_at is_active is_current user_agent ip_address last_ip_address
|
|
7
6
|
last_activity_at session_started_at created_at updated_at
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
require 'time'
|
|
5
|
+
|
|
6
|
+
module Volcano
|
|
7
|
+
SESSION_USER_CODER = JSON::Coder.new(freeze: true, allow_duplicate_key: false) do |value|
|
|
8
|
+
value.instance_of?(Time) ? Time.at(value.to_r).utc.iso8601(9) : value
|
|
9
|
+
end
|
|
10
|
+
private_constant :SESSION_USER_CODER
|
|
11
|
+
|
|
12
|
+
# In-memory credentials with an optional, unverified local user snapshot.
|
|
13
|
+
Session = Data.define(:access_token, :refresh_token, :user_id, :user) do
|
|
14
|
+
def initialize(access_token:, refresh_token:, user_id:, user: nil)
|
|
15
|
+
super(access_token:, refresh_token:, user_id:, user: immutable_user(user))
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def immutable_user(value)
|
|
21
|
+
SESSION_USER_CODER.load(SESSION_USER_CODER.dump(value))
|
|
22
|
+
rescue JSON::GeneratorError, JSON::NestingError
|
|
23
|
+
raise TypeError, 'Session user snapshot must contain JSON values or timestamps', cause: nil
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
data/lib/volcano/version.rb
CHANGED
data/lib/volcano.rb
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require_relative 'volcano/version'
|
|
4
4
|
require_relative 'volcano/connection_string'
|
|
5
5
|
require_relative 'volcano/models'
|
|
6
|
+
require_relative 'volcano/session'
|
|
6
7
|
require_relative 'volcano/function_response'
|
|
7
8
|
require_relative 'volcano/log_responses'
|
|
8
9
|
require_relative 'volcano/storage_models'
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: volcano-sdk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kong
|
|
@@ -65,6 +65,20 @@ dependencies:
|
|
|
65
65
|
- - "~>"
|
|
66
66
|
- !ruby/object:Gem::Version
|
|
67
67
|
version: '0.2'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: json
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - "~>"
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '2.17'
|
|
75
|
+
type: :runtime
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - "~>"
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '2.17'
|
|
68
82
|
- !ruby/object:Gem::Dependency
|
|
69
83
|
name: logger
|
|
70
84
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -560,6 +574,7 @@ files:
|
|
|
560
574
|
- lib/volcano/realtime/protocol_recovery_position.rb
|
|
561
575
|
- lib/volcano/realtime/reconnect.rb
|
|
562
576
|
- lib/volcano/redaction.rb
|
|
577
|
+
- lib/volcano/session.rb
|
|
563
578
|
- lib/volcano/sign_up_result.rb
|
|
564
579
|
- lib/volcano/storage.rb
|
|
565
580
|
- lib/volcano/storage_models.rb
|