statelydb 0.13.0 → 0.14.0

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
2
  SHA256:
3
- metadata.gz: 1518fe47ef69d7e171862c88f5b8a9425116dc1390623724dc95e285e960b728
4
- data.tar.gz: f5e9faad6e851892a695a47590e7430908e419b44c2f94a60087fec4c316c808
3
+ metadata.gz: a723737fdce6e8ad2bec8937cfd79f6d968df0fc3e9e747c64e18af9ce769601
4
+ data.tar.gz: 1f0279a8b9507f4cffacc360ab82e2289471a40de39bd3891f0c7db5c63877c6
5
5
  SHA512:
6
- metadata.gz: acc4be2621242c08236efdf8e1f9fa48090070c3c4ad12583481bc2a2df4ee5638fbb665059a0138a7bf53270bed8d6bf0f5290843dd5d488b71274f2a3284b8
7
- data.tar.gz: ddccab6882a70b7eab33c56893fd9cae614ee67c5343b0953f7af33d3fe487418eb00c3300d3a24ae6e14df88f5cf49609b9e1f4a966db10d646ab184c00a685
6
+ metadata.gz: 815835070a91366b18948afe145eb548ae4f6ecbc6559ed3b8193288cd1084b7ac1a416264b0769afea93f4a8c01e17b0474facb46fe90460b0b3db803466428
7
+ data.tar.gz: e0c75f31911432f2544c4097fbc0c7a1615624257e80495aef9e5b3a0dddc92dd9341683d24416c4a32ab19b8bd34a2d79abb577781d75ee41b55a02f2e2e11c
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
3
+ # source: auth/get_auth_token.proto
4
+
5
+ require 'google/protobuf'
6
+
7
+
8
+ descriptor_data = "\n\x19\x61uth/get_auth_token.proto\x12\x0cstately.auth\"B\n\x13GetAuthTokenRequest\x12\x1f\n\naccess_key\x18\x01 \x01(\tH\x00R\taccessKeyB\n\n\x08identity\"W\n\x14GetAuthTokenResponse\x12\x1d\n\nauth_token\x18\x01 \x01(\tR\tauthToken\x12 \n\x0c\x65xpires_in_s\x18\x02 \x01(\x04R\nexpiresInSBv\n\x10\x63om.stately.authB\x11GetAuthTokenProtoP\x01\xa2\x02\x03SAX\xaa\x02\x0cStately.Auth\xca\x02\x0cStately\\Auth\xe2\x02\x18Stately\\Auth\\GPBMetadata\xea\x02\rStately::Authb\x06proto3"
9
+
10
+ pool = Google::Protobuf::DescriptorPool.generated_pool
11
+ pool.add_serialized_file(descriptor_data)
12
+
13
+ module Stately
14
+ module Auth
15
+ GetAuthTokenRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("stately.auth.GetAuthTokenRequest").msgclass
16
+ GetAuthTokenResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("stately.auth.GetAuthTokenResponse").msgclass
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
3
+ # source: auth/service.proto
4
+
5
+ require 'google/protobuf'
6
+
7
+ require 'api/auth/get_auth_token_pb'
8
+
9
+
10
+ descriptor_data = "\n\x12\x61uth/service.proto\x12\x0cstately.auth\x1a\x19\x61uth/get_auth_token.proto2i\n\x0b\x41uthService\x12Z\n\x0cGetAuthToken\x12!.stately.auth.GetAuthTokenRequest\x1a\".stately.auth.GetAuthTokenResponse\"\x03\x90\x02\x01\x42q\n\x10\x63om.stately.authB\x0cServiceProtoP\x01\xa2\x02\x03SAX\xaa\x02\x0cStately.Auth\xca\x02\x0cStately\\Auth\xe2\x02\x18Stately\\Auth\\GPBMetadata\xea\x02\rStately::Authb\x06proto3"
11
+
12
+ pool = Google::Protobuf::DescriptorPool.generated_pool
13
+ pool.add_serialized_file(descriptor_data)
14
+
15
+ module Stately
16
+ module Auth
17
+ end
18
+ end
@@ -0,0 +1,29 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # Source: auth/service.proto for package 'Stately.Auth'
3
+
4
+ require 'grpc'
5
+ require 'api/auth/service_pb'
6
+
7
+ module Stately
8
+ module Auth
9
+ module AuthService
10
+ # AuthService is the service for vending access tokens used to connect to
11
+ # StatelyDB. This API is meant to be used from SDKs. Access Keys are created
12
+ # and managed from the stately.dbmanagement.UserService.
13
+ class Service
14
+
15
+ include ::GRPC::GenericService
16
+
17
+ self.marshal_class_method = :encode
18
+ self.unmarshal_class_method = :decode
19
+ self.service_name = 'stately.auth.AuthService'
20
+
21
+ # GetAuthToken returns a short-lived access token from some proof of
22
+ # identity. This operation will fail if the identity cannot be verified.
23
+ rpc :GetAuthToken, ::Stately::Auth::GetAuthTokenRequest, ::Stately::Auth::GetAuthTokenResponse
24
+ end
25
+
26
+ Stub = Service.rpc_stub_class
27
+ end
28
+ end
29
+ end
@@ -6,8 +6,10 @@ require "async/http/internet"
6
6
  require "async/semaphore"
