@cubist-labs/cubesigner-sdk 0.1.77 → 0.2.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.
package/src/role.ts CHANGED
@@ -1,24 +1,23 @@
1
1
  import {
2
- CubeSigner,
3
2
  Key,
3
+ KeyWithPoliciesInfo,
4
4
  MfaType,
5
+ PageOpts,
6
+ RoleInfo,
5
7
  SignerSession,
6
8
  SignerSessionInfo,
7
9
  SignerSessionLifetime,
8
10
  SignerSessionManager,
9
11
  SignerSessionStorage,
12
+ UpdateRoleRequest,
10
13
  } from ".";
11
- import { components, paths } from "./client";
12
- import { assertOk } from "./util";
14
+ import { CubeSignerClient } from "./client";
13
15
 
14
- type UpdateRoleRequest =
15
- paths["/v0/org/{org_id}/keys/{key_id}"]["patch"]["requestBody"]["content"]["application/json"];
16
- type KeyWithPoliciesInfo = components["schemas"]["KeyInRoleInfo"];
17
- export type RoleInfo = components["schemas"]["RoleInfo"];
18
-
19
- /** Restrict transaction receiver.
16
+ /**
17
+ * Restrict transaction receiver.
18
+ *
20
19
  * @example { TxReceiver: "0x8c594691c0e592ffa21f153a16ae41db5befcaaa" }
21
- * */
20
+ */
22
21
  export type TxReceiver = { TxReceiver: string };
23
22
 
24
23
  /** The kind of deposit contracts. */
@@ -35,14 +34,18 @@ export type TxDeposit = TxDepositBase | TxDepositPubkey | TxDepositRole;
35
34
  /** Restrict transactions to calls to deposit contract*/
36
35
  export type TxDepositBase = { TxDeposit: { kind: DepositContract } };
37
36
 
38
- /** Restrict transactions to calls to deposit contract with fixed validator (pubkey):
39
- * @example { TxDeposit: { kind: DespositContract.Canonical, validator: { pubkey: "8879...8"} }}
40
- * */
37
+ /**
38
+ * Restrict transactions to calls to deposit contract with fixed validator (pubkey):
39
+ *
40
+ * @example { TxDeposit: { kind: DespositContract.Canonical, validator: { pubkey: "8879...8"} }}
41
+ */
41
42
  export type TxDepositPubkey = { TxDeposit: { kind: DepositContract; pubkey: string } };
42
43
 
43
- /** Restrict transactions to calls to deposit contract with any validator key in a role:
44
+ /**
45
+ * Restrict transactions to calls to deposit contract with any validator key in a role:
46
+ *
44
47
  * @example { TxDeposit: { kind: DespositContract.Canonical, validator: { role_id: "Role#c63...af"} }}
45
- * */
48
+ */
46
49
  export type TxDepositRole = { TxDeposit: { kind: DepositContract; role_id: string } };
47
50
 
48
51
  /** All different kinds of sensitive operations. */
@@ -55,7 +58,9 @@ export enum OperationKind {
55
58
  SolanaSign = "SolanaSign", // eslint-disable-line no-unused-vars
56
59
  }
57
60
 
