@cubist-labs/cubesigner-sdk 0.1.26 → 0.1.77
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.
- package/README.md +94 -33
- package/dist/src/ethers/index.d.ts +25 -5
- package/dist/src/ethers/index.js +58 -16
- package/dist/src/fido.d.ts +76 -0
- package/dist/src/fido.js +148 -0
- package/dist/src/index.d.ts +148 -35
- package/dist/src/index.js +320 -53
- package/dist/src/key.d.ts +64 -8
- package/dist/src/key.js +91 -19
- package/dist/src/org.d.ts +98 -9
- package/dist/src/org.js +144 -29
- package/dist/src/paginator.d.ts +76 -0
- package/dist/src/paginator.js +99 -0
- package/dist/src/role.d.ts +20 -8
- package/dist/src/role.js +7 -5
- package/dist/src/schema.d.ts +2395 -393
- package/dist/src/schema.js +1 -1
- package/dist/src/session/cognito_manager.d.ts +59 -0
- package/dist/src/session/cognito_manager.js +111 -0
- package/dist/src/session/session_manager.d.ts +15 -0
- package/dist/src/session/session_manager.js +21 -2
- package/dist/src/session/session_storage.js +1 -1
- package/dist/src/session/signer_session_manager.d.ts +24 -12
- package/dist/src/session/signer_session_manager.js +45 -20
- package/dist/src/signer_session.d.ts +136 -38
- package/dist/src/signer_session.js +187 -80
- package/dist/src/util.d.ts +20 -0
- package/dist/src/util.js +31 -2
- package/package.json +12 -7
- package/src/ethers/index.ts +88 -16
- package/src/fido.ts +166 -0
- package/src/index.ts +366 -77
- package/src/key.ts +112 -16
- package/src/org.ts +200 -37
- package/src/paginator.ts +122 -0
- package/src/role.ts +24 -11
- package/src/schema.ts +2458 -449
- package/src/session/{management_session_manager.ts → cognito_manager.ts} +13 -15
- package/src/session/session_manager.ts +25 -1
- package/src/session/session_storage.ts +1 -1
- package/src/session/signer_session_manager.ts +57 -27
- package/src/signer_session.ts +266 -89
- package/src/util.ts +41 -0
- package/src/session/oidc_session_manager.ts +0 -193
package/src/key.ts
CHANGED
|
@@ -7,10 +7,12 @@ export enum Secp256k1 {
|
|
|
7
7
|
Evm = "SecpEthAddr", // eslint-disable-line no-unused-vars
|
|
8
8
|
Btc = "SecpBtc", // eslint-disable-line no-unused-vars
|
|
9
9
|
BtcTest = "SecpBtcTest", // eslint-disable-line no-unused-vars
|
|
10
|
+
Ava = "SecpAvaAddr", // eslint-disable-line no-unused-vars
|
|
11
|
+
AvaTest = "SecpAvaTestAddr", // eslint-disable-line no-unused-vars
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
/** BLS key type */
|
|
13
|
-
export enum
|
|
15
|
+
export enum Bls {
|
|
14
16
|
Eth2Deposited = "BlsPub", // eslint-disable-line no-unused-vars
|
|
15
17
|
Eth2Inactive = "BlsInactive", // eslint-disable-line no-unused-vars
|
|
16
18
|
}
|
|
@@ -20,16 +22,56 @@ export enum Ed25519 {
|
|
|
20
22
|
Solana = "Ed25519SolanaAddr", // eslint-disable-line no-unused-vars
|
|
21
23
|
Sui = "Ed25519SuiAddr", // eslint-disable-line no-unused-vars
|
|
22
24
|
Aptos = "Ed25519AptosAddr", // eslint-disable-line no-unused-vars
|
|
25
|
+
Cardano = "Ed25519CardanoAddrVk", // eslint-disable-line no-unused-vars
|
|
26
|
+
Stellar = "Ed25519StellarAddr", // eslint-disable-line no-unused-vars
|
|
23
27
|
}
|
|
24
28
|
|
|
29
|
+
/** Mnemonic key type */
|
|
30
|
+
export const Mnemonic = "Mnemonic" as const;
|
|
31
|
+
export type Mnemonic = typeof Mnemonic;
|
|
32
|
+
|
|
33
|
+
/** Stark key type */
|
|
34
|
+
export const Stark = "Stark" as const;
|
|
35
|
+
export type Stark = typeof Stark;
|
|
36
|
+
|
|
25
37
|
/** Key type */
|
|
26
|
-
export type KeyType = Secp256k1 |
|
|
38
|
+
export type KeyType = Secp256k1 | Bls | Ed25519 | Mnemonic | Stark;
|
|
27
39
|
|
|
28
40
|
/** Schema key type (i.e., key type at the API level) */
|
|
29
41
|
type SchemaKeyType = components["schemas"]["KeyType"];
|
|
30
42
|
|
|
31
43
|
type UpdateKeyRequest = components["schemas"]["UpdateKeyRequest"];
|
|
32
|
-
type
|
|
44
|
+
type KeyInfoApi = components["schemas"]["KeyInfo"];
|
|
45
|
+
type KeyTypeApi = components["schemas"]["KeyType"];
|
|
46
|
+
|
|
47
|
+
/** Additional properties (for backward compatibility) */
|
|
48
|
+
export interface KeyInfo extends KeyInfoApi {
|
|
49
|
+
/** Alias for key_id */
|
|
50
|
+
id: string;
|
|
51
|
+
/** Alias for key_type */
|
|
52
|
+
type: KeyTypeApi;
|
|
53
|
+
/** Alias for material_id */
|
|
54
|
+
materialId: string;
|
|
55
|
+
/** Alias for public_key */
|
|
56
|
+
publicKey: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Define some additional (backward compatibility) properties
|
|
61
|
+
* on a `KeyInfoApi` object returned from the remote end.
|
|
62
|
+
*
|
|
63
|
+
* @param {KeyInfoApi} key Key information returned from the remote end
|
|
64
|
+
* @return {KeyInfo} The same `key` object extended with some derived properties.
|
|
65
|
+
*/
|
|
66
|
+
export function toKeyInfo(key: KeyInfoApi): KeyInfo {
|
|
67
|
+
return {
|
|
68
|
+
...key,
|
|
69
|
+
id: key.key_id,
|
|
70
|
+
type: key.key_type,
|
|
71
|
+
publicKey: key.public_key,
|
|
72
|
+
materialId: key.material_id,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
33
75
|
|
|
34
76
|
/** Signing keys. */
|
|
35
77
|
export class Key {
|
|
@@ -44,9 +86,6 @@ export class Key {
|
|
|
44
86
|
* */
|
|
45
87
|
readonly id: string;
|
|
46
88
|
|
|
47
|
-
/** The type of key. */
|
|
48
|
-
readonly type: KeyType;
|
|
49
|
-
|
|
50
89
|
/**
|
|
51
90
|
* A unique identifier specific to the type of key, such as a public key or an ethereum address
|
|
52
91
|
* @example 0x8e3484687e66cdd26cf04c3647633ab4f3570148
|
|
@@ -61,6 +100,12 @@ export class Key {
|
|
|
61
100
|
* */
|
|
62
101
|
readonly publicKey: string;
|
|
63
102
|
|
|
103
|
+
/** The type of key. */
|
|
104
|
+
async type(): Promise<KeyType> {
|
|
105
|
+
const data = await this.fetch();
|
|
106
|
+
return fromSchemaKeyType(data.key_type);
|
|
107
|
+
}
|
|
108
|
+
|
|
64
109
|
/** Is the key enabled? */
|
|
65
110
|
async enabled(): Promise<boolean> {
|
|
66
111
|
const data = await this.fetch();
|
|
@@ -119,6 +164,13 @@ export class Key {
|
|
|
119
164
|
await this.update({ owner });
|
|
120
165
|
}
|
|
121
166
|
|
|
167
|
+
/**
|
|
168
|
+
* Delete this key.
|
|
169
|
+
*/
|
|
170
|
+
async delete() {
|
|
171
|
+
await this.#cs.deleteKey(this.orgId, this.id);
|
|
172
|
+
}
|
|
173
|
+
|
|
122
174
|
// --------------------------------------------------------------------------
|
|
123
175
|
// -- INTERNAL --------------------------------------------------------------
|
|
124
176
|
// --------------------------------------------------------------------------
|
|
@@ -129,11 +181,10 @@ export class Key {
|
|
|
129
181
|
* @param {KeyInfo} data The JSON response from the API server.
|
|
130
182
|
* @internal
|
|
131
183
|
* */
|
|
132
|
-
constructor(cs: CubeSigner, orgId: string, data:
|
|
184
|
+
constructor(cs: CubeSigner, orgId: string, data: KeyInfoApi) {
|
|
133
185
|
this.#cs = cs;
|
|
134
186
|
this.orgId = orgId;
|
|
135
187
|
this.id = data.key_id;
|
|
136
|
-
this.type = fromSchemaKeyType(data.key_type);
|
|
137
188
|
this.materialId = data.material_id;
|
|
138
189
|
this.publicKey = data.public_key;
|
|
139
190
|
}
|
|
@@ -150,7 +201,7 @@ export class Key {
|
|
|
150
201
|
body: request,
|
|
151
202
|
parseAs: "json",
|
|
152
203
|
});
|
|
153
|
-
return assertOk(resp);
|
|
204
|
+
return toKeyInfo(assertOk(resp));
|
|
154
205
|
}
|
|
155
206
|
|
|
156
207
|
/** Create new signing keys.
|
|
@@ -183,7 +234,42 @@ export class Key {
|
|
|
183
234
|
parseAs: "json",
|
|
184
235
|
});
|
|
185
236
|
const data = assertOk(resp);
|
|
186
|
-
return data.keys.map((k
|
|
237
|
+
return data.keys.map((k) => new Key(cs, orgId, k));
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Derives a key of a specified type using a supplied derivation path and an existing long-lived mnemonic.
|
|
242
|
+
*
|
|
243
|
+
* The owner of the derived key will be the owner of the mnemonic.
|
|
244
|
+
*
|
|
245
|
+
* @param {CubeSigner} cs The CubeSigner instance to use for key creation.
|
|
246
|
+
* @param {string} orgId The id of the organization to which the key belongs.
|
|
247
|
+
* @param {KeyType} keyType The type of key to create.
|
|
248
|
+
* @param {string[]} derivationPaths Derivation paths from which to derive new keys.
|
|
249
|
+
* @param {string} mnemonicId materialId of mnemonic key used to derive the new key.
|
|
250
|
+
*
|
|
251
|
+
* @return {Key[]} The newly derived keys.
|
|
252
|
+
*/
|
|
253
|
+
static async deriveKeys(
|
|
254
|
+
cs: CubeSigner,
|
|
255
|
+
orgId: string,
|
|
256
|
+
keyType: KeyType,
|
|
257
|
+
derivationPaths: string[],
|
|
258
|
+
mnemonicId: string,
|
|
259
|
+
): Promise<Key[]> {
|
|
260
|
+
const resp = await (
|
|
261
|
+
await cs.management()
|
|
262
|
+
).put("/v0/org/{org_id}/derive_key", {
|
|
263
|
+
params: { path: { org_id: orgId } },
|
|
264
|
+
body: {
|
|
265
|
+
derivation_path: derivationPaths,
|
|
266
|
+
mnemonic_id: mnemonicId,
|
|
267
|
+
key_type: keyType,
|
|
268
|
+
},
|
|
269
|
+
parseAs: "json",
|
|
270
|
+
});
|
|
271
|
+
const data = assertOk(resp);
|
|
272
|
+
return data.keys.map((k) => new Key(cs, orgId, k));
|
|
187
273
|
}
|
|
188
274
|
|
|
189
275
|
/** Get a key by id.
|
|
@@ -216,7 +302,7 @@ export class Key {
|
|
|
216
302
|
parseAs: "json",
|
|
217
303
|
});
|
|
218
304
|
const data = assertOk(resp);
|
|
219
|
-
return data;
|
|
305
|
+
return toKeyInfo(data);
|
|
220
306
|
}
|
|
221
307
|
}
|
|
222
308
|
|
|
@@ -225,7 +311,7 @@ export class Key {
|
|
|
225
311
|
* @return {KeyType} The key type.
|
|
226
312
|
* @internal
|
|
227
313
|
* */
|
|
228
|
-
function fromSchemaKeyType(ty: SchemaKeyType): KeyType {
|
|
314
|
+
export function fromSchemaKeyType(ty: SchemaKeyType): KeyType {
|
|
229
315
|
switch (ty) {
|
|
230
316
|
case "SecpEthAddr":
|
|
231
317
|
return Secp256k1.Evm;
|
|
@@ -233,17 +319,27 @@ function fromSchemaKeyType(ty: SchemaKeyType): KeyType {
|
|
|
233
319
|
return Secp256k1.Btc;
|
|
234
320
|
case "SecpBtcTest":
|
|
235
321
|
return Secp256k1.BtcTest;
|
|
322
|
+
case "SecpAvaAddr":
|
|
323
|
+
return Secp256k1.Ava;
|
|
324
|
+
case "SecpAvaTestAddr":
|
|
325
|
+
return Secp256k1.AvaTest;
|
|
236
326
|
case "BlsPub":
|
|
237
|
-
return
|
|
327
|
+
return Bls.Eth2Deposited;
|
|
238
328
|
case "BlsInactive":
|
|
239
|
-
return
|
|
329
|
+
return Bls.Eth2Inactive;
|
|
240
330
|
case "Ed25519SolanaAddr":
|
|
241
331
|
return Ed25519.Solana;
|
|
242
332
|
case "Ed25519SuiAddr":
|
|
243
333
|
return Ed25519.Sui;
|
|
244
334
|
case "Ed25519AptosAddr":
|
|
245
335
|
return Ed25519.Aptos;
|
|
246
|
-
|
|
247
|
-
|
|
336
|
+
case "Ed25519CardanoAddrVk":
|
|
337
|
+
return Ed25519.Cardano;
|
|
338
|
+
case "Ed25519StellarAddr":
|
|
339
|
+
return Ed25519.Stellar;
|
|
340
|
+
case "Stark":
|
|
341
|
+
return Stark;
|
|
342
|
+
case "Mnemonic":
|
|
343
|
+
return Mnemonic;
|
|
248
344
|
}
|
|
249
345
|
}
|
package/src/org.ts
CHANGED
|
@@ -1,14 +1,34 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
CubeSigner,
|
|
3
|
+
MfaRequestInfo,
|
|
4
|
+
IdentityProof,
|
|
5
|
+
PageOpts,
|
|
6
|
+
Page,
|
|
7
|
+
PageQueryArgs,
|
|
8
|
+
Paginator,
|
|
9
|
+
} from ".";
|
|
2
10
|
import { components, paths } from "./client";
|
|
3
11
|
import { assertOk } from "./util";
|
|
4
12
|
import { KeyType, Key } from "./key";
|
|
5
|
-
import { Role, RoleInfo } from "./role";
|
|
13
|
+
import { MfaPolicy, Role, RoleInfo } from "./role";
|
|
6
14
|
|
|
7
15
|
/** Organization id */
|
|
8
16
|
export type OrgId = string;
|
|
9
17
|
|
|
10
18
|
/** Org-wide policy */
|
|
11
|
-
export type OrgPolicy =
|
|
19
|
+
export type OrgPolicy =
|
|
20
|
+
| SourceIpAllowlistPolicy
|
|
21
|
+
| OidcAuthSourcesPolicy
|
|
22
|
+
| OriginAllowlistPolicy
|
|
23
|
+
| MaxDailyUnstakePolicy;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Provides an allowlist of OIDC Issuers and audiences that are allowed to authenticate into this org.
|
|
27
|
+
* @example {"OidcAuthSources": { "https://accounts.google.com": [ "1234.apps.googleusercontent.com" ]}}
|
|
28
|
+
*/
|
|
29
|
+
export interface OidcAuthSourcesPolicy {
|
|
30
|
+
OidcAuthSources: Record<string, string[]>;
|
|
31
|
+
}
|
|
12
32
|
|
|
13
33
|
/**
|
|
14
34
|
* Only allow requests from the specified origins.
|
|
@@ -44,6 +64,14 @@ type UpdateOrgResponse =
|
|
|
44
64
|
export type OidcIdentity = components["schemas"]["OIDCIdentity"];
|
|
45
65
|
export type MemberRole = components["schemas"]["MemberRole"];
|
|
46
66
|
|
|
67
|
+
/** Options for a new OIDC user */
|
|
68
|
+
export interface CreateOidcUserOptions {
|
|
69
|
+
/** The role of an OIDC user, default is "Alien" */
|
|
70
|
+
memberRole?: MemberRole;
|
|
71
|
+
/** Optional MFA policy to associate with the user account */
|
|
72
|
+
mfaPolicy?: MfaPolicy;
|
|
73
|
+
}
|
|
74
|
+
|
|
47
75
|
/** An organization. */
|
|
48
76
|
export class Org {
|
|
49
77
|
readonly #cs: CubeSigner;
|
|
@@ -127,6 +155,35 @@ export class Org {
|
|
|
127
155
|
return Key.createKeys(this.#cs, this.id, type, count, ownerId);
|
|
128
156
|
}
|
|
129
157
|
|
|
158
|
+
/**
|
|
159
|
+
* Derives a key of the given type using the given derivation path and mnemonic.
|
|
160
|
+
* The owner of the derived key will be the owner of the mnemonic.
|
|
161
|
+
*
|
|
162
|
+
* @param {KeyType} type Type of key to derive from the mnemonic.
|
|
163
|
+
* @param {string} derivationPath Mnemonic derivation path used to generate new key.
|
|
164
|
+
* @param {string} mnemonicId materialId of mnemonic key used to derive the new key.
|
|
165
|
+
*
|
|
166
|
+
* @return {Key} newly derived key.
|
|
167
|
+
*/
|
|
168
|
+
async deriveKey(type: KeyType, derivationPath: string, mnemonicId: string): Promise<Key> {
|
|
169
|
+
return (await Key.deriveKeys(this.#cs, this.id, type, [derivationPath], mnemonicId))[0];
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Derives a set of keys of the given type using the given derivation paths and mnemonic.
|
|
174
|
+
*
|
|
175
|
+
* The owner of the derived keys will be the owner of the mnemonic.
|
|
176
|
+
*
|
|
177
|
+
* @param {KeyType} type Type of key to derive from the mnemonic.
|
|
178
|
+
* @param {string[]} derivationPaths Mnemonic derivation paths used to generate new key.
|
|
179
|
+
* @param {string} mnemonicId materialId of mnemonic key used to derive the new key.
|
|
180
|
+
*
|
|
181
|
+
* @return {Key[]} newly derived keys.
|
|
182
|
+
*/
|
|
183
|
+
async deriveKeys(type: KeyType, derivationPaths: string[], mnemonicId: string): Promise<Key[]> {
|
|
184
|
+
return await Key.deriveKeys(this.#cs, this.#id, type, derivationPaths, mnemonicId);
|
|
185
|
+
}
|
|
186
|
+
|
|
130
187
|
/**
|
|
131
188
|
* Create a new user in the organization and sends an invitation to that user
|
|
132
189
|
* @param {string} email Email of the user
|
|
@@ -150,23 +207,54 @@ export class Org {
|
|
|
150
207
|
/**
|
|
151
208
|
* Create a new OIDC user
|
|
152
209
|
* @param {OidcIdentity} identity The identity of the OIDC user
|
|
153
|
-
* @param {
|
|
210
|
+
* @param {string} email Email of the OIDC user
|
|
211
|
+
* @param {CreateOidcUserOptions} opts Additional options for new OIDC users
|
|
154
212
|
* @return {string} User id of the new user
|
|
155
213
|
*/
|
|
156
|
-
async createOidcUser(
|
|
214
|
+
async createOidcUser(
|
|
215
|
+
identity: OidcIdentity,
|
|
216
|
+
email: string,
|
|
217
|
+
opts: CreateOidcUserOptions = {},
|
|
218
|
+
): Promise<string> {
|
|
157
219
|
const resp = await (
|
|
158
220
|
await this.#cs.management()
|
|
159
221
|
).post("/v0/org/{org_id}/users", {
|
|
160
222
|
params: { path: { org_id: this.id } },
|
|
161
223
|
body: {
|
|
162
224
|
identity,
|
|
163
|
-
role: memberRole,
|
|
225
|
+
role: opts.memberRole ?? "Alien",
|
|
226
|
+
email: email,
|
|
227
|
+
mfa_policy: opts.mfaPolicy ?? null,
|
|
164
228
|
},
|
|
165
229
|
parseAs: "json",
|
|
166
230
|
});
|
|
167
231
|
return assertOk(resp).user_id;
|
|
168
232
|
}
|
|
169
233
|
|
|
234
|
+
/**
|
|
235
|
+
* Delete an existing OIDC user
|
|
236
|
+
* @param {OidcIdentity} identity The identity of the OIDC user
|
|
237
|
+
*/
|
|
238
|
+
async deleteOidcUser(identity: OidcIdentity) {
|
|
239
|
+
const resp = await (
|
|
240
|
+
await this.#cs.management()
|
|
241
|
+
).del("/v0/org/{org_id}/users/oidc", {
|
|
242
|
+
params: { path: { org_id: this.id } },
|
|
243
|
+
body: identity,
|
|
244
|
+
parseAs: "json",
|
|
245
|
+
});
|
|
246
|
+
return assertOk(resp);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Checks if a given proof of OIDC authentication is valid.
|
|
251
|
+
*
|
|
252
|
+
* @param {IdentityProof} proof The proof of authentication.
|
|
253
|
+
*/
|
|
254
|
+
async verifyIdentity(proof: IdentityProof) {
|
|
255
|
+
await this.#cs.verifyIdentity(this.id, proof);
|
|
256
|
+
}
|
|
257
|
+
|
|
170
258
|
/**
|
|
171
259
|
* List users in the organization
|
|
172
260
|
* @return {UserIdInfo[]} List of users
|
|
@@ -191,20 +279,33 @@ export class Org {
|
|
|
191
279
|
|
|
192
280
|
/** Get all keys in the org.
|
|
193
281
|
* @param {KeyType?} type Optional key type to filter list for.
|
|
282
|
+
* @param {PageOpts} page Pagination options. Defaults to fetching the entire result set.
|
|
194
283
|
* @return {Key} The key.
|
|
195
284
|
* */
|
|
196
|
-
async keys(type?: KeyType): Promise<Key[]> {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
285
|
+
async keys(type?: KeyType, page?: PageOpts): Promise<Key[]> {
|
|
286
|
+
page ??= Page.default();
|
|
287
|
+
const listFn = async (query: PageQueryArgs) => {
|
|
288
|
+
const client = await this.#cs.management();
|
|
289
|
+
const resp = await client.get("/v0/org/{org_id}/keys", {
|
|
290
|
+
params: {
|
|
291
|
+
path: { org_id: this.id },
|
|
292
|
+
query: {
|
|
293
|
+
key_type: type,
|
|
294
|
+
...query,
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
parseAs: "json",
|
|
298
|
+
});
|
|
299
|
+
return assertOk(resp);
|
|
300
|
+
};
|
|
301
|
+
const p = new Paginator(
|
|
302
|
+
page,
|
|
303
|
+
listFn,
|
|
304
|
+
(r) => r.keys,
|
|
305
|
+
(r) => r.last_evaluated_key,
|
|
306
|
+
);
|
|
307
|
+
const keys = await p.fetch();
|
|
308
|
+
return keys.map((k) => new Key(this.#cs, this.id, k));
|
|
208
309
|
}
|
|
209
310
|
|
|
210
311
|
/** Create a new role.
|
|
@@ -223,25 +324,32 @@ export class Org {
|
|
|
223
324
|
return Role.getRole(this.#cs, this.id, roleId);
|
|
224
325
|
}
|
|
225
326
|
|
|
226
|
-
/**
|
|
327
|
+
/**
|
|
328
|
+
* List all roles in the org.
|
|
329
|
+
*
|
|
330
|
+
* @param {PageOpts} page Pagination options. Defaults to fetching the entire result set.
|
|
227
331
|
* @return {Role[]} The roles.
|
|
228
332
|
* */
|
|
229
|
-
async
|
|
230
|
-
return Org.roles(this.#cs, this.id);
|
|
333
|
+
async listRoles(page?: PageOpts): Promise<Role[]> {
|
|
334
|
+
return Org.roles(this.#cs, this.id, page);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/** List all users in the org.
|
|
338
|
+
* @return {User[]} The users.
|
|
339
|
+
* */
|
|
340
|
+
async listUsers(): Promise<UserIdInfo[]> {
|
|
341
|
+
return Org.users(this.#cs, this.id);
|
|
231
342
|
}
|
|
232
343
|
|
|
233
344
|
/**
|
|
234
345
|
* Get a pending MFA request by its id.
|
|
235
346
|
* @param {string} mfaId The id of the MFA request.
|
|
236
347
|
* @return {Promise<MfaRequestInfo>} The MFA request.
|
|
348
|
+
*
|
|
349
|
+
* @deprecated Use {@link getMfaInfo()} instead.
|
|
237
350
|
*/
|
|
238
351
|
async mfaGet(mfaId: string): Promise<MfaRequestInfo> {
|
|
239
|
-
|
|
240
|
-
await this.#cs.management()
|
|
241
|
-
).get("/v0/org/{org_id}/mfa/{mfa_id}", {
|
|
242
|
-
params: { path: { org_id: this.#id, mfa_id: mfaId } },
|
|
243
|
-
});
|
|
244
|
-
return assertOk(resp);
|
|
352
|
+
return await this.getMfaInfo(mfaId);
|
|
245
353
|
}
|
|
246
354
|
|
|
247
355
|
/**
|
|
@@ -249,8 +357,37 @@ export class Org {
|
|
|
249
357
|
*
|
|
250
358
|
* @param {string} mfaId The id of the MFA request.
|
|
251
359
|
* @return {Promise<MfaRequestInfo>} The MFA request.
|
|
360
|
+
*
|
|
361
|
+
* @deprecated Use {@link approveMfaRequest()} instead.
|
|
252
362
|
*/
|
|
253
363
|
async mfaApprove(mfaId: string): Promise<MfaRequestInfo> {
|
|
364
|
+
return await this.approveMfaRequest(mfaId);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Get a pending MFA request by its id.
|
|
369
|
+
* @param {string} mfaId The id of the MFA request.
|
|
370
|
+
* @return {Promise<MfaRequestInfo>} The MFA request.
|
|
371
|
+
*/
|
|
372
|
+
async getMfaInfo(mfaId: string): Promise<MfaRequestInfo> {
|
|
373
|
+
return await this.#cs.mfaGet(this.id, mfaId);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* List pending MFA requests accessible to the current user.
|
|
378
|
+
* @return {Promise<MfaRequestInfo[]>} The MFA requests.
|
|
379
|
+
*/
|
|
380
|
+
async listMfaInfos(): Promise<MfaRequestInfo[]> {
|
|
381
|
+
return await this.#cs.mfaList(this.id);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Approve a pending MFA request.
|
|
386
|
+
*
|
|
387
|
+
* @param {string} mfaId The id of the MFA request.
|
|
388
|
+
* @return {Promise<MfaRequestInfo>} The MFA request.
|
|
389
|
+
*/
|
|
390
|
+
async approveMfaRequest(mfaId: string): Promise<MfaRequestInfo> {
|
|
254
391
|
return Org.mfaApprove(this.#cs, this.#id, mfaId);
|
|
255
392
|
}
|
|
256
393
|
|
|
@@ -277,12 +414,7 @@ export class Org {
|
|
|
277
414
|
* @return {Promise<MfaRequestInfo>} The result of the MFA request
|
|
278
415
|
*/
|
|
279
416
|
static async mfaApprove(cs: CubeSigner, orgId: string, mfaId: string): Promise<MfaRequestInfo> {
|
|
280
|
-
|
|
281
|
-
await cs.management()
|
|
282
|
-
).patch("/v0/org/{org_id}/mfa/{mfa_id}", {
|
|
283
|
-
params: { path: { org_id: orgId, mfa_id: mfaId } },
|
|
284
|
-
});
|
|
285
|
-
return assertOk(resp);
|
|
417
|
+
return await cs.mfaApprove(orgId, mfaId);
|
|
286
418
|
}
|
|
287
419
|
|
|
288
420
|
/** Fetch org info.
|
|
@@ -317,17 +449,48 @@ export class Org {
|
|
|
317
449
|
/** List roles.
|
|
318
450
|
* @param {CubeSigner} cs The CubeSigner instance to use for signing.
|
|
319
451
|
* @param {string} orgId The id of the organization to which the role belongs.
|
|
320
|
-
* @
|
|
452
|
+
* @param {PageOpts} page Pagination options. Defaults to fetching the entire result set.
|
|
453
|
+
* @return {Role[]} Org roles.
|
|
454
|
+
* @internal
|
|
455
|
+
* */
|
|
456
|
+
private static async roles(cs: CubeSigner, orgId: string, page?: PageOpts): Promise<Role[]> {
|
|
457
|
+
page ??= Page.default();
|
|
458
|
+
const listFn = async (query: PageQueryArgs) => {
|
|
459
|
+
const resp = await (
|
|
460
|
+
await cs.management()
|
|
461
|
+
).get("/v0/org/{org_id}/roles", {
|
|
462
|
+
params: {
|
|
463
|
+
path: { org_id: orgId },
|
|
464
|
+
query,
|
|
465
|
+
},
|
|
466
|
+
parseAs: "json",
|
|
467
|
+
});
|
|
468
|
+
return assertOk(resp);
|
|
469
|
+
};
|
|
470
|
+
const p = new Paginator(
|
|
471
|
+
page,
|
|
472
|
+
listFn,
|
|
473
|
+
(u) => u.roles,
|
|
474
|
+
(u) => u.last_evaluated_key,
|
|
475
|
+
);
|
|
476
|
+
const roles = await p.fetch();
|
|
477
|
+
return roles.map((r: RoleInfo) => new Role(cs, orgId, r));
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/** List users.
|
|
481
|
+
* @param {CubeSigner} cs The CubeSigner instance to use for signing.
|
|
482
|
+
* @param {string} orgId The id of the organization to which the role belongs.
|
|
483
|
+
* @return {User[]} Org users.
|
|
321
484
|
* @internal
|
|
322
485
|
* */
|
|
323
|
-
private static async
|
|
486
|
+
private static async users(cs: CubeSigner, orgId: string): Promise<UserIdInfo[]> {
|
|
324
487
|
const resp = await (
|
|
325
488
|
await cs.management()
|
|
326
|
-
).get("/v0/org/{org_id}/
|
|
489
|
+
).get("/v0/org/{org_id}/users", {
|
|
327
490
|
params: { path: { org_id: orgId } },
|
|
328
491
|
parseAs: "json",
|
|
329
492
|
});
|
|
330
493
|
const data = assertOk(resp);
|
|
331
|
-
return data.
|
|
494
|
+
return data.users;
|
|
332
495
|
}
|
|
333
496
|
}
|
package/src/paginator.ts
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/** Pagination options. */
|
|
2
|
+
export interface PageOpts {
|
|
3
|
+
/** Max number of items per page. */
|
|
4
|
+
size?: number;
|
|
5
|
+
/**
|
|
6
|
+
* Starting point (i.e., 'last_evaluated_key' from the previous page).
|
|
7
|
+
* Omit to start from the beginning.
|
|
8
|
+
*/
|
|
9
|
+
start?: string;
|
|
10
|
+
/** Iterate until retrieving the entire result set. */
|
|
11
|
+
all: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** Static constructors for `IPage` */
|
|
15
|
+
export class Page {
|
|
16
|
+
/**
|
|
17
|
+
* The default is to fetch the entire result set
|
|
18
|
+
* (by repeatedly calling the remote endpoint until all pages are retrieved).
|
|
19
|
+
*
|
|
20
|
+
* @return {PageOpts} Pagination options.
|
|
21
|
+
*/
|
|
22
|
+
static default(): PageOpts {
|
|
23
|
+
return <PageOpts>{
|
|
24
|
+
all: true,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface PageQueryArgs {
|
|
30
|
+
/**
|
|
31
|
+
* Max number of items to return per page.
|
|
32
|
+
*
|
|
33
|
+
* The actual number of returned items may be less that this, even if there exist more
|
|
34
|
+
* data in the result set. To reliably determine if more data is left in the result set,
|
|
35
|
+
* inspect the [UnencryptedLastEvalKey] value in the response object.
|
|
36
|
+
*/
|
|
37
|
+
"page.size"?: number;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* The start of the page.
|
|
41
|
+
*
|
|
42
|
+
* Omit to start from the beginning; otherwise, only specify the exact
|
|
43
|
+
* value previously returned as 'last_evaluated_key' from the same endpoint.
|
|
44
|
+
*/
|
|
45
|
+
"page.start"?: string | null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export type ListFn<U> = (pageQueryArgs: PageQueryArgs) => Promise<U>;
|
|
49
|
+
export type ItemsFn<U, T> = (resp: U) => T[];
|
|
50
|
+
export type LastFn<U> = (resp: U) => string | null | undefined;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Helper class for fetching paginated results.
|
|
54
|
+
*/
|
|
55
|
+
export class Paginator<U, T> {
|
|
56
|
+
readonly #listFn: ListFn<U>;
|
|
57
|
+
readonly #itemsFn: ItemsFn<U, T>;
|
|
58
|
+
readonly #lastFn: LastFn<U>;
|
|
59
|
+
#opts: PageOpts;
|
|
60
|
+
#last: string | null | undefined;
|
|
61
|
+
#done: boolean;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @param {PageOpts} pageOpts Pagination options
|
|
65
|
+
* @param {ListFn<U>} listFn Calls a remote endpoint that returns a paginated response
|
|
66
|
+
* @param {ItemsFn<U, T>} itemsFn Extracts items from the paginated response
|
|
67
|
+
* @param {LastFn<U>} lastFn Extracts the last evaluated key from the paginated response
|
|
68
|
+
*/
|
|
69
|
+
constructor(pageOpts: PageOpts, listFn: ListFn<U>, itemsFn: ItemsFn<U, T>, lastFn: LastFn<U>) {
|
|
70
|
+
this.#listFn = listFn;
|
|
71
|
+
this.#itemsFn = itemsFn;
|
|
72
|
+
this.#lastFn = lastFn;
|
|
73
|
+
this.#opts = pageOpts;
|
|
74
|
+
this.#last = pageOpts.start;
|
|
75
|
+
this.#done = false;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Fetches either a single page or the entire result set, depending on
|
|
80
|
+
* the `all` property of the pagination options.
|
|
81
|
+
*
|
|
82
|
+
* @return {Promise<T[]>} A single page or the entire result set.
|
|
83
|
+
*/
|
|
84
|
+
async fetch(): Promise<T[]> {
|
|
85
|
+
return this.#opts.all ? await this.fetchAll() : await this.fetchPage();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Fetches a single page of the result set from where it previously left off.
|
|
90
|
+
* Mutates self to remember where it left off.
|
|
91
|
+
*
|
|
92
|
+
* @return {Promise<T[]>} The next page of the result set.
|
|
93
|
+
*/
|
|
94
|
+
async fetchPage(): Promise<T[]> {
|
|
95
|
+
if (this.#done) {
|
|
96
|
+
return [];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const resp = await this.#listFn({
|
|
100
|
+
"page.size": this.#opts.size,
|
|
101
|
+
"page.start": this.#last,
|
|
102
|
+
});
|
|
103
|
+
this.#last = this.#lastFn(resp);
|
|
104
|
+
this.#done = !this.#last;
|
|
105
|
+
return this.#itemsFn(resp);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Fetches the entire result set starting from where it previously left off
|
|
110
|
+
* by iterating through the pages returned by the remote end.
|
|
111
|
+
*
|
|
112
|
+
* @return {Promise<T[]>} The entire result set.
|
|
113
|
+
*/
|
|
114
|
+
async fetchAll(): Promise<T[]> {
|
|
115
|
+
const result = [];
|
|
116
|
+
while (!this.#done) {
|
|
117
|
+
const items = await this.fetchPage();
|
|
118
|
+
result.push(...items);
|
|
119
|
+
}
|
|
120
|
+
return result;
|
|
121
|
+
}
|
|
122
|
+
}
|