7
7
  require "json"
8
8
  require "logger"
9
- require "weakref"
9
+ require "grpc"
10
10
  require_relative "token_provider"
11
+ require_relative "token_fetcher"
12
+ require_relative "../../error"
11
13
 
12
14
  LOGGER = Logger.new($stdout)
13
15
  LOGGER.level = Logger::WARN
@@ -22,20 +24,22 @@ module StatelyDB
22
24
  # which vends tokens from auth0 with the given client_id and client_secret.
23
25
  # It will default to using the values of `STATELY_CLIENT_ID` and `STATELY_CLIENT_SECRET` if
24
26
  # no credentials are explicitly passed and will throw an error if none are found.
25
- class Auth0TokenProvider < TokenProvider
27
+ class AuthTokenProvider < TokenProvider
26
28
  # @param [String] origin The origin of the OAuth server
27
29
  # @param [String] audience The OAuth Audience for the token
28
30
  # @param [String] client_secret The StatelyDB client secret credential
29
31
  # @param [String] client_id The StatelyDB client ID credential
32
+ # @param [String] access_key The StatelyDB access key credential
30
33
  def initialize(
31
34
  origin: "https://oauth.stately.cloud",
32
35
  audience: "api.stately.cloud",
33
- client_secret: ENV.fetch("STATELY_CLIENT_SECRET"),
34
- client_id: ENV.fetch("STATELY_CLIENT_ID")
36
+ client_secret: ENV.fetch("STATELY_CLIENT_SECRET", nil),
37
+ client_id: ENV.fetch("STATELY_CLIENT_ID", nil),
38
+ access_key: ENV.fetch("STATELY_ACCESS_KEY", nil)
35
39
  )
36
40
  super()
37
41
  @actor = Async::Actor.new(Actor.new(origin: origin, audience: audience,
38
- client_secret: client_secret, client_id: client_id))
42
+ client_secret: client_secret, client_id: client_id, access_key: access_key))
39
43
  # this initialization cannot happen in the constructor because it is async and must run on the event loop
40
44
  # which is not available in the constructor
41
45
  @actor.init
@@ -64,29 +68,41 @@ module StatelyDB
64
68
  origin:,
65
69
  audience:,
66
70
  client_secret:,
67
- client_id:
71
+ client_id:,
72
+ access_key:
68
73
  )
69
74
  super()
70
- @client = Async::HTTP::Client.new(Async::HTTP::Endpoint.parse(origin))
71
- @client_id = client_id
72
- @client_secret = client_secret
73
- @audience = audience
74
75
 
75
- @access_token = nil
76
- @expires_at_unix_secs = nil
76
+ @token_fetcher = nil
77
+ if !access_key.nil?
78
+ @token_fetcher = StatelyDB::Common::Auth::StatelyAccessTokenFetcher.new(origin: origin, access_key: access_key)
79
+ elsif !client_secret.nil? && !client_id.nil?
80
+ @token_fetcher = StatelyDB::Common::Auth::Auth0TokenFetcher.new(origin: origin, audience: audience,
81
+ client_secret: client_secret, client_id: client_id)
82
+ else
83
+ raise StatelyDB::Error.new("unable to find client credentials in STATELY_ACCESS_KEY or STATELY_CLIENT_ID and " \
84
+ "STATELY_CLIENT_SECRET environment variables. Either pass your credentials in " \
85
+ "explicitly or set these environment variables",
86
+ code: GRPC::Core::StatusCodes::UNAUTHENTICATED,
87
+ stately_code: "Unauthenticated")
88
+ end
89
+
90
+ @token_state = nil
77
91
  @pending_refresh = nil
