volcano-sdk 0.6.0 → 0.7.1
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 +12 -8
- 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_refresh.rb +4 -4
- data/lib/volcano/auth_state.rb +13 -15
- data/lib/volcano/auth_update_user.rb +1 -4
- data/lib/volcano/client.rb +6 -2
- data/lib/volcano/storage.rb +20 -8
- data/lib/volcano/storage_mutations.rb +11 -11
- data/lib/volcano/storage_upload_sessions.rb +10 -10
- data/lib/volcano/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9d85e7ec311f812ca5267cec7b463ebd65ff82ba44f4ce06e71f23085f7932ea
|
|
4
|
+
data.tar.gz: 772266f8fe5398d085442a03bcf2544468016fc335eb61fb0c1ba04ba47dde35
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2718f112a8e2264f826aa4f3bc89c61f4492ee6034c0913d0e8b64e3d5662e8b89579af0dfbe11a88b2c92fee01c8f7508f90e347a0a7b14f7e4aa3fd40433f4
|
|
7
|
+
data.tar.gz: 773a396b12e6c1b02ed03c5c3d8b4356b39bdac11a222bfecd2817ff0fe6ceee7644d367bb4255f6da90652cf45782efc4fc922e5d2501042ba07d1f1a2847b7
|
data/README.md
CHANGED
|
@@ -78,7 +78,10 @@ Snapshots contain deeply frozen JSON data. Plain `Time` timestamps become UTC
|
|
|
78
78
|
ISO8601 strings with nanosecond precision; symbols become strings. Custom objects,
|
|
79
79
|
container/string/time subclasses, non-finite numbers, duplicate JSON keys, and
|
|
80
80
|
structures deeper than 100 levels raise `TypeError`. Use the typed `auth.user`
|
|
81
|
-
profile when you need Ruby `Time` values.
|
|
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.
|
|
82
85
|
|
|
83
86
|
### Get the current user
|
|
84
87
|
|
|
@@ -89,8 +92,8 @@ raise "wrong user" unless user.id == session.user_id
|
|
|
89
92
|
|
|
90
93
|
`user` sends the active access token to Volcano and returns an immutable,
|
|
91
94
|
server-validated `Volcano::User`. The SDK recursively freezes its strings and
|
|
92
|
-
metadata
|
|
93
|
-
|
|
95
|
+
metadata and updates `current_session.user`. A session change while the request
|
|
96
|
+
is in flight raises
|
|
94
97
|
`Volcano::Error::SessionChangedError` instead of returning a stale profile.
|
|
95
98
|
`get_user` is available as a cross-SDK alias.
|
|
96
99
|
|
|
@@ -106,8 +109,8 @@ raise "wrong user" unless user.id == session.user_id
|
|
|
106
109
|
|
|
107
110
|
`update_user` changes the current user's password, metadata, or both. Metadata
|
|
108
111
|
is a shallow patch: omitted keys remain unchanged, and a `nil` value removes
|
|
109
|
-
that key. The method returns an immutable `Volcano::User`
|
|
110
|
-
|
|
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
|
|
111
114
|
replaces the session while the request is in flight.
|
|
112
115
|
|
|
113
116
|
### Request a password reset email
|
|
@@ -170,8 +173,8 @@ user = client.auth.confirm_email_change(token: "email-change-token")
|
|
|
170
173
|
puts user.email
|
|
171
174
|
```
|
|
172
175
|
|
|
173
|
-
The method returns the immutable updated user
|
|
174
|
-
|
|
176
|
+
The method returns the immutable updated user and updates the local user
|
|
177
|
+
snapshot. A successful stale response is rejected if another authentication
|
|
175
178
|
operation replaces that session in flight.
|
|
176
179
|
|
|
177
180
|
### List sessions
|
|
@@ -484,7 +487,8 @@ syntax. Both methods require an active user session.
|
|
|
484
487
|
rows = client.database("main").from("items").select("*").eq("slug", "a").execute
|
|
485
488
|
```
|
|
486
489
|
|
|
487
|
-
Database selects, inserts, updates, deletes,
|
|
490
|
+
Database selects, inserts, updates, deletes, log reads, and authenticated storage
|
|
491
|
+
requests (including upload sessions and parts) refresh the captured
|
|
488
492
|
session after an HTTP 401 and retry the same request once. Concurrent requests reuse a successful
|
|
489
493
|
refresh for that session.
|
|
490
494
|
Replacing or signing out the session before replay, or while replay is in flight,
|
|
@@ -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_refresh.rb
CHANGED
|
@@ -10,10 +10,10 @@ module Volcano
|
|
|
10
10
|
refresh_captured_session(binding)
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
def session_request
|
|
14
|
-
binding = @client.capture_session_binding
|
|
13
|
+
def session_request(binding: @client.capture_session_binding)
|
|
15
14
|
raise Error::AuthenticationError, 'No active session' unless binding.last
|
|
16
15
|
|
|
16
|
+
binding = owned_session_binding(binding)
|
|
17
17
|
response = yield(binding.last.access_token)
|
|
18
18
|
return response unless response.status == 401
|
|
19
19
|
|
|
@@ -65,10 +65,10 @@ module Volcano
|
|
|
65
65
|
active = @client.capture_session_binding
|
|
66
66
|
raise Error::AuthenticationError, 'No active session' if rejected_refresh?(binding, active)
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
_, active_lineage, current = active
|
|
69
69
|
raise Error::SessionChangedError unless current && active_lineage == binding[1]
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
active
|
|
72
72
|
end
|
|
73
73
|
|
|
74
74
|
def rejected_refresh?(binding, active)
|
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
|
@@ -49,8 +49,8 @@ module Volcano
|
|
|
49
49
|
session.access_token
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
-
def session_request(
|
|
53
|
-
@auth.session_request(
|
|
52
|
+
def session_request(...)
|
|
53
|
+
@auth.session_request(...)
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
alias session_read session_request
|
|
@@ -89,6 +89,10 @@ module Volcano
|
|
|
89
89
|
@auth_state.subscribe(...)
|
|
90
90
|
end
|
|
91
91
|
|
|
92
|
+
def update_session_user_if_current?(...)
|
|
93
|
+
@auth_state.update_user_if_current?(...)
|
|
94
|
+
end
|
|
95
|
+
|
|
92
96
|
private
|
|
93
97
|
|
|
94
98
|
def database_with_token(name, token)
|
data/lib/volcano/storage.rb
CHANGED
|
@@ -28,7 +28,7 @@ module Volcano
|
|
|
28
28
|
def initialize(client, transport, name, api_url:, anon_key:)
|
|
29
29
|
@client = client
|
|
30
30
|
@transport = transport
|
|
31
|
-
@name = name
|
|
31
|
+
@name = name.dup.freeze
|
|
32
32
|
@api_url = api_url.dup.freeze
|
|
33
33
|
@anon_key = anon_key.dup.freeze
|
|
34
34
|
freeze
|
|
@@ -36,12 +36,16 @@ module Volcano
|
|
|
36
36
|
|
|
37
37
|
def upload(path, value, content_type: nil)
|
|
38
38
|
mime_type = upload_content_type(content_type)
|
|
39
|
-
|
|
39
|
+
path = storage_paths(path).first
|
|
40
|
+
binding = @client.capture_session_binding
|
|
41
|
+
@client.session_token
|
|
42
|
+
content = upload_bytes(value).freeze
|
|
43
|
+
response = storage_request(binding: binding) do |token|
|
|
40
44
|
@transport.upload_storage_object(
|
|
41
|
-
authorization:
|
|
45
|
+
authorization: token,
|
|
42
46
|
bucket_name: @name,
|
|
43
47
|
path: path,
|
|
44
|
-
data:
|
|
48
|
+
data: content,
|
|
45
49
|
content_type: mime_type
|
|
46
50
|
)
|
|
47
51
|
end
|
|
@@ -49,9 +53,11 @@ module Volcano
|
|
|
49
53
|
end
|
|
50
54
|
|
|
51
55
|
def download(path, range: nil)
|
|
52
|
-
|
|
56
|
+
path = storage_paths(path).first
|
|
57
|
+
range = range&.dup&.freeze
|
|
58
|
+
response = storage_request do |token|
|
|
53
59
|
@transport.download_storage_object(
|
|
54
|
-
authorization:
|
|
60
|
+
authorization: token,
|
|
55
61
|
bucket_name: @name,
|
|
56
62
|
path: path,
|
|
57
63
|
byte_range: range
|
|
@@ -63,9 +69,11 @@ module Volcano
|
|
|
63
69
|
end
|
|
64
70
|
|
|
65
71
|
def list(prefix = '', limit: nil, cursor: nil)
|
|
66
|
-
|
|
72
|
+
prefix = prefix.dup.freeze
|
|
73
|
+
cursor = cursor&.dup&.freeze
|
|
74
|
+
response = storage_request do |token|
|
|
67
75
|
@transport.list_storage_objects(
|
|
68
|
-
authorization:
|
|
76
|
+
authorization: token,
|
|
69
77
|
bucket_name: @name,
|
|
70
78
|
prefix: prefix,
|
|
71
79
|
limit: limit,
|
|
@@ -82,6 +90,10 @@ module Volcano
|
|
|
82
90
|
|
|
83
91
|
private
|
|
84
92
|
|
|
93
|
+
def storage_request(binding: @client.capture_session_binding)
|
|
94
|
+
@client.session_request(binding: binding) { |token| Transport.invoke { yield(token) } }
|
|
95
|
+
end
|
|
96
|
+
|
|
85
97
|
def upload_content_type(value)
|
|
86
98
|
return if value.nil?
|
|
87
99
|
return value.dup.freeze if value.is_a?(String) && value.match?(/\A[\x20-\x7e]+\z/) && !value.strip.empty?
|
|
@@ -5,16 +5,16 @@ module Volcano
|
|
|
5
5
|
class StorageBucket
|
|
6
6
|
def remove(paths)
|
|
7
7
|
deleted = storage_paths(paths)
|
|
8
|
-
|
|
9
|
-
deleted.each { |path| delete_path(path,
|
|
8
|
+
binding = @client.capture_session_binding
|
|
9
|
+
deleted.each { |path| delete_path(path, binding) }
|
|
10
10
|
deleted
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def move(from_path, to_path)
|
|
14
14
|
source, destination = storage_paths([from_path, to_path])
|
|
15
|
-
response =
|
|
15
|
+
response = storage_request do |token|
|
|
16
16
|
@transport.move_storage_object(
|
|
17
|
-
authorization:
|
|
17
|
+
authorization: token,
|
|
18
18
|
bucket_name: @name,
|
|
19
19
|
from_path: source,
|
|
20
20
|
to_path: destination
|
|
@@ -25,9 +25,9 @@ module Volcano
|
|
|
25
25
|
|
|
26
26
|
def copy(from_path, to_path)
|
|
27
27
|
source, destination = storage_paths([from_path, to_path])
|
|
28
|
-
response =
|
|
28
|
+
response = storage_request do |token|
|
|
29
29
|
@transport.copy_storage_object(
|
|
30
|
-
authorization:
|
|
30
|
+
authorization: token,
|
|
31
31
|
bucket_name: @name,
|
|
32
32
|
from_path: source,
|
|
33
33
|
to_path: destination
|
|
@@ -39,9 +39,9 @@ module Volcano
|
|
|
39
39
|
def update_visibility(path, public:)
|
|
40
40
|
object_path = storage_paths(path).fetch(0)
|
|
41
41
|
visibility = visibility_value(public)
|
|
42
|
-
response =
|
|
42
|
+
response = storage_request do |token|
|
|
43
43
|
@transport.update_storage_object_visibility(
|
|
44
|
-
authorization:
|
|
44
|
+
authorization: token,
|
|
45
45
|
bucket_name: @name,
|
|
46
46
|
path: object_path,
|
|
47
47
|
is_public: visibility
|
|
@@ -61,10 +61,10 @@ module Volcano
|
|
|
61
61
|
path_list.map { |path| path.dup.freeze }.freeze
|
|
62
62
|
end
|
|
63
63
|
|
|
64
|
-
def delete_path(path,
|
|
65
|
-
response =
|
|
64
|
+
def delete_path(path, binding)
|
|
65
|
+
response = storage_request(binding: binding) do |token|
|
|
66
66
|
@transport.delete_storage_object(
|
|
67
|
-
authorization:
|
|
67
|
+
authorization: token,
|
|
68
68
|
bucket_name: @name,
|
|
69
69
|
path: path
|
|
70
70
|
)
|
|
@@ -15,9 +15,9 @@ module Volcano
|
|
|
15
15
|
total_size: total_size,
|
|
16
16
|
part_size: part_size
|
|
17
17
|
)
|
|
18
|
-
response =
|
|
18
|
+
response = storage_request do |token|
|
|
19
19
|
@transport.create_upload_session(
|
|
20
|
-
authorization:
|
|
20
|
+
authorization: token,
|
|
21
21
|
bucket_name: @name,
|
|
22
22
|
request: request
|
|
23
23
|
)
|
|
@@ -32,9 +32,9 @@ module Volcano
|
|
|
32
32
|
part_number: part_number,
|
|
33
33
|
data: upload_bytes(data)
|
|
34
34
|
)
|
|
35
|
-
response =
|
|
35
|
+
response = storage_request do |token|
|
|
36
36
|
@transport.upload_part(
|
|
37
|
-
authorization:
|
|
37
|
+
authorization: token,
|
|
38
38
|
bucket_name: @name,
|
|
39
39
|
request: request
|
|
40
40
|
)
|
|
@@ -44,9 +44,9 @@ module Volcano
|
|
|
44
44
|
|
|
45
45
|
def complete_upload_session(path, session_id:)
|
|
46
46
|
request = UploadSessionReference.new(path: path, session_id: session_id)
|
|
47
|
-
response =
|
|
47
|
+
response = storage_request do |token|
|
|
48
48
|
@transport.complete_upload_session(
|
|
49
|
-
authorization:
|
|
49
|
+
authorization: token,
|
|
50
50
|
bucket_name: @name,
|
|
51
51
|
request: request
|
|
52
52
|
)
|
|
@@ -56,9 +56,9 @@ module Volcano
|
|
|
56
56
|
|
|
57
57
|
def get_upload_session(path, session_id:)
|
|
58
58
|
request = UploadSessionReference.new(path: path, session_id: session_id)
|
|
59
|
-
response =
|
|
59
|
+
response = storage_request do |token|
|
|
60
60
|
@transport.get_upload_session(
|
|
61
|
-
authorization:
|
|
61
|
+
authorization: token,
|
|
62
62
|
bucket_name: @name,
|
|
63
63
|
request: request
|
|
64
64
|
)
|
|
@@ -68,9 +68,9 @@ module Volcano
|
|
|
68
68
|
|
|
69
69
|
def abort_upload_session(path, session_id:)
|
|
70
70
|
request = UploadSessionReference.new(path: path, session_id: session_id)
|
|
71
|
-
response =
|
|
71
|
+
response = storage_request do |token|
|
|
72
72
|
@transport.abort_upload_session(
|
|
73
|
-
authorization:
|
|
73
|
+
authorization: token,
|
|
74
74
|
bucket_name: @name,
|
|
75
75
|
request: request
|
|
76
76
|
)
|
data/lib/volcano/version.rb
CHANGED