58
- /** MFA policy
61
+ /**
62
+ * MFA policy
63
+ *
59
64
  * @example {
60
65
  * {
61
66
  * count: 1,
@@ -63,7 +68,7 @@ export enum OperationKind {
63
68
  * allowed_mfa_types: [ "Totp" ],
64
69
  * allowed_approvers: [ "User#123" ],
65
70
  * }
66
- * */
71
+ */
67
72
  export type MfaPolicy = {
68
73
  count?: number;
69
74
  num_auth_factors?: number;
@@ -93,7 +98,9 @@ export type RequireMfa = {
93
98
  export const AllowRawBlobSigning = "AllowRawBlobSigning" as const;
94
99
  export type AllowRawBlobSigning = typeof AllowRawBlobSigning;
95
100
 
96
- /** Key policy
101
+ /**
102
+ * Key policy
103
+ *
97
104
  * @example [
98
105
  * {
99
106
  * "TxReceiver": "0x8c594691c0e592ffa21f153a16ae41db5befcaaa"
@@ -114,30 +121,29 @@ export type AllowRawBlobSigning = typeof AllowRawBlobSigning;
114
121
  * }
115
122
  * }
116
123
  * ]
117
- * */
124
+ */
118
125
  export type KeyPolicy = (TxReceiver | TxDeposit | RequireMfa | AllowRawBlobSigning)[];
119
126
 
120
127
  /** A key guarded by a policy. */
121
128
  export class KeyWithPolicies {
122
- readonly #cs: CubeSigner;
123
- readonly #orgId: string;
129
+ readonly #csc: CubeSignerClient;
124
130
  readonly keyId: string;
125
131
  readonly policy?: KeyPolicy;
126
132
 
127
133
  /** @return {Promise<Key>} The key */
128
134
  async getKey(): Promise<Key> {
129
- return await Key.getKey(this.#cs, this.#orgId, this.keyId);
135
+ const keyInfo = await this.#csc.keyGet(this.keyId);
136
+ return new Key(this.#csc, keyInfo);
130
137
  }
131
138
 
132
- /** Constructor.
133
- * @param {CubeSigner} cs The CubeSigner instance to use for signing.
134
- * @param {string} orgId The id of the organization to which the key belongs.
139
+ /**
140
+ * Constructor.
141
+ * @param {CubeSignerClient} csc The CubeSigner instance to use for signing.
135
142
  * @param {KeyWithPoliciesInfo} keyWithPolicies The key and its policies
136
143
  * @internal
137
- * */
138
- constructor(cs: CubeSigner, orgId: string, keyWithPolicies: KeyWithPoliciesInfo) {
139
- this.#cs = cs;
140
- this.#orgId = orgId;
144
+ */
145
+ constructor(csc: CubeSignerClient, keyWithPolicies: KeyWithPoliciesInfo) {
146
+ this.#csc = csc;
141
147
  this.keyId = keyWithPolicies.key_id;
142
148
  this.policy = keyWithPolicies.policy as unknown as KeyPolicy;
143
149
  }
@@ -145,8 +151,8 @@ export class KeyWithPolicies {
145
151
 
146
152
  /** Roles. */
147
153
  export class Role {
148
- readonly #cs: CubeSigner;
149
- readonly #orgId: string;
154
+ readonly #csc: CubeSignerClient;
155
+
150
156
  /** Human-readable name for the role */
151
157
  public readonly name?: string;
152
158
 
@@ -158,7 +164,7 @@ export class Role {
158
164
 
159
165
  /** Delete the role. */
160
166
  async delete(): Promise<void> {
161
- await Role.deleteRole(this.#cs, this.#orgId, this.id);
167
+ await this.#csc.roleDelete(this.id);
162
168
  }
163
169
 
164
170
  /** Is the role enabled? */
@@ -177,222 +183,143 @@ export class Role {
177
183
  await this.update({ enabled: false });
178
184
  }
179
185
 
180
- /** The list of users with access to the role.
186
+ /**
187
+ * The list of all users with access to the role.
181
188
  * @example [
182
189
  * "User#c3b9379c-4e8c-4216-bd0a-65ace53cf98f",
183
190
  * "User#5593c25b-52e2-4fb5-b39b-96d41d681d82"
184
191
  * ]
185
- * */
186
- async users(): Promise<string[]> {
187
- const data = await this.fetch();
188
- return data.users || [];
192
+ *
193
+ * @param {PageOpts} page Optional pagination options; by default, retrieves all users.
194
+ */
195
+ async users(page?: PageOpts): Promise<string[]> {
196
+ const users = await this.#csc.roleUsersList(this.id, page).fetch();
197
+ return (users || []).map((u) => u.user_id);
189
198
  }
190
199
 
191
- /** Add a user to the role.
192
- * Adds an existing user to an existing role.
200
+ /**
201
+ * Add an existing user to an existing role.
202
+ *
193
203
  * @param {string} userId The user-id of the user to add to the role.
194
- * */
204
+ */
195
205
  async addUser(userId: string) {
196
- const resp = await (
197
- await this.#cs.management()
198
- ).put("/v0/org/{org_id}/roles/{role_id}/add_user/{user_id}", {
199
- params: { path: { org_id: this.#orgId, role_id: this.id, user_id: userId } },
200
- parseAs: "json",
201
- });
202
- assertOk(resp, "Failed to add user to role");
206
+ await this.#csc.roleUserAdd(this.id, userId);
203
207
  }
204
208
 
205
- /** The list of keys in the role.
209
+ /**
210
+ * The list of keys in the role.
206
211
  * @example [
207
212
  * {
208
213
  * id: "Key#bfe3eccb-731e-430d-b1e5-ac1363e6b06b",
209
214
  * policy: { TxReceiver: "0x8c594691c0e592ffa21f153a16ae41db5befcaaa" }
210
215
  * },
211
216
  * ]
212
- * */
213
- async keys(): Promise<KeyWithPolicies[]> {
214
- const data = await this.fetch();
215
- return (data.keys || []).map((k) => new KeyWithPolicies(this.#cs, this.#orgId, k));
217
+ *
218
+ * @param {PageOpts} page Optional pagination options; by default, retrieves all keys in this role.
219
+ */
220
+ async keys(page?: PageOpts): Promise<KeyWithPolicies[]> {
221
+ const keysInRole = await this.#csc.roleKeysList(this.id, page).fetch();
222
+ return keysInRole.map((k) => new KeyWithPolicies(this.#csc, k));
216
223
  }
217
224
 
218
- /** Add keys to the role.
219
- * Adds a list of existing keys to an existing role.
225
+ /**
226
+ * Add a list of existing keys to an existing role.
227
+ *
220
228
  * @param {Key[]} keys The list of keys to add to the role.
221
229
  * @param {KeyPolicy?} policy The optional policy to apply to each key.
222
- * */
230
+ */
223
231
  async addKeys(keys: Key[], policy?: KeyPolicy) {
224
- const resp = await (
225
- await this.#cs.management()
226
- ).put("/v0/org/{org_id}/roles/{role_id}/add_keys", {
227
- params: { path: { org_id: this.#orgId, role_id: this.id } },
228
- body: {
229
- key_ids: keys.map((k) => k.id),
230
- policy: (policy ?? null) as Record<string, never>[] | null,
231
- },
232
- parseAs: "json",
233
- });
234
- assertOk(resp, "Failed to add keys to role");
232
+ await this.#csc.roleKeysAdd(
233
+ this.id,
234
+ keys.map((k) => k.id),
235
+ policy,
236
+ );
235
237
  }
236
238
 
237
- /** Add a key to the role.
238
- * Adds an existing key to an existing role.
239
+ /**
240
+ * Add an existing key to an existing role.
241
+ *
239
242
  * @param {Key} key The key to add to the role.
240
243
  * @param {KeyPolicy?} policy The optional policy to apply to the key.
241
- * */
244
+ */
242
245
  async addKey(key: Key, policy?: KeyPolicy) {
243
- return await this.addKeys([key], policy);
246
+ await this.addKeys([key], policy);
244
247
  }
245
248
 
246
- /** Remove key from the role.
247
- * Removes an existing key from an existing role.
249
+ /**
250
+ * Remove an existing key from an existing role.
251
+ *
248
252
  * @param {Key} key The key to remove from the role.
249
- * */
253
+ */
250
254
  async removeKey(key: Key) {
251
- const resp = await (
252
- await this.#cs.management()
253
- ).del("/v0/org/{org_id}/roles/{role_id}/keys/{key_id}", {
254
- params: { path: { org_id: this.#orgId, role_id: this.id, key_id: key.id } },
255
- parseAs: "json",
256
- });
257
- assertOk(resp, "Failed to remove key from role");
255
+ await this.#csc.roleKeysRemove(this.id, key.id);
258
256
  }
259
257
 
260
258
  /**
261
259
  * Create a new session for this role.
262
260
  * @param {SignerSessionStorage} storage The session storage to use
263
261
  * @param {string} purpose Descriptive purpose.
264
- * @param {SignerSessionLifetime} ttl Optional session lifetimes.
262
+ * @param {SignerSessionLifetime} lifetimes Optional session lifetimes.
263
+ * @param {string[]} scopes Session scopes. Only `sign:*` scopes are allowed.
265
264
  * @return {Promise<SignerSession>} New signer session.
266
265
  */
267
266
  async createSession(
268
267
  storage: SignerSessionStorage,
269
268
  purpose: string,
270
- ttl?: SignerSessionLifetime,
269
+ lifetimes?: SignerSessionLifetime,
270
+ scopes?: string[],
271
271
  ): Promise<SignerSession> {
272
- const manager = await SignerSessionManager.create(
273
- this.#cs,
274
- storage,
275
- this.#orgId,
276
- this.id,
277
- purpose,
278
- ttl,
279
- );
272
+ const sessionData = await this.#csc.sessionCreateForRole(this.id, purpose, scopes, lifetimes);
273
+ await storage.save(sessionData);
274
+ const manager = await SignerSessionManager.loadFromStorage(storage);
280
275
  return new SignerSession(manager);
281
276
  }
282
277
 
283
278
  /**
284
279
  * List all signer sessions for this role. Returned objects can be used to
285
280
  * revoke individual sessions, but they cannot be used for authentication.
281
+ *
282
+ * @param {PageOpts} page Optional pagination options; by default, retrieves all sessions.
286
283
  * @return {Promise<SignerSessionInfo[]>} Signer sessions for this role.
287
284
  */
288
- async sessions(): Promise<SignerSessionInfo[]> {
289
- const resp = await (
290
- await this.#cs.management()
291
- ).get("/v0/org/{org_id}/roles/{role_id}/tokens", {
292
- params: { path: { org_id: this.#orgId, role_id: this.id } },
293
- });
294
- const data = assertOk(resp);
295
- return data.tokens.map(
296
- (t) => new SignerSessionInfo(this.#cs, this.#orgId, this.id, t.hash, t.purpose),
297
- );
285
+ async sessions(page?: PageOpts): Promise<SignerSessionInfo[]> {
286
+ const sessions = await this.#csc.sessionsList(this.id, page).fetch();
287
+ return sessions.map((t) => new SignerSessionInfo(this.#csc, t.session_id, t.purpose));
298
288
  }
299
289
 
300
290
  // --------------------------------------------------------------------------
301
291
  // -- INTERNAL --------------------------------------------------------------
302
292
  // --------------------------------------------------------------------------
303
293
 
304
- /** Create a new role.
305
- * @param {CubeSigner} cs The CubeSigner instance to use for signing.
306
- * @param {string} orgId The id of the organization to which the role belongs.
294
+ /**
295
+ * Constructor.
296
+ * @param {CubeSignerClient} csc The CubeSigner instance to use for signing.
307
297
  * @param {RoleInfo} data The JSON response from the API server.
308
298
  * @internal
309
- * */
310
- constructor(cs: CubeSigner, orgId: string, data: RoleInfo) {
311
- this.#cs = cs;
312
- this.#orgId = orgId;
299
+ */
300
+ constructor(csc: CubeSignerClient, data: RoleInfo) {
301
+ this.#csc = csc;
313
302
  this.id = data.role_id;
314
303
  this.name = data.name ?? undefined;
315
304
  }
316
305
 
317
- /** Update the role.
306
+ /**
307
+ * Update the role.
308
+ *
318
309
  * @param {UpdateRoleRequest} request The JSON request to send to the API server.
319
- * */
320
- private async update(request: UpdateRoleRequest): Promise<void> {
321
- const resp = await (
322
- await this.#cs.management()
323
- ).patch("/v0/org/{org_id}/roles/{role_id}", {
324
- params: { path: { org_id: this.#orgId, role_id: this.id } },
325
- body: request,
326
- parseAs: "json",
327
- });
328
- assertOk(resp);
329
- }
330
-
331
- /** Create new role.
332
- * @param {CubeSigner} cs The CubeSigner instance to use for signing.
333
- * @param {string} orgId The id of the organization to which the role belongs.
334
- * @param {string?} name The optional name of the role.
335
- * @return {Role} The new role.
336
- * @internal
337
- * */
338
- static async createRole(cs: CubeSigner, orgId: string, name?: string): Promise<Role> {
339
- const resp = await (
340
- await cs.management()
341
- ).post("/v0/org/{org_id}/roles", {
342
- params: { path: { org_id: orgId } },
343
- body: name ? { name } : undefined,
344
- parseAs: "json",
345
- });
346
- const data = assertOk(resp);
347
- return await Role.getRole(cs, orgId, data.role_id);
348
- }
349
-
350
- /** Get a role by id.
351
- * @param {CubeSigner} cs The CubeSigner instance to use for signing.
352
- * @param {string} orgId The id of the organization to which the role belongs.
353
- * @param {string} roleId The id of the role to get.
354
- * @return {Role} The role.
355
- * @internal
356
- * */
357
- static async getRole(cs: CubeSigner, orgId: string, roleId: string): Promise<Role> {
358
- const resp = await (
359
- await cs.management()
360
- ).get("/v0/org/{org_id}/roles/{role_id}", {
361
- params: { path: { org_id: orgId, role_id: roleId } },
362
- parseAs: "json",
363
- });
364
- const data = assertOk(resp);
365
- return new Role(cs, orgId, data);
310
+ * @return {Promise<RoleInfo>} The updated role information.
311
+ */
312
+ private async update(request: UpdateRoleRequest): Promise<RoleInfo> {
313
+ return await this.#csc.roleUpdate(this.id, request);
366
314
  }
367
315
 
368
- /** Fetches the role information.
316
+ /**
317
+ * Fetches the role information.
318
+ *
369
319
  * @return {RoleInfo} The role information.
370
320
  * @internal
371
- * */
321
+ */
372
322
  private async fetch(): Promise<RoleInfo> {
373
- const resp = await (
374
- await this.#cs.management()
375
- ).get("/v0/org/{org_id}/roles/{role_id}", {
376
- params: { path: { org_id: this.#orgId, role_id: this.id } },
377
- parseAs: "json",
378
- });
379
- const data = assertOk(resp);
380
- return data;
381
- }
382
-
383
- /** Delete role.
384
- * @param {CubeSigner} cs The CubeSigner instance to use for signing.
385
- * @param {string} orgId The id of the organization to which the role belongs.
386
- * @param {string} roleId The id of the role to delete.
387
- * @internal
388
- * */
389
- private static async deleteRole(cs: CubeSigner, orgId: string, roleId: string): Promise<void> {
390
- const resp = await (
391
- await cs.management()
392
- ).del("/v0/org/{org_id}/roles/{role_id}", {
393
- params: { path: { org_id: orgId, role_id: roleId } },
394
- parseAs: "json",
395
- });
396
- assertOk(resp);
323
+ return await this.#csc.roleGet(this.id);
397
324
  }
398
325
  }