78
92
  end
79
93
 
80
94
  # Initialize the actor. This runs on the actor thread which means
81
95
  # we can dispatch async operations here.
82
96
  def init
97
+ # disable the async lib logger. We do our own error handling and propagation
98
+ Console.logger.disable(Async::Task)
83
99
  refresh_token
84
100
  end
85
101
 
86
102
  # Close the token provider and kill any background operations
87
103
  def close
88
104
  @scheduled&.stop
89
- @client&.close
105
+ @token_fetcher&.close
90
106
  end
91
107
 
92
108
  # Get the current access token
@@ -94,8 +110,7 @@ module StatelyDB
94
110
  # @return [String] The current access token
95
111
  def get_token(force: false)
96
112
  if force
97
- @access_token = nil
98
- @expires_at_unix_secs = nil
113
+ @token_state = nil
99
114
  else
100
115
  token, ok = valid_access_token
101
116
  return token if ok
@@ -107,11 +122,10 @@ module StatelyDB
107
122
  # Get the current access token and whether it is valid
108
123
  # @return [Array] The current access token and whether it is valid
109
124
  def valid_access_token
110
- return "", false if @access_token.nil?
111
- return "", false if @expires_at_unix_secs.nil?
112
- return "", false if @expires_at_unix_secs < Time.now.to_i
125
+ return "", false if @token_state.nil?
126
+ return "", false if @token_state.expires_at_unix_secs < Time.now.to_i
113
127
 
114
- [@access_token, true]
128
+ [@token_state.token, true]
115
129
  end
116
130
 
117
131
  # Refresh the access token
@@ -151,19 +165,16 @@ module StatelyDB
151
165
  # @return [String] The new access token
152
166
  def refresh_token_impl
153
167
  Sync do
154
- resp_data = make_auth0_request
155
-
156
- new_access_token = resp_data["access_token"]
157
- new_expires_in_secs = resp_data["expires_in"]
168
+ token_result = @token_fetcher.fetch
169
+ new_expires_in_secs = token_result.expires_in_secs
158
170
  new_expires_at_unix_secs = Time.now.to_i + new_expires_in_secs
159
- if @expires_at_unix_secs.nil? || new_expires_at_unix_secs > @expires_at_unix_secs
160
171
 
161
- @access_token = new_access_token
162
- @expires_at_unix_secs = new_expires_at_unix_secs
172
+ # only update the token state if the new expiry is later than the current one
173
+ if @token_state.nil? || new_expires_at_unix_secs > @token_state.expires_at_unix_secs
174
+ @token_state = TokenState.new(token: token_result.token, expires_at_unix_secs: new_expires_at_unix_secs)
163
175
  else
164
-
165
- new_access_token = @access_token
166
- new_expires_in_secs = @expires_at_unix_secs - Time.now.to_i
176
+ # otherwise use the existing expiry time for scheduling the refresh
177
+ new_expires_in_secs = @token_state.expires_at_unix_secs - Time.now.to_i
167
178
  end
168
179
 
169
180
  # Schedule a refresh of the token ahead of the expiry time
@@ -182,24 +193,21 @@ module StatelyDB
182
193
  @scheduled = nil
183
194
  end
184
195
 
185
- new_access_token
196
+ @token_state.token
186
197
  end
187
198
  end
199
+ end
188
200
 
189
- def make_auth0_request
190
- headers = [["content-type", "application/json"]]
191
- body = JSON.dump({ "client_id" => @client_id, client_secret: @client_secret, audience: @audience,
192
- grant_type: DEFAULT_GRANT_TYPE })
193
- Sync do
194
- # TODO: Wrap this in a retry loop and parse errors like we
195
- # do in the Go SDK.
196
- response = @client.post("/oauth/token", headers, body)
197
- raise "Auth request failed" if response.status != 200
198
-
199
- JSON.parse(response.read)
200
- ensure
201
- response&.close
202
- end
201
+ # Persistent state for the token provider
202
+ class TokenState
203
+ attr_reader :token, :expires_at_unix_secs
204
+
205
+ # Create a new TokenState
206
+ # @param [String] token The access token
207
+ # @param [Integer] expires_at_unix_secs The unix timestamp when the token expires
208
+ def initialize(token:, expires_at_unix_secs:)
209
+ @token = token
210
+ @expires_at_unix_secs = expires_at_unix_secs
203
211
  end
204
212
  end
205
213
  end
@@ -11,7 +11,7 @@ module StatelyDB
11
11
  class Interceptor < GRPC::ClientInterceptor
12
12
  # @param [TokenProvider] token_provider The token provider to use for authentication
13
13
  def initialize(
14
- token_provider: Auth0TokenProvider.new
14
+ token_provider: AuthTokenProvider.new
15
15
  )
16
16
  super()
17
17
  @token_provider = token_provider
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../net/conn"
4
+ require_relative "../error_interceptor"
5
+ require_relative "../../api/auth/service_services_pb"
6
+ require "grpc"
7
+
8
+ module StatelyDB
9
+ module Common
10
+ # A module for Stately Cloud auth code
11
+ module Auth
12
+ # Result from a token fetch operation
13
+ class TokenResult
14
+ attr_reader :token, :expires_in_secs
15
+
16
+ # Create a new TokenResult
17
+ # @param [String] token The access token
18
+ # @param [Integer] expires_in_secs The number of seconds until the token expires
19
+ def initialize(token:, expires_in_secs:)
20
+ @token = token
21
+ @expires_in_secs = expires_in_secs
22
+ end
23
+ end
24
+
25
+ # TokenFetcher is an abstract base class that should be extended
26
+ # for individual token fetcher implementations
27
+ class TokenFetcher
28
+ # Get the current access token
29
+ # @return [TokenResult] The fetched TokenResult
30
+ def fetch
31
+ raise "Not Implemented"
32
+ end
33
+
34
+ # Close the token provider and kill any background operations
35
+ def close
36
+ raise "Not Implemented"
37
+ end
38
+ end
39
+
40
+ # Auth0TokenFetcher is a TokenFetcher that fetches tokens from an Auth0 server
41
+ class Auth0TokenFetcher < TokenFetcher
42
+ # @param [String] origin The origin of the OAuth server
43
+ # @param [String] audience The OAuth Audience for the token
44
+ # @param [String] client_secret The StatelyDB client secret credential
45
+ # @param [String] client_id The StatelyDB client ID credential
46
+ def initialize(origin:, audience:, client_secret:, client_id:)
47
+ super()
48
+ @client = Async::HTTP::Client.new(Async::HTTP::Endpoint.parse(origin))
49
+ @audience = audience
50
+ @client_secret = client_secret
51
+ @client_id = client_id
52
+ end
53
+
54
+ # Fetch a new token from auth0
55
+ # @return [TokenResult] The fetched TokenResult
56
+ def fetch
57
+ headers = [["content-type", "application/json"]]
58
+ body = JSON.dump({ "client_id" => @client_id, client_secret: @client_secret, audience: @audience,
59
+ grant_type: DEFAULT_GRANT_TYPE })
60
+ Sync do
61
+ # TODO: Wrap this in a retry loop and parse errors like we
62
+ # do in the Go SDK.
63
+ response = @client.post("/oauth/token", headers, body)
64
+ raise "Auth request failed" if response.status != 200
65
+
66
+ resp_data = JSON.parse(response.read)
67
+ TokenResult.new(token: resp_data["access_token"], expires_in_secs: resp_data["expires_in"])
68
+ ensure
69
+ response&.close
70
+ end
71
+ end
72
+
73
+ def close
74
+ @client&.close
75
+ end
76
+ end
77
+
78
+ # StatelyAccessTokenFetcher is a TokenFetcher that fetches tokens from the StatelyDB API
79
+ class StatelyAccessTokenFetcher < TokenFetcher
80
+ # @param [String] origin The origin of the OAuth server
81
+ # @param [String] access_key The StatelyDB access key credential
82
+ def initialize(origin:, access_key:)
83
+ super()
84
+ @access_key = access_key
85
+ @channel = Common::Net.new_channel(endpoint: origin)
86
+ error_interceptor = Common::ErrorInterceptor.new
87
+ @stub = Stately::Auth::AuthService::Stub.new(nil, nil, channel_override: @channel,
88
+ interceptors: [error_interceptor])
89
+ end
90
+
91
+ # Fetch a new token from the StatelyDB API
92
+ # @return [TokenResult] The fetched TokenResult
93
+ def fetch
94
+ resp = @stub.get_auth_token(Stately::Auth::GetAuthTokenRequest.new(access_key: @access_key))
95
+ TokenResult.new(token: resp.auth_token, expires_in_secs: resp.expires_in_s)
96
+ end
97
+
98
+ def close
99
+ @channel&.close
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
data/lib/statelydb.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "api/db/service_services_pb"
4
- require "common/auth/auth0_token_provider"
4
+ require "common/auth/auth_token_provider"
5
5
  require "common/auth/interceptor"
6
6
  require "common/net/conn"
7
7
  require "common/error_interceptor"
@@ -30,7 +30,7 @@ module StatelyDB
30
30
  # @param region [String] the region to connect to.
31
31
  def initialize(store_id:,
32
32
  schema:,
33
- token_provider: Common::Auth::Auth0TokenProvider.new,
33
+ token_provider: Common::Auth::AuthTokenProvider.new,
34
34
  endpoint: nil,
35
35
  region: nil)
36
36
  if store_id.nil?
data/sig/statelydb.rbi CHANGED
@@ -213,7 +213,7 @@ module StatelyDB
213
213
  region: T.nilable(String)
214
214
  ).void
215
215
  end
216
- def initialize(store_id:, schema:, token_provider: Common::Auth::Auth0TokenProvider.new, endpoint: nil, region: nil); end
216
+ def initialize(store_id:, schema:, token_provider: Common::Auth::AuthTokenProvider.new, endpoint: nil, region: nil); end
217
217
 
218
218
  # _@return_ — nil
219
219
  sig { void }
@@ -479,7 +479,7 @@ module StatelyDB
479
479
  class Interceptor < GRPC::ClientInterceptor
480
480
  # _@param_ `token_provider` — The token provider to use for authentication
481
481
  sig { params(token_provider: TokenProvider).void }
482
- def initialize(token_provider: Auth0TokenProvider.new); end
482
+ def initialize(token_provider: AuthTokenProvider.new); end
483
483
 
484
484
  # gRPC client unary interceptor
485
485
  #
@@ -572,6 +572,86 @@ module StatelyDB
572
572
  def add_jwt_to_grpc_request(metadata:); end
573
573
  end
574
574
 
575
+ # Result from a token fetch operation
576
+ class TokenResult
577
+ # Create a new TokenResult
578
+ #
579
+ # _@param_ `token` — The access token
580
+ #
581
+ # _@param_ `expires_in_secs` — The number of seconds until the token expires
582
+ sig { params(token: String, expires_in_secs: Integer).void }
583
+ def initialize(token:, expires_in_secs:); end
584
+
585
+ # Returns the value of attribute token.
586
+ sig { returns(T.untyped) }
587
+ attr_reader :token
588
+
589
+ # Returns the value of attribute expires_in_secs.
590
+ sig { returns(T.untyped) }
591
+ attr_reader :expires_in_secs
592
+ end
593
+
594
+ # TokenFetcher is an abstract base class that should be extended
595
+ # for individual token fetcher implementations
596
+ class TokenFetcher
597
+ # Get the current access token
598
+ #
599
+ # _@return_ — The fetched TokenResult
600
+ sig { returns(TokenResult) }
601
+ def fetch; end
602
+
603
+ # Close the token provider and kill any background operations
604
+ sig { returns(T.untyped) }
605
+ def close; end
606
+ end
607
+
608
+ # Auth0TokenFetcher is a TokenFetcher that fetches tokens from an Auth0 server
609
+ class Auth0TokenFetcher < StatelyDB::Common::Auth::TokenFetcher
610
+ # _@param_ `origin` — The origin of the OAuth server
611
+ #
612
+ # _@param_ `audience` — The OAuth Audience for the token
613
+ #
614
+ # _@param_ `client_secret` — The StatelyDB client secret credential
615
+ #
616
+ # _@param_ `client_id` — The StatelyDB client ID credential
617
+ sig do
618
+ params(
619
+ origin: String,
620
+ audience: String,
621
+ client_secret: String,
622
+ client_id: String
623
+ ).void
624
+ end
625
+ def initialize(origin:, audience:, client_secret:, client_id:); end
626
+
627
+ # Fetch a new token from auth0
628
+ #
629
+ # _@return_ — The fetched TokenResult
630
+ sig { returns(TokenResult) }
631
+ def fetch; end
632
+
633
+ sig { returns(T.untyped) }
634
+ def close; end
635
+ end
636
+
637
+ # StatelyAccessTokenFetcher is a TokenFetcher that fetches tokens from the StatelyDB API
638
+ class StatelyAccessTokenFetcher < StatelyDB::Common::Auth::TokenFetcher
639
+ # _@param_ `origin` — The origin of the OAuth server
640
+ #
641
+ # _@param_ `access_key` — The StatelyDB access key credential
642
+ sig { params(origin: String, access_key: String).void }
643
+ def initialize(origin:, access_key:); end
644
+
645
+ # Fetch a new token from the StatelyDB API
646
+ #
647
+ # _@return_ — The fetched TokenResult
648
+ sig { returns(TokenResult) }
649
+ def fetch; end
650
+
651
+ sig { returns(T.untyped) }
652
+ def close; end
653
+ end
654
+
575
655
  # TokenProvider is an abstract base class that should be extended
576
656
  # for individual token provider implementations
577
657
  class TokenProvider
@@ -592,7 +672,7 @@ module StatelyDB
592
672
  # which vends tokens from auth0 with the given client_id and client_secret.
593
673
  # It will default to using the values of `STATELY_CLIENT_ID` and `STATELY_CLIENT_SECRET` if
594
674
  # no credentials are explicitly passed and will throw an error if none are found.
595
- class Auth0TokenProvider < StatelyDB::Common::Auth::TokenProvider
675
+ class AuthTokenProvider < StatelyDB::Common::Auth::TokenProvider
596
676
  # _@param_ `origin` — The origin of the OAuth server
597
677
  #
598
678
  # _@param_ `audience` — The OAuth Audience for the token
@@ -600,15 +680,18 @@ module StatelyDB
600
680
  # _@param_ `client_secret` — The StatelyDB client secret credential
601
681
  #
602
682
  # _@param_ `client_id` — The StatelyDB client ID credential
683
+ #
684
+ # _@param_ `access_key` — The StatelyDB access key credential
603
685
  sig do
604
686
  params(
605
687
  origin: String,
606
688
  audience: String,
607
689
  client_secret: String,
608
- client_id: String
690
+ client_id: String,
691
+ access_key: String
609
692
  ).void
610
693
  end
611
- def initialize(origin: "https://oauth.stately.cloud", audience: "api.stately.cloud", client_secret: ENV.fetch("STATELY_CLIENT_SECRET"), client_id: ENV.fetch("STATELY_CLIENT_ID")); end
694
+ def initialize(origin: "https://oauth.stately.cloud", audience: "api.stately.cloud", client_secret: ENV.fetch("STATELY_CLIENT_SECRET", nil), client_id: ENV.fetch("STATELY_CLIENT_ID", nil), access_key: ENV.fetch("STATELY_ACCESS_KEY", nil)); end
612
695
 
613
696
  # Close the token provider and kill any background operations
614
697
  # This just invokes the close method on the actor which should do the cleanup
@@ -636,10 +719,11 @@ module StatelyDB
636
719
  origin: String,
637
720
  audience: String,
638
721
  client_secret: String,
639
- client_id: String
722
+ client_id: String,
723
+ access_key: T.untyped
640
724
  ).void
641
725
  end
642
- def initialize(origin:, audience:, client_secret:, client_id:); end
726
+ def initialize(origin:, audience:, client_secret:, client_id:, access_key:); end
643
727
 
644
728
  # Initialize the actor. This runs on the actor thread which means
645
729
  # we can dispatch async operations here.
@@ -675,9 +759,25 @@ module StatelyDB
675
759
  # _@return_ — The new access token
676
760
  sig { returns(String) }
677
761
  def refresh_token_impl; end
762
+ end
763
+
764
+ # Persistent state for the token provider
765
+ class TokenState
766
+ # Create a new TokenState
767
+ #
768
+ # _@param_ `token` — The access token
769
+ #
770
+ # _@param_ `expires_at_unix_secs` — The unix timestamp when the token expires
771
+ sig { params(token: String, expires_at_unix_secs: Integer).void }
772
+ def initialize(token:, expires_at_unix_secs:); end
773
+
774
+ # Returns the value of attribute token.
775
+ sig { returns(T.untyped) }
776
+ attr_reader :token
678
777
 
778
+ # Returns the value of attribute expires_at_unix_secs.
679
779
  sig { returns(T.untyped) }
680
- def make_auth0_request; end
780
+ attr_reader :expires_at_unix_secs
681
781
  end
682
782
  end
683
783
  end
@@ -1069,6 +1169,22 @@ module Stately
1069
1169
  end
1070
1170
  end
1071
1171
 
1172
+ module Auth
1173
+ GetAuthTokenRequest = T.let(::Google::Protobuf::DescriptorPool.generated_pool.lookup("stately.auth.GetAuthTokenRequest").msgclass, T.untyped)
1174
+ GetAuthTokenResponse = T.let(::Google::Protobuf::DescriptorPool.generated_pool.lookup("stately.auth.GetAuthTokenResponse").msgclass, T.untyped)
1175
+
1176
+ module AuthService
1177
+ Stub = T.let(Service.rpc_stub_class, T.untyped)
1178
+
1179
+ # AuthService is the service for vending access tokens used to connect to
1180
+ # StatelyDB. This API is meant to be used from SDKs. Access Keys are created
1181
+ # and managed from the stately.dbmanagement.UserService.
1182
+ class Service
1183
+ include GRPC::GenericService
1184
+ end
1185
+ end
1186
+ end
1187
+
1072
1188
  module Errors
1073
1189
  StatelyErrorDetails = T.let(::Google::Protobuf::DescriptorPool.generated_pool.lookup("stately.errors.StatelyErrorDetails").msgclass, T.untyped)
1074
1190
  end
data/sig/statelydb.rbs CHANGED
@@ -496,6 +496,73 @@ module StatelyDB
496
496
  def add_jwt_to_grpc_request: (metadata: ::Hash[untyped, untyped]) -> void
497
497
  end
498
498
 
499
+ # Result from a token fetch operation
500
+ class TokenResult
501
+ # Create a new TokenResult
502
+ #
503
+ # _@param_ `token` — The access token
504
+ #
505
+ # _@param_ `expires_in_secs` — The number of seconds until the token expires
506
+ def initialize: (token: String, expires_in_secs: Integer) -> void
507
+
508
+ # Returns the value of attribute token.
509
+ attr_reader token: untyped
510
+
511
+ # Returns the value of attribute expires_in_secs.
512
+ attr_reader expires_in_secs: untyped
513
+ end
514
+
515
+ # TokenFetcher is an abstract base class that should be extended
516
+ # for individual token fetcher implementations
517
+ class TokenFetcher
518
+ # Get the current access token
519
+ #
520
+ # _@return_ — The fetched TokenResult
521
+ def fetch: () -> TokenResult
522
+
523
+ # Close the token provider and kill any background operations
524
+ def close: () -> untyped
525
+ end
526
+
527
+ # Auth0TokenFetcher is a TokenFetcher that fetches tokens from an Auth0 server
528
+ class Auth0TokenFetcher < StatelyDB::Common::Auth::TokenFetcher
529
+ # _@param_ `origin` — The origin of the OAuth server
530
+ #
531
+ # _@param_ `audience` — The OAuth Audience for the token
532
+ #
533
+ # _@param_ `client_secret` — The StatelyDB client secret credential
534
+ #
535
+ # _@param_ `client_id` — The StatelyDB client ID credential
536
+ def initialize: (
537
+ origin: String,
538
+ audience: String,
539
+ client_secret: String,
540
+ client_id: String
541
+ ) -> void
542
+
543
+ # Fetch a new token from auth0
544
+ #
545
+ # _@return_ — The fetched TokenResult
546
+ def fetch: () -> TokenResult
547
+
548
+ def close: () -> untyped
549
+ end
550
+
551
+ # StatelyAccessTokenFetcher is a TokenFetcher that fetches tokens from the StatelyDB API
552
+ class StatelyAccessTokenFetcher < StatelyDB::Common::Auth::TokenFetcher
553
+ # _@param_ `origin` — The origin of the OAuth server
554
+ #
555
+ # _@param_ `access_key` — The StatelyDB access key credential
556
+ def initialize: (origin: String, access_key: String) -> void
557
+
558
+ # Fetch a new token from the StatelyDB API
559
+ #
560
+ # _@return_ — The fetched TokenResult
561
+ def fetch: () -> TokenResult
562
+
563
+ def close: () -> untyped
564
+ end
565
+
499
566
  # TokenProvider is an abstract base class that should be extended
500
567
  # for individual token provider implementations
501
568
  class TokenProvider
@@ -514,7 +581,7 @@ module StatelyDB
514
581
  # which vends tokens from auth0 with the given client_id and client_secret.
515
582
  # It will default to using the values of `STATELY_CLIENT_ID` and `STATELY_CLIENT_SECRET` if
516
583
  # no credentials are explicitly passed and will throw an error if none are found.
517
- class Auth0TokenProvider < StatelyDB::Common::Auth::TokenProvider
584
+ class AuthTokenProvider < StatelyDB::Common::Auth::TokenProvider
518
585
  # _@param_ `origin` — The origin of the OAuth server
519
586
  #
520
587
  # _@param_ `audience` — The OAuth Audience for the token
@@ -522,11 +589,14 @@ module StatelyDB
522
589
  # _@param_ `client_secret` — The StatelyDB client secret credential
523
590
  #
524
591
  # _@param_ `client_id` — The StatelyDB client ID credential
592
+ #
593
+ # _@param_ `access_key` — The StatelyDB access key credential
525
594
  def initialize: (
526
595
  ?origin: String,
527
596
  ?audience: String,
528
597
  ?client_secret: String,
529
- ?client_id: String
598
+ ?client_id: String,
599
+ ?access_key: String
530
600
  ) -> void
531
601
 
532
602
  # Close the token provider and kill any background operations
@@ -552,7 +622,8 @@ module StatelyDB
552
622
  origin: String,
553
623
  audience: String,
554
624
  client_secret: String,
555
- client_id: String
625
+ client_id: String,
626
+ access_key: untyped
556
627
  ) -> void
557
628
 
558
629
  # Initialize the actor. This runs on the actor thread which means
@@ -583,8 +654,22 @@ module StatelyDB
583
654
  #
584
655
  # _@return_ — The new access token
585
656
  def refresh_token_impl: () -> String
657
+ end
586
658
 
587
- def make_auth0_request: () -> untyped
659
+ # Persistent state for the token provider
660
+ class TokenState
661
+ # Create a new TokenState
662
+ #
663
+ # _@param_ `token` — The access token
664
+ #
665
+ # _@param_ `expires_at_unix_secs` — The unix timestamp when the token expires
666
+ def initialize: (token: String, expires_at_unix_secs: Integer) -> void
667
+
668
+ # Returns the value of attribute token.
669
+ attr_reader token: untyped
670
+
671
+ # Returns the value of attribute expires_at_unix_secs.
672
+ attr_reader expires_at_unix_secs: untyped
588
673
  end
589
674
  end
590
675
  end
@@ -936,6 +1021,22 @@ module Stately
936
1021
  end
937
1022
  end
938
1023
 
1024
+ module Auth
1025
+ GetAuthTokenRequest: untyped
1026
+ GetAuthTokenResponse: untyped
1027
+
1028
+ module AuthService
1029
+ Stub: untyped
1030
+
1031
+ # AuthService is the service for vending access tokens used to connect to
1032
+ # StatelyDB. This API is meant to be used from SDKs. Access Keys are created
1033
+ # and managed from the stately.dbmanagement.UserService.
1034
+ class Service
1035
+ include GRPC::GenericService
1036
+ end
1037
+ end
1038
+ end
1039
+
939
1040
  module Errors
940
1041
  StatelyErrorDetails: untyped
941
1042
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: statelydb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.0
4
+ version: 0.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stately Cloud, Inc.
@@ -73,6 +73,9 @@ extensions: []
73
73
  extra_rdoc_files: []
74
74
  files:
75
75
  - README.md
76
+ - lib/api/auth/get_auth_token_pb.rb
77
+ - lib/api/auth/service_pb.rb
78
+ - lib/api/auth/service_services_pb.rb
76
79
  - lib/api/db/continue_list_pb.rb
77
80
  - lib/api/db/delete_pb.rb
78
81
  - lib/api/db/get_pb.rb
@@ -87,8 +90,9 @@ files:
87
90
  - lib/api/db/sync_list_pb.rb
88
91
  - lib/api/db/transaction_pb.rb
89
92
  - lib/api/errors/error_details_pb.rb
90
- - lib/common/auth/auth0_token_provider.rb
93
+ - lib/common/auth/auth_token_provider.rb
91
94
  - lib/common/auth/interceptor.rb
95
+ - lib/common/auth/token_fetcher.rb
92
96
  - lib/common/auth/token_provider.rb
93
97
  - lib/common/error_interceptor.rb
94
98
  - lib/common/net/conn.rb