opal-security 3.1.1-beta.55edef9 → 3.1.1-beta.5641f4d

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 CHANGED
@@ -22,7 +22,7 @@ $ npm install -g opal-security
22
22
  $ opal COMMAND
23
23
  running command...
24
24
  $ opal (--version)
25
- opal-security/3.1.1-beta.55edef9 linux-x64 node-v20.19.2
25
+ opal-security/3.1.1-beta.5641f4d linux-x64 node-v20.19.2
26
26
  $ opal --help [COMMAND]
27
27
  USAGE
28
28
  $ opal COMMAND
@@ -101,7 +101,7 @@ EXAMPLES
101
101
  $ opal aws:identity
102
102
  ```
103
103
 
104
- _See code: [src/commands/aws/identity.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.55edef9/src/commands/aws/identity.ts)_
104
+ _See code: [src/commands/aws/identity.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5641f4d/src/commands/aws/identity.ts)_
105
105
 
106
106
  ## `opal clear-auth-provider`
107
107
 
@@ -121,7 +121,7 @@ EXAMPLES
121
121
  $ opal clear-auth-provider
122
122
  ```
123
123
 
124
- _See code: [src/commands/clear-auth-provider.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.55edef9/src/commands/clear-auth-provider.ts)_
124
+ _See code: [src/commands/clear-auth-provider.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5641f4d/src/commands/clear-auth-provider.ts)_
125
125
 
126
126
  ## `opal curl-example`
127
127
 
@@ -138,7 +138,7 @@ DESCRIPTION
138
138
  Prints out an example cURL command containing the parameters the CLI uses to query the Opal server.
139
139
  ```
140
140
 
141
- _See code: [src/commands/curl-example.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.55edef9/src/commands/curl-example.ts)_
141
+ _See code: [src/commands/curl-example.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5641f4d/src/commands/curl-example.ts)_
142
142
 
143
143
  ## `opal groups get`
144
144
 
@@ -150,7 +150,7 @@ USAGE
150
150
 
151
151
  FLAGS
152
152
  -h, --help Show CLI help.
153
- -i, --id=<value> The Opal ID of the resource. You can find this from the URL, e.g. https://opal.dev/resources/[ID]
153
+ -i, --id=<value> The Opal ID of the asset. You can find this from the URL, e.g. https://opal.dev/resources/[ID]
154
154
 
155
155
  DESCRIPTION
156
156
  Get group info for a particular group.
@@ -159,7 +159,7 @@ EXAMPLES
159
159
  $ opal groups:get --id 54052a3e-5375-4392-aeaf-0c6c44c131d4
160
160
  ```
161
161
 
162
- _See code: [src/commands/groups/get.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.55edef9/src/commands/groups/get.ts)_
162
+ _See code: [src/commands/groups/get.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5641f4d/src/commands/groups/get.ts)_
163
163
 
164
164
  ## `opal help [COMMANDS]`
165
165
 
@@ -191,7 +191,7 @@ USAGE
191
191
 
192
192
  FLAGS
193
193
  -h, --help Show CLI help.
194
- -i, --id=<value> The Opal ID of the resource. You can find this from the URL, e.g.
194
+ -i, --id=<value> The Opal ID of the asset. You can find this from the URL, e.g.
195
195
  https://opal.dev/resources/[ID]
196
196
  -r, --refresh Starts a new session even if one already exists. Useful if a session is about to expire.
197
197
  -s, --sessionId=<value> The Opal ID of the session to connect to. Uses an existing session that was created via the
@@ -209,7 +209,7 @@ EXAMPLES
209
209
  $ opal iam-roles:start --id 51f7176b-0464-4a6f-8369-e951e187b398 --profileName "custom-profile"
210
210
  ```
211
211
 
212
- _See code: [src/commands/iam-roles/start.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.55edef9/src/commands/iam-roles/start.ts)_
212
+ _See code: [src/commands/iam-roles/start.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5641f4d/src/commands/iam-roles/start.ts)_
213
213
 
214
214
  ## `opal kube-roles start`
215
215
 
@@ -222,7 +222,7 @@ USAGE
222
222
  FLAGS
223
223
  -a, --accessLevelRemoteId=<value> The remote ID of the access level with which to access the resource.
224
224
  -h, --help Show CLI help.
225
- -i, --id=<value> The Opal ID of the resource. You can find this from the URL, e.g.
225
+ -i, --id=<value> The Opal ID of the asset. You can find this from the URL, e.g.
226
226
  https://opal.dev/resources/[ID]
227
227
  -r, --refresh Starts a new session even if one already exists. Useful if a session is about to
228
228
  expire.
@@ -240,7 +240,7 @@ EXAMPLES
240
240
  $ opal kube-roles:start --id 51f7176b-0464-4a6f-8369-e951e187b398 --accessLevelRemoteId "arn:aws:iam::712234975475:role/acme-eks-cluster-admin-role"
241
241
  ```
242
242
 
243
- _See code: [src/commands/kube-roles/start.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.55edef9/src/commands/kube-roles/start.ts)_
243
+ _See code: [src/commands/kube-roles/start.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5641f4d/src/commands/kube-roles/start.ts)_
244
244
 
245
245
  ## `opal login`
246
246
 
@@ -261,7 +261,7 @@ EXAMPLES
261
261
  $ opal login
262
262
  ```
263
263
 
264
- _See code: [src/commands/login.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.55edef9/src/commands/login.ts)_
264
+ _See code: [src/commands/login.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5641f4d/src/commands/login.ts)_
265
265
 
266
266
  ## `opal logout`
267
267
 
@@ -281,7 +281,7 @@ EXAMPLES
281
281
  $ opal logout
282
282
  ```
283
283
 
284
- _See code: [src/commands/logout.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.55edef9/src/commands/logout.ts)_
284
+ _See code: [src/commands/logout.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5641f4d/src/commands/logout.ts)_
285
285
 
286
286
  ## `opal postgres-instances start`
287
287
 
@@ -294,7 +294,7 @@ USAGE
294
294
  FLAGS
295
295
  -a, --accessLevelRemoteId=<value> The remote ID of the access level with which to access the resource.
296
296
  -h, --help Show CLI help.
297
- -i, --id=<value> The Opal ID of the resource. You can find this from the URL, e.g.
297
+ -i, --id=<value> The Opal ID of the asset. You can find this from the URL, e.g.
298
298
  https://opal.dev/resources/[ID]
299
299
  -r, --refresh Starts a new session even if one already exists. Useful if a session is about to
300
300
  expire.
@@ -318,7 +318,7 @@ EXAMPLES
318
318
  $ opal postgres-instances:start --id 51f7176b-0464-4a6f-8369-e951e187b398 --accessLevelRemoteId fullaccess --action view
319
319
  ```
320
320
 
321
- _See code: [src/commands/postgres-instances/start.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.55edef9/src/commands/postgres-instances/start.ts)_
321
+ _See code: [src/commands/postgres-instances/start.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5641f4d/src/commands/postgres-instances/start.ts)_
322
322
 
323
323
  ## `opal resources get`
324
324
 
@@ -330,7 +330,7 @@ USAGE
330
330
 
331
331
  FLAGS
332
332
  -h, --help Show CLI help.
333
- -i, --id=<value> The Opal ID of the resource. You can find this from the URL, e.g. https://opal.dev/resources/[ID]
333
+ -i, --id=<value> The Opal ID of the asset. You can find this from the URL, e.g. https://opal.dev/resources/[ID]
334
334
 
335
335
  DESCRIPTION
336
336
  Get resource info for a particular resource.
@@ -339,7 +339,7 @@ EXAMPLES
339
339
  $ opal resources:get --id 54052a3e-5375-4392-aeaf-0c6c44c131d4
340
340
  ```
341
341
 
342
- _See code: [src/commands/resources/get.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.55edef9/src/commands/resources/get.ts)_
342
+ _See code: [src/commands/resources/get.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5641f4d/src/commands/resources/get.ts)_
343
343
 
344
344
  ## `opal set-auth-provider`
345
345
 
@@ -365,7 +365,7 @@ EXAMPLES
365
365
  $ opal set-auth-provider --clientID 1234asdf --issuerUrl https://auth.example.com
366
366
  ```
367
367
 
368
- _See code: [src/commands/set-auth-provider.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.55edef9/src/commands/set-auth-provider.ts)_
368
+ _See code: [src/commands/set-auth-provider.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5641f4d/src/commands/set-auth-provider.ts)_
369
369
 
370
370
  ## `opal set-custom-header`
371
371
 
@@ -386,7 +386,7 @@ EXAMPLES
386
386
  $ opal set-custom-header --header 'cf-access-token: $TOKEN'
387
387
  ```
388
388
 
389
- _See code: [src/commands/set-custom-header.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.55edef9/src/commands/set-custom-header.ts)_
389
+ _See code: [src/commands/set-custom-header.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5641f4d/src/commands/set-custom-header.ts)_
390
390
 
391
391
  ## `opal set-token`
392
392
 
@@ -406,7 +406,7 @@ EXAMPLES
406
406
  $ opal set-token
407
407
  ```
408
408
 
409
- _See code: [src/commands/set-token.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.55edef9/src/commands/set-token.ts)_
409
+ _See code: [src/commands/set-token.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5641f4d/src/commands/set-token.ts)_
410
410
 
411
411
  ## `opal set-url [URL]`
412
412
 
@@ -430,7 +430,7 @@ EXAMPLES
430
430
  $ opal set-url
431
431
  ```
432
432
 
433
- _See code: [src/commands/set-url.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.55edef9/src/commands/set-url.ts)_
433
+ _See code: [src/commands/set-url.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5641f4d/src/commands/set-url.ts)_
434
434
 
435
435
  ## `opal ssh copyFrom`
436
436
 
@@ -442,7 +442,7 @@ USAGE
442
442
 
443
443
  FLAGS
444
444
  -h, --help Show CLI help.
445
- -i, --id=<value> The Opal ID of the resource. You can find this from the URL, e.g.
445
+ -i, --id=<value> The Opal ID of the asset. You can find this from the URL, e.g.
446
446
  https://opal.dev/resources/[ID]
447
447
  -s, --sessionId=<value> The Opal ID of the session to connect to. Uses an existing session that was created via the
448
448
  web flow.
@@ -461,7 +461,7 @@ EXAMPLES
461
461
  $ opal ssh:copyFrom --src instance/dir --dest my/dir --id 51f7176b-0464-4a6f-8369-e951e187b398
462
462
  ```
463
463
 
464
- _See code: [src/commands/ssh/copyFrom.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.55edef9/src/commands/ssh/copyFrom.ts)_
464
+ _See code: [src/commands/ssh/copyFrom.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5641f4d/src/commands/ssh/copyFrom.ts)_
465
465
 
466
466
  ## `opal ssh copyTo`
467
467
 
@@ -473,7 +473,7 @@ USAGE
473
473
 
474
474
  FLAGS
475
475
  -h, --help Show CLI help.
476
- -i, --id=<value> The Opal ID of the resource. You can find this from the URL, e.g.
476
+ -i, --id=<value> The Opal ID of the asset. You can find this from the URL, e.g.
477
477
  https://opal.dev/resources/[ID]
478
478
  -s, --sessionId=<value> The Opal ID of the session to connect to. Uses an existing session that was created via the
479
479
  web flow.
@@ -492,7 +492,7 @@ EXAMPLES
492
492
  $ opal ssh:copyTo --src my/dir --dest instance/dir --id 51f7176b-0464-4a6f-8369-e951e187b398
493
493
  ```
494
494
 
495
- _See code: [src/commands/ssh/copyTo.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.55edef9/src/commands/ssh/copyTo.ts)_
495
+ _See code: [src/commands/ssh/copyTo.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5641f4d/src/commands/ssh/copyTo.ts)_
496
496
 
497
497
  ## `opal ssh start`
498
498
 
@@ -504,7 +504,7 @@ USAGE
504
504
 
505
505
  FLAGS
506
506
  -h, --help Show CLI help.
507
- -i, --id=<value> The Opal ID of the resource. You can find this from the URL, e.g.
507
+ -i, --id=<value> The Opal ID of the asset. You can find this from the URL, e.g.
508
508
  https://opal.dev/resources/[ID]
509
509
  -r, --refresh Starts a new session even if one already exists. Useful if a session is about to expire.
510
510
  -s, --sessionId=<value> The Opal ID of the session to connect to. Uses an existing session that was created via the
@@ -519,7 +519,7 @@ EXAMPLES
519
519
  $ opal ssh:start --id 51f7176b-0464-4a6f-8369-e951e187b398
520
520
  ```
521
521
 
522
- _See code: [src/commands/ssh/start.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.55edef9/src/commands/ssh/start.ts)_
522
+ _See code: [src/commands/ssh/start.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5641f4d/src/commands/ssh/start.ts)_
523
523
 
524
524
  ## `opal version`
525
525
 
@@ -2,5 +2,9 @@ import { Command } from "@oclif/core";
2
2
  export default class RequestCreate extends Command {
3
3
  static hidden: boolean;
4
4
  static description: string;
5
+ static flags: {
6
+ help: import("@oclif/core/lib/interfaces").BooleanFlag<void>;
7
+ id: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
8
+ };
5
9
  run(): Promise<void>;
6
10
  }
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const core_1 = require("@oclif/core");
4
4
  const apollo_1 = require("../../lib/apollo");
5
+ const flags_1 = require("../../lib/flags");
5
6
  const requests_1 = require("../../lib/requests");
6
7
  const displays_1 = require("../../utils/displays");
7
8
  const utils_1 = require("../../utils/utils");
@@ -10,17 +11,23 @@ class RequestCreate extends core_1.Command {
10
11
  await (0, apollo_1.initClient)(this, true);
11
12
  const client = await (0, apollo_1.getClient)(this, true);
12
13
  (0, utils_1.restrictToDev)(); //TODO: Remove after development is complete
14
+ const { flags } = await this.parse(RequestCreate);
13
15
  const metadata = (0, requests_1.initEmptyRequestMetadata)();
14
- (0, displays_1.headerMessage)(this);
15
- let shouldProceed = false;
16
- while (!shouldProceed) {
17
- // Step 1: Select first round of assets from an app
18
- await (0, requests_1.selectRequestableItems)(this, client, metadata.requestMap);
19
- // Step 2: Display the selected items in a tree format
16
+ if (flags.id) {
17
+ (0, requests_1.bypassRequestSelection)(this, client, flags.id, metadata);
18
+ }
19
+ else {
20
20
  (0, displays_1.headerMessage)(this);
21
- this.log((0, displays_1.treeifyRequestMap)(metadata.requestMap), "\n");
22
- // Step 3: Prompt to add more items, repeat 1-3 if needed
23
- shouldProceed = await (0, requests_1.doneSelectingAssets)();
21
+ let shouldProceed = false;
22
+ while (!shouldProceed) {
23
+ // Step 1: Select first round of assets from an app
24
+ await (0, requests_1.selectRequestableItems)(this, client, metadata.requestMap);
25
+ // Step 2: Display the selected items in a tree format
26
+ (0, displays_1.headerMessage)(this);
27
+ (0, displays_1.treeifyRequestMap)(this, metadata.requestMap);
28
+ // Step 3: Prompt to add more items, repeat 1-3 if needed
29
+ shouldProceed = await (0, requests_1.doneSelectingAssets)();
30
+ }
24
31
  }
25
32
  // Step 4: Set Request Defaults
26
33
  await (0, requests_1.setRequestDefaults)(this, client, metadata);
@@ -36,4 +43,12 @@ class RequestCreate extends core_1.Command {
36
43
  }
37
44
  RequestCreate.hidden = true;
38
45
  RequestCreate.description = "Creates an Opal access request via an interactive form";
46
+ RequestCreate.flags = {
47
+ help: flags_1.SHARED_FLAGS.help,
48
+ id: core_1.Flags.string({
49
+ char: "i",
50
+ multiple: true,
51
+ description: "The id of the asset (resource, group) to request access to. Append a role ID using a colon if needed, e.g. `--id 123:456`.",
52
+ }),
53
+ };
39
54
  exports.default = RequestCreate;
@@ -66,7 +66,7 @@ class ListRequests extends core_1.Command {
66
66
  let showPendingOnly = false;
67
67
  const { flags } = await this.parse(ListRequests);
68
68
  if (flags.n) {
69
- pageSize = flags.pageSinze;
69
+ pageSize = flags.n;
70
70
  }
71
71
  if (flags.showPendingOnly) {
72
72
  showPendingOnly = flags.showPendingOnly;
@@ -84,7 +84,7 @@ class ListRequests extends core_1.Command {
84
84
  (0, apollo_1.printResponse)(this, resp);
85
85
  }
86
86
  else {
87
- (0, displays_1.displayRequestList)(this, resp);
87
+ (0, displays_1.displayRequestListTable)(this, resp);
88
88
  }
89
89
  }
90
90
  }
@@ -22,6 +22,7 @@ type Documents = {
22
22
  "\nquery GroupAccessLevels($groupId: GroupId!) {\n groupAccessLevels(\n input: { groupId: $groupId }\n ) {\n ... on GroupAccessLevelsResult {\n groupId\n accessLevels {\n ... on GroupAccessLevel {\n accessLevelName\n accessLevelRemoteId\n }\n }\n }\n }\n}\n": typeof types.GroupAccessLevelsDocument;
23
23
  "\n query RequestDefaults(\n $requestedResources: [RequestConfigurationResourceInput!]!\n $requestedGroups: [RequestConfigurationGroupInput!]!\n ) {\n requestDefaults(input: {\n requestedResources: $requestedResources,\n requestedGroups: $requestedGroups,\n }\n ) {\n ... on RequestDefaults {\n durationOptions {\n durationInMinutes\n label\n }\n recommendedDurationInMinutes\n defaultDurationInMinutes\n maxDurationInMinutes\n requireSupportTicket\n reasonOptional\n requesterIsAdmin\n }\n }\n }": typeof types.RequestDefaultsDocument;
24
24
  "\n mutation CreateRequest(\n $requestedResources: [RequestedResourceInput!]!\n $requestedGroups: [RequestedGroupInput!]!\n $reason: String!\n $durationInMinutes: Int\n ) {\n createRequest(\n input: {\n requestedResources: $requestedResources\n requestedGroups: $requestedGroups\n reason: $reason\n durationInMinutes: $durationInMinutes\n }\n ) {\n ... on CreateRequestResult {\n request {\n id\n status\n }\n }\n ... on RequestDurationTooLargeError {\n message\n }\n ... on RequestRequiresUserAuthTokenForConnectionError {\n message\n }\n ... on NoReviewersSetForOwnerError {\n message\n ownerId\n }\n ... on NoReviewersSetForResourceError {\n message\n resourceId\n }\n ... on NoReviewersSetForGroupError {\n message\n groupId\n }\n ... on NoManagerSetForRequestingUserError {\n message\n }\n ... on MfaInvalidError {\n message\n }\n ... on BulkRequestTooLargeError {\n message\n }\n ... on ItemCannotBeRequestedError {\n message\n }\n ... on UserCannotRequestAccessForTargetGroupError {\n message\n groupId\n userId\n }\n ... on GroupNestingNotAllowedError {\n message\n fromGroupId\n toGroupId\n }\n ... on TargetUserHasNestedAccessError {\n message\n groupIds\n }\n ... on RequestReasonMissingError {\n message\n }\n ... on RequestFieldValueMissingError {\n message\n fieldName\n }\n ... on LinkedGroupNotRequestableError {\n message\n sourceGroupId\n groupBindingId\n }\n ... on RequestReasonBelowMinLengthError {\n message\n }\n\n }\n }\n": typeof types.CreateRequestDocument;
25
+ "\n query GetCatalogItem($uuid: UUID!) {\n catalogItem(id: $uuid) {\n __typename\n ... on Connection {\n id\n displayName\n }\n ... on Resource {\n id\n displayName\n connection {\n id\n displayName\n }\n accessLevels{\n accessLevelName\n accessLevelRemoteId\n }\n }\n ...on Group {\n id\n name\n connection {\n id\n displayName\n }\n accessLevels{\n accessLevelName\n accessLevelRemoteId\n }\n }\n ... on UserFacingError {\n message\n }\n }\n }\n ": typeof types.GetCatalogItemDocument;
25
26
  };
26
27
  declare const documents: Documents;
27
28
  /**
@@ -77,5 +78,9 @@ export declare function graphql(source: "\n query RequestDefaults(\n $reques
77
78
  * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
78
79
  */
79
80
  export declare function graphql(source: "\n mutation CreateRequest(\n $requestedResources: [RequestedResourceInput!]!\n $requestedGroups: [RequestedGroupInput!]!\n $reason: String!\n $durationInMinutes: Int\n ) {\n createRequest(\n input: {\n requestedResources: $requestedResources\n requestedGroups: $requestedGroups\n reason: $reason\n durationInMinutes: $durationInMinutes\n }\n ) {\n ... on CreateRequestResult {\n request {\n id\n status\n }\n }\n ... on RequestDurationTooLargeError {\n message\n }\n ... on RequestRequiresUserAuthTokenForConnectionError {\n message\n }\n ... on NoReviewersSetForOwnerError {\n message\n ownerId\n }\n ... on NoReviewersSetForResourceError {\n message\n resourceId\n }\n ... on NoReviewersSetForGroupError {\n message\n groupId\n }\n ... on NoManagerSetForRequestingUserError {\n message\n }\n ... on MfaInvalidError {\n message\n }\n ... on BulkRequestTooLargeError {\n message\n }\n ... on ItemCannotBeRequestedError {\n message\n }\n ... on UserCannotRequestAccessForTargetGroupError {\n message\n groupId\n userId\n }\n ... on GroupNestingNotAllowedError {\n message\n fromGroupId\n toGroupId\n }\n ... on TargetUserHasNestedAccessError {\n message\n groupIds\n }\n ... on RequestReasonMissingError {\n message\n }\n ... on RequestFieldValueMissingError {\n message\n fieldName\n }\n ... on LinkedGroupNotRequestableError {\n message\n sourceGroupId\n groupBindingId\n }\n ... on RequestReasonBelowMinLengthError {\n message\n }\n\n }\n }\n"): (typeof documents)["\n mutation CreateRequest(\n $requestedResources: [RequestedResourceInput!]!\n $requestedGroups: [RequestedGroupInput!]!\n $reason: String!\n $durationInMinutes: Int\n ) {\n createRequest(\n input: {\n requestedResources: $requestedResources\n requestedGroups: $requestedGroups\n reason: $reason\n durationInMinutes: $durationInMinutes\n }\n ) {\n ... on CreateRequestResult {\n request {\n id\n status\n }\n }\n ... on RequestDurationTooLargeError {\n message\n }\n ... on RequestRequiresUserAuthTokenForConnectionError {\n message\n }\n ... on NoReviewersSetForOwnerError {\n message\n ownerId\n }\n ... on NoReviewersSetForResourceError {\n message\n resourceId\n }\n ... on NoReviewersSetForGroupError {\n message\n groupId\n }\n ... on NoManagerSetForRequestingUserError {\n message\n }\n ... on MfaInvalidError {\n message\n }\n ... on BulkRequestTooLargeError {\n message\n }\n ... on ItemCannotBeRequestedError {\n message\n }\n ... on UserCannotRequestAccessForTargetGroupError {\n message\n groupId\n userId\n }\n ... on GroupNestingNotAllowedError {\n message\n fromGroupId\n toGroupId\n }\n ... on TargetUserHasNestedAccessError {\n message\n groupIds\n }\n ... on RequestReasonMissingError {\n message\n }\n ... on RequestFieldValueMissingError {\n message\n fieldName\n }\n ... on LinkedGroupNotRequestableError {\n message\n sourceGroupId\n groupBindingId\n }\n ... on RequestReasonBelowMinLengthError {\n message\n }\n\n }\n }\n"];
81
+ /**
82
+ * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
83
+ */
84
+ export declare function graphql(source: "\n query GetCatalogItem($uuid: UUID!) {\n catalogItem(id: $uuid) {\n __typename\n ... on Connection {\n id\n displayName\n }\n ... on Resource {\n id\n displayName\n connection {\n id\n displayName\n }\n accessLevels{\n accessLevelName\n accessLevelRemoteId\n }\n }\n ...on Group {\n id\n name\n connection {\n id\n displayName\n }\n accessLevels{\n accessLevelName\n accessLevelRemoteId\n }\n }\n ... on UserFacingError {\n message\n }\n }\n }\n "): (typeof documents)["\n query GetCatalogItem($uuid: UUID!) {\n catalogItem(id: $uuid) {\n __typename\n ... on Connection {\n id\n displayName\n }\n ... on Resource {\n id\n displayName\n connection {\n id\n displayName\n }\n accessLevels{\n accessLevelName\n accessLevelRemoteId\n }\n }\n ...on Group {\n id\n name\n connection {\n id\n displayName\n }\n accessLevels{\n accessLevelName\n accessLevelRemoteId\n }\n }\n ... on UserFacingError {\n message\n }\n }\n }\n "];
80
85
  export type DocumentType<TDocumentNode extends DocumentNode<any, any>> = TDocumentNode extends DocumentNode<infer TType, any> ? TType : never;
81
86
  export {};
@@ -14,6 +14,7 @@ const documents = {
14
14
  "\nquery GroupAccessLevels($groupId: GroupId!) {\n groupAccessLevels(\n input: { groupId: $groupId }\n ) {\n ... on GroupAccessLevelsResult {\n groupId\n accessLevels {\n ... on GroupAccessLevel {\n accessLevelName\n accessLevelRemoteId\n }\n }\n }\n }\n}\n": types.GroupAccessLevelsDocument,
15
15
  "\n query RequestDefaults(\n $requestedResources: [RequestConfigurationResourceInput!]!\n $requestedGroups: [RequestConfigurationGroupInput!]!\n ) {\n requestDefaults(input: {\n requestedResources: $requestedResources,\n requestedGroups: $requestedGroups,\n }\n ) {\n ... on RequestDefaults {\n durationOptions {\n durationInMinutes\n label\n }\n recommendedDurationInMinutes\n defaultDurationInMinutes\n maxDurationInMinutes\n requireSupportTicket\n reasonOptional\n requesterIsAdmin\n }\n }\n }": types.RequestDefaultsDocument,
16
16
  "\n mutation CreateRequest(\n $requestedResources: [RequestedResourceInput!]!\n $requestedGroups: [RequestedGroupInput!]!\n $reason: String!\n $durationInMinutes: Int\n ) {\n createRequest(\n input: {\n requestedResources: $requestedResources\n requestedGroups: $requestedGroups\n reason: $reason\n durationInMinutes: $durationInMinutes\n }\n ) {\n ... on CreateRequestResult {\n request {\n id\n status\n }\n }\n ... on RequestDurationTooLargeError {\n message\n }\n ... on RequestRequiresUserAuthTokenForConnectionError {\n message\n }\n ... on NoReviewersSetForOwnerError {\n message\n ownerId\n }\n ... on NoReviewersSetForResourceError {\n message\n resourceId\n }\n ... on NoReviewersSetForGroupError {\n message\n groupId\n }\n ... on NoManagerSetForRequestingUserError {\n message\n }\n ... on MfaInvalidError {\n message\n }\n ... on BulkRequestTooLargeError {\n message\n }\n ... on ItemCannotBeRequestedError {\n message\n }\n ... on UserCannotRequestAccessForTargetGroupError {\n message\n groupId\n userId\n }\n ... on GroupNestingNotAllowedError {\n message\n fromGroupId\n toGroupId\n }\n ... on TargetUserHasNestedAccessError {\n message\n groupIds\n }\n ... on RequestReasonMissingError {\n message\n }\n ... on RequestFieldValueMissingError {\n message\n fieldName\n }\n ... on LinkedGroupNotRequestableError {\n message\n sourceGroupId\n groupBindingId\n }\n ... on RequestReasonBelowMinLengthError {\n message\n }\n\n }\n }\n": types.CreateRequestDocument,
17
+ "\n query GetCatalogItem($uuid: UUID!) {\n catalogItem(id: $uuid) {\n __typename\n ... on Connection {\n id\n displayName\n }\n ... on Resource {\n id\n displayName\n connection {\n id\n displayName\n }\n accessLevels{\n accessLevelName\n accessLevelRemoteId\n }\n }\n ...on Group {\n id\n name\n connection {\n id\n displayName\n }\n accessLevels{\n accessLevelName\n accessLevelRemoteId\n }\n }\n ... on UserFacingError {\n message\n }\n }\n }\n ": types.GetCatalogItemDocument,
17
18
  };
18
19
  function graphql(source) {
19
20
  var _a;
@@ -11752,6 +11752,48 @@ export type CreateRequestMutation = {
11752
11752
  userId: string;
11753
11753
  };
11754
11754
  };
11755
+ export type GetCatalogItemQueryVariables = Exact<{
11756
+ uuid: Scalars["UUID"]["input"];
11757
+ }>;
11758
+ export type GetCatalogItemQuery = {
11759
+ __typename?: "Query";
11760
+ catalogItem: {
11761
+ __typename: "Connection";
11762
+ id: string;
11763
+ displayName: string;
11764
+ } | {
11765
+ __typename: "Group";
11766
+ id: string;
11767
+ name: string;
11768
+ connection?: {
11769
+ __typename?: "Connection";
11770
+ id: string;
11771
+ displayName: string;
11772
+ } | null;
11773
+ accessLevels?: Array<{
11774
+ __typename?: "GroupAccessLevel";
11775
+ accessLevelName: string;
11776
+ accessLevelRemoteId: string;
11777
+ }> | null;
11778
+ } | {
11779
+ __typename: "Resource";
11780
+ id: string;
11781
+ displayName: string;
11782
+ connection?: {
11783
+ __typename?: "Connection";
11784
+ id: string;
11785
+ displayName: string;
11786
+ } | null;
11787
+ accessLevels?: Array<{
11788
+ __typename?: "ResourceAccessLevel";
11789
+ accessLevelName: string;
11790
+ accessLevelRemoteId: string;
11791
+ }> | null;
11792
+ } | {
11793
+ __typename: "UserFacingError";
11794
+ message: string;
11795
+ };
11796
+ };
11755
11797
  export declare const GetGroupDocument: DocumentNode<GetGroupQuery, GetGroupQueryVariables>;
11756
11798
  export declare const GetRequestDocument: DocumentNode<GetRequestQuery, GetRequestQueryVariables>;
11757
11799
  export declare const GetRequestsDocument: DocumentNode<GetRequestsQuery, GetRequestsQueryVariables>;
@@ -11762,3 +11804,4 @@ export declare const ResourceAccessLevelsDocument: DocumentNode<ResourceAccessLe
11762
11804
  export declare const GroupAccessLevelsDocument: DocumentNode<GroupAccessLevelsQuery, GroupAccessLevelsQueryVariables>;
11763
11805
  export declare const RequestDefaultsDocument: DocumentNode<RequestDefaultsQuery, RequestDefaultsQueryVariables>;
11764
11806
  export declare const CreateRequestDocument: DocumentNode<CreateRequestMutation, CreateRequestMutationVariables>;
11807
+ export declare const GetCatalogItemDocument: DocumentNode<GetCatalogItemQuery, GetCatalogItemQueryVariables>;
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GroupUserSource = exports.GroupUserSortByField = exports.GroupType = exports.GroupResourceSource = exports.GroupBindingsSortByField = exports.GroupBindingSuggestionsSortByField = exports.GeneralSettingType = exports.FiltersMatchMode = exports.FilterRule = exports.FactorType = exports.EventType = exports.EventSeverity = exports.ErrorNotificationSettingType = exports.EntityType = exports.ConnectionValidationStatus = exports.ConnectionValidationSeverity = exports.ConnectionType = exports.BundlesSortByField = exports.BundleItemsSortByField = exports.AuthType = exports.AuthSessionStatus = exports.AuthFlowType = exports.AssociatedItemsSortByField = exports.AssignmentsSortByField = exports.AppsSortByField = exports.AppType = exports.AppItemsSortByField = exports.AppCategory = exports.ApiAuthType = exports.ApiAccessLevel = exports.AldwinRole = exports.AccessType = exports.AccessRuleStatus = exports.AccessReviewUserWarningType = exports.AccessReviewType = exports.AccessReviewTab = exports.AccessReviewSummaryStatus = exports.AccessReviewStatus = exports.AccessReviewReviewerAssignmentPolicy = exports.AccessReviewItemsSortByField = exports.AccessReviewItemStatus = exports.AccessReviewItemOutcome = exports.AccessReviewGroupResourceVisibilityPolicy = exports.AccessReviewGroupItemKind = exports.AccessReviewEndUserView = exports.AccessReviewAssignedStatus = exports.AccessReviewAction = exports.AccessOption = exports.AccessChangeType = exports.AwsIdentityCenterImportSetting = void 0;
4
4
  exports.TagsSortByField = exports.TagFilterMatchMode = exports.SyncType = exports.SyncTaskStatus = exports.SubEventsSortByField = exports.StringFormatType = exports.SortDirection = exports.ServiceType = exports.SearchType = exports.RolePermissionTargetType = exports.RolePermission = exports.RoleAssignmentsSortByField = exports.RoleAssignmentSource = exports.RiskLevel = exports.ReviewerUserStatus = exports.ReviewerAction = exports.ReviewStageOperator = exports.ResourceUserSource = exports.ResourceUserSortByField = exports.ResourceType = exports.RequestsSortByField = exports.RequestType = exports.RequestTemplateCustomFieldType = exports.RequestStatus = exports.RequestMessageLevel = exports.RequestMessageCode = exports.RequestApprovalType = exports.RecommendationsSubscoreType = exports.RecommendationsMetricType = exports.RecommendationsFeedbackType = exports.RecommendationsEntityType = exports.PubsubPublishMessageType = exports.PubsubPublishMessageStatusCode = exports.PubsubPublishConnectionType = exports.ProvisionSource = exports.PropagationTaskType = exports.PropagationStatusCode = exports.OwnersSortByField = exports.OrganizationType = exports.OidcProviderType = exports.NotificationType = exports.MessageChannelType = exports.MfaProvider = exports.IntegrationType = exports.ImportSetting = exports.IdpConnectionUserAttributeUseAs = exports.IdpConnectionType = exports.IdentityCategory = exports.HrIdpStatus = exports.HealthStatus = void 0;
5
- exports.CreateRequestDocument = exports.RequestDefaultsDocument = exports.GroupAccessLevelsDocument = exports.ResourceAccessLevelsDocument = exports.PaginatedEntityDropdownDocument = exports.GetRequestableAppsQueryDocument = exports.CheckAuthSessionQueryDocument = exports.GetRequestsDocument = exports.GetRequestDocument = exports.GetGroupDocument = exports.RequestDecisionLevel = exports.WebhookPubsubPublishConnectionAuthType = exports.WebhookPubsubPublishConnectionApiKeyLocation = exports.Visibility = exports.VerifyFactorStatus = exports.UsersSortByField = exports.UserProductRole = exports.UserErrorType = exports.UsageAttributionType = exports.UiSource = exports.TimePeriod = exports.TimeBucket = exports.ThirdPartyProvider = exports.TaskTrigger = void 0;
5
+ exports.GetCatalogItemDocument = exports.CreateRequestDocument = exports.RequestDefaultsDocument = exports.GroupAccessLevelsDocument = exports.ResourceAccessLevelsDocument = exports.PaginatedEntityDropdownDocument = exports.GetRequestableAppsQueryDocument = exports.CheckAuthSessionQueryDocument = exports.GetRequestsDocument = exports.GetRequestDocument = exports.GetGroupDocument = exports.RequestDecisionLevel = exports.WebhookPubsubPublishConnectionAuthType = exports.WebhookPubsubPublishConnectionApiKeyLocation = exports.Visibility = exports.VerifyFactorStatus = exports.UsersSortByField = exports.UserProductRole = exports.UserErrorType = exports.UsageAttributionType = exports.UiSource = exports.TimePeriod = exports.TimeBucket = exports.ThirdPartyProvider = exports.TaskTrigger = void 0;
6
6
  var AwsIdentityCenterImportSetting;
7
7
  (function (AwsIdentityCenterImportSetting) {
8
8
  AwsIdentityCenterImportSetting["All"] = "ALL";
@@ -3496,3 +3496,186 @@ exports.CreateRequestDocument = {
3496
3496
  },
3497
3497
  ],
3498
3498
  };
3499
+ exports.GetCatalogItemDocument = {
3500
+ kind: "Document",
3501
+ definitions: [
3502
+ {
3503
+ kind: "OperationDefinition",
3504
+ operation: "query",
3505
+ name: { kind: "Name", value: "GetCatalogItem" },
3506
+ variableDefinitions: [
3507
+ {
3508
+ kind: "VariableDefinition",
3509
+ variable: { kind: "Variable", name: { kind: "Name", value: "uuid" } },
3510
+ type: {
3511
+ kind: "NonNullType",
3512
+ type: { kind: "NamedType", name: { kind: "Name", value: "UUID" } },
3513
+ },
3514
+ },
3515
+ ],
3516
+ selectionSet: {
3517
+ kind: "SelectionSet",
3518
+ selections: [
3519
+ {
3520
+ kind: "Field",
3521
+ name: { kind: "Name", value: "catalogItem" },
3522
+ arguments: [
3523
+ {
3524
+ kind: "Argument",
3525
+ name: { kind: "Name", value: "id" },
3526
+ value: {
3527
+ kind: "Variable",
3528
+ name: { kind: "Name", value: "uuid" },
3529
+ },
3530
+ },
3531
+ ],
3532
+ selectionSet: {
3533
+ kind: "SelectionSet",
3534
+ selections: [
3535
+ { kind: "Field", name: { kind: "Name", value: "__typename" } },
3536
+ {
3537
+ kind: "InlineFragment",
3538
+ typeCondition: {
3539
+ kind: "NamedType",
3540
+ name: { kind: "Name", value: "Connection" },
3541
+ },
3542
+ selectionSet: {
3543
+ kind: "SelectionSet",
3544
+ selections: [
3545
+ { kind: "Field", name: { kind: "Name", value: "id" } },
3546
+ {
3547
+ kind: "Field",
3548
+ name: { kind: "Name", value: "displayName" },
3549
+ },
3550
+ ],
3551
+ },
3552
+ },
3553
+ {
3554
+ kind: "InlineFragment",
3555
+ typeCondition: {
3556
+ kind: "NamedType",
3557
+ name: { kind: "Name", value: "Resource" },
3558
+ },
3559
+ selectionSet: {
3560
+ kind: "SelectionSet",
3561
+ selections: [
3562
+ { kind: "Field", name: { kind: "Name", value: "id" } },
3563
+ {
3564
+ kind: "Field",
3565
+ name: { kind: "Name", value: "displayName" },
3566
+ },
3567
+ {
3568
+ kind: "Field",
3569
+ name: { kind: "Name", value: "connection" },
3570
+ selectionSet: {
3571
+ kind: "SelectionSet",
3572
+ selections: [
3573
+ {
3574
+ kind: "Field",
3575
+ name: { kind: "Name", value: "id" },
3576
+ },
3577
+ {
3578
+ kind: "Field",
3579
+ name: { kind: "Name", value: "displayName" },
3580
+ },
3581
+ ],
3582
+ },
3583
+ },
3584
+ {
3585
+ kind: "Field",
3586
+ name: { kind: "Name", value: "accessLevels" },
3587
+ selectionSet: {
3588
+ kind: "SelectionSet",
3589
+ selections: [
3590
+ {
3591
+ kind: "Field",
3592
+ name: { kind: "Name", value: "accessLevelName" },
3593
+ },
3594
+ {
3595
+ kind: "Field",
3596
+ name: {
3597
+ kind: "Name",
3598
+ value: "accessLevelRemoteId",
3599
+ },
3600
+ },
3601
+ ],
3602
+ },
3603
+ },
3604
+ ],
3605
+ },
3606
+ },
3607
+ {
3608
+ kind: "InlineFragment",
3609
+ typeCondition: {
3610
+ kind: "NamedType",
3611
+ name: { kind: "Name", value: "Group" },
3612
+ },
3613
+ selectionSet: {
3614
+ kind: "SelectionSet",
3615
+ selections: [
3616
+ { kind: "Field", name: { kind: "Name", value: "id" } },
3617
+ { kind: "Field", name: { kind: "Name", value: "name" } },
3618
+ {
3619
+ kind: "Field",
3620
+ name: { kind: "Name", value: "connection" },
3621
+ selectionSet: {
3622
+ kind: "SelectionSet",
3623
+ selections: [
3624
+ {
3625
+ kind: "Field",
3626
+ name: { kind: "Name", value: "id" },
3627
+ },
3628
+ {
3629
+ kind: "Field",
3630
+ name: { kind: "Name", value: "displayName" },
3631
+ },
3632
+ ],
3633
+ },
3634
+ },
3635
+ {
3636
+ kind: "Field",
3637
+ name: { kind: "Name", value: "accessLevels" },
3638
+ selectionSet: {
3639
+ kind: "SelectionSet",
3640
+ selections: [
3641
+ {
3642
+ kind: "Field",
3643
+ name: { kind: "Name", value: "accessLevelName" },
3644
+ },
3645
+ {
3646
+ kind: "Field",
3647
+ name: {
3648
+ kind: "Name",
3649
+ value: "accessLevelRemoteId",
3650
+ },
3651
+ },
3652
+ ],
3653
+ },
3654
+ },
3655
+ ],
3656
+ },
3657
+ },
3658
+ {
3659
+ kind: "InlineFragment",
3660
+ typeCondition: {
3661
+ kind: "NamedType",
3662
+ name: { kind: "Name", value: "UserFacingError" },
3663
+ },
3664
+ selectionSet: {
3665
+ kind: "SelectionSet",
3666
+ selections: [
3667
+ {
3668
+ kind: "Field",
3669
+ name: { kind: "Name", value: "message" },
3670
+ },
3671
+ ],
3672
+ },
3673
+ },
3674
+ ],
3675
+ },
3676
+ },
3677
+ ],
3678
+ },
3679
+ },
3680
+ ],
3681
+ };
package/lib/lib/flags.js CHANGED
@@ -7,7 +7,7 @@ exports.SHARED_FLAGS = {
7
7
  id: core_1.Flags.string({
8
8
  multiple: false,
9
9
  char: "i",
10
- description: "The Opal ID of the resource. You can find this from the URL, e.g. https://opal.dev/resources/[ID]",
10
+ description: "The Opal ID of the asset. You can find this from the URL, e.g. https://opal.dev/resources/[ID]",
11
11
  }),
12
12
  accessLevelRemoteId: core_1.Flags.string({
13
13
  multiple: false,
@@ -43,4 +43,5 @@ export declare function setRequestDefaults(cmd: Command, client: ApolloClient<No
43
43
  export declare function promptForReason(metadata: RequestMetadata): Promise<void>;
44
44
  export declare function promptForExpiration(metadata: RequestMetadata): Promise<void>;
45
45
  export declare function submitFinalRequest(cmd: Command, client: ApolloClient<NormalizedCacheObject>, metadata: RequestMetadata): Promise<void>;
46
+ export declare function bypassRequestSelection(cmd: Command, client: ApolloClient<NormalizedCacheObject>, flagIds: string[], metadata: RequestMetadata): Promise<void>;
46
47
  export {};
@@ -9,6 +9,7 @@ exports.setRequestDefaults = setRequestDefaults;
9
9
  exports.promptForReason = promptForReason;
10
10
  exports.promptForExpiration = promptForExpiration;
11
11
  exports.submitFinalRequest = submitFinalRequest;
12
+ exports.bypassRequestSelection = bypassRequestSelection;
12
13
  const chalk_1 = require("chalk");
13
14
  const inquirer = require("inquirer");
14
15
  const graphql_1 = require("../graphql");
@@ -89,13 +90,12 @@ async function queryRequestableApps(cmd, client, input) {
89
90
  default:
90
91
  type = edge.node.__typename;
91
92
  }
92
- const label = `${edge.node.displayName} (${type})`;
93
93
  return {
94
- message: label,
94
+ message: `${edge.node.displayName} [${type}]`,
95
95
  value: {
96
96
  id: edge.node.id,
97
- name: label,
98
- toString: () => label,
97
+ name: edge.node.displayName,
98
+ toString: () => edge.node.displayName,
99
99
  },
100
100
  };
101
101
  });
@@ -162,11 +162,10 @@ async function queryRequestableAssets(cmd, client, appId, input) {
162
162
  const name = ((_a = item.resource) === null || _a === void 0 ? void 0 : _a.name) || ((_b = item.group) === null || _b === void 0 ? void 0 : _b.name);
163
163
  const id = ((_c = item.resource) === null || _c === void 0 ? void 0 : _c.id) || ((_d = item.group) === null || _d === void 0 ? void 0 : _d.id);
164
164
  const type = ((_e = item.resource) === null || _e === void 0 ? void 0 : _e.__typename) || ((_f = item.group) === null || _f === void 0 ? void 0 : _f.__typename);
165
- const label = `${name} (${type})`;
166
165
  return {
167
- message: label,
166
+ message: `${name} [${type}]`,
168
167
  value: {
169
- name: label || "",
168
+ name: name || "",
170
169
  id: id || "",
171
170
  type: ((_g = item.resource) === null || _g === void 0 ? void 0 : _g.__typename) || ((_h = item.group) === null || _h === void 0 ? void 0 : _h.__typename) || "",
172
171
  },
@@ -428,57 +427,56 @@ async function createRequest(cmd, client, requestedResources, requestedGroups, r
428
427
  durationInMinutes: durationInMinutes,
429
428
  },
430
429
  });
431
- let x;
432
430
  switch ((_a = resp.data) === null || _a === void 0 ? void 0 : _a.createRequest.__typename) {
433
431
  case "CreateRequestResult":
434
432
  return (_b = resp.data) === null || _b === void 0 ? void 0 : _b.createRequest.request;
435
433
  case "RequestDurationTooLargeError":
436
- x = cmd.error((_c = resp.data) === null || _c === void 0 ? void 0 : _c.createRequest.message);
434
+ cmd.log((_c = resp.data) === null || _c === void 0 ? void 0 : _c.createRequest.message);
437
435
  break;
438
436
  case "RequestRequiresUserAuthTokenForConnectionError":
439
- x = cmd.error((_d = resp.data) === null || _d === void 0 ? void 0 : _d.createRequest.message);
437
+ cmd.log((_d = resp.data) === null || _d === void 0 ? void 0 : _d.createRequest.message);
440
438
  break;
441
439
  case "NoReviewersSetForOwnerError":
442
- x = cmd.error((_e = resp.data) === null || _e === void 0 ? void 0 : _e.createRequest.message);
440
+ cmd.log((_e = resp.data) === null || _e === void 0 ? void 0 : _e.createRequest.message);
443
441
  break;
444
442
  case "NoReviewersSetForResourceError":
445
- x = cmd.error((_f = resp.data) === null || _f === void 0 ? void 0 : _f.createRequest.message);
443
+ cmd.log((_f = resp.data) === null || _f === void 0 ? void 0 : _f.createRequest.message);
446
444
  break;
447
445
  case "NoReviewersSetForGroupError":
448
- x = cmd.error((_g = resp.data) === null || _g === void 0 ? void 0 : _g.createRequest.message);
446
+ cmd.log((_g = resp.data) === null || _g === void 0 ? void 0 : _g.createRequest.message);
449
447
  break;
450
448
  case "NoManagerSetForRequestingUserError":
451
- x = cmd.error((_h = resp.data) === null || _h === void 0 ? void 0 : _h.createRequest.message);
449
+ cmd.log((_h = resp.data) === null || _h === void 0 ? void 0 : _h.createRequest.message);
452
450
  break;
453
451
  case "MfaInvalidError":
454
- x = cmd.error((_j = resp.data) === null || _j === void 0 ? void 0 : _j.createRequest.message);
452
+ cmd.log((_j = resp.data) === null || _j === void 0 ? void 0 : _j.createRequest.message);
455
453
  break;
456
454
  case "BulkRequestTooLargeError":
457
- x = cmd.error((_k = resp.data) === null || _k === void 0 ? void 0 : _k.createRequest.message);
455
+ cmd.log((_k = resp.data) === null || _k === void 0 ? void 0 : _k.createRequest.message);
458
456
  break;
459
457
  case "ItemCannotBeRequestedError":
460
- x = cmd.error((_l = resp.data) === null || _l === void 0 ? void 0 : _l.createRequest.message);
458
+ cmd.log((_l = resp.data) === null || _l === void 0 ? void 0 : _l.createRequest.message);
461
459
  break;
462
460
  case "UserCannotRequestAccessForTargetGroupError":
463
- x = cmd.error((_m = resp.data) === null || _m === void 0 ? void 0 : _m.createRequest.message);
461
+ cmd.log((_m = resp.data) === null || _m === void 0 ? void 0 : _m.createRequest.message);
464
462
  break;
465
463
  case "GroupNestingNotAllowedError":
466
- x = cmd.error((_o = resp.data) === null || _o === void 0 ? void 0 : _o.createRequest.message);
464
+ cmd.log((_o = resp.data) === null || _o === void 0 ? void 0 : _o.createRequest.message);
467
465
  break;
468
466
  case "TargetUserHasNestedAccessError":
469
- x = cmd.error((_p = resp.data) === null || _p === void 0 ? void 0 : _p.createRequest.message);
467
+ cmd.log((_p = resp.data) === null || _p === void 0 ? void 0 : _p.createRequest.message);
470
468
  break;
471
469
  case "RequestReasonMissingError":
472
- x = cmd.error((_q = resp.data) === null || _q === void 0 ? void 0 : _q.createRequest.message);
470
+ cmd.log((_q = resp.data) === null || _q === void 0 ? void 0 : _q.createRequest.message);
473
471
  break;
474
472
  case "RequestFieldValueMissingError":
475
- x = cmd.error((_r = resp.data) === null || _r === void 0 ? void 0 : _r.createRequest.message);
473
+ cmd.log((_r = resp.data) === null || _r === void 0 ? void 0 : _r.createRequest.message);
476
474
  break;
477
475
  case "LinkedGroupNotRequestableError":
478
- x = cmd.error((_s = resp.data) === null || _s === void 0 ? void 0 : _s.createRequest.message);
476
+ cmd.log((_s = resp.data) === null || _s === void 0 ? void 0 : _s.createRequest.message);
479
477
  break;
480
478
  case "RequestReasonBelowMinLengthError":
481
- x = cmd.error((_t = resp.data) === null || _t === void 0 ? void 0 : _t.createRequest.message);
479
+ cmd.log((_t = resp.data) === null || _t === void 0 ? void 0 : _t.createRequest.message);
482
480
  break;
483
481
  }
484
482
  }
@@ -488,6 +486,44 @@ async function createRequest(cmd, client, requestedResources, requestedGroups, r
488
486
  }
489
487
  }
490
488
  }
489
+ const CATALOG_ITEM = (0, graphql_1.graphql)(`
490
+ query GetCatalogItem($uuid: UUID!) {
491
+ catalogItem(id: $uuid) {
492
+ __typename
493
+ ... on Connection {
494
+ id
495
+ displayName
496
+ }
497
+ ... on Resource {
498
+ id
499
+ displayName
500
+ connection {
501
+ id
502
+ displayName
503
+ }
504
+ accessLevels{
505
+ accessLevelName
506
+ accessLevelRemoteId
507
+ }
508
+ }
509
+ ...on Group {
510
+ id
511
+ name
512
+ connection {
513
+ id
514
+ displayName
515
+ }
516
+ accessLevels{
517
+ accessLevelName
518
+ accessLevelRemoteId
519
+ }
520
+ }
521
+ ... on UserFacingError {
522
+ message
523
+ }
524
+ }
525
+ }
526
+ `);
491
527
  // Helper functions
492
528
  async function selectRequestableItems(cmd, client, requestMap) {
493
529
  const initialChoices = (await queryRequestableApps(cmd, client, "")) || [];
@@ -665,10 +701,16 @@ async function promptForReason(metadata) {
665
701
  async function promptForExpiration(metadata) {
666
702
  var _a, _b;
667
703
  const durations = ((_b = (_a = metadata.requestDefaults) === null || _a === void 0 ? void 0 : _a.durationOptions) === null || _b === void 0 ? void 0 : _b.map((option) => {
668
- const label = option.durationInMinutes ===
669
- metadata.requestDefaults.recommendedDurationInMinutes
670
- ? `${option.label} (Recommended)`
671
- : option.label;
704
+ var _a;
705
+ let label = option.label;
706
+ if (option.durationInMinutes ===
707
+ ((_a = metadata.requestDefaults) === null || _a === void 0 ? void 0 : _a.maxDurationInMinutes)) {
708
+ label = `${label} (MAX)`;
709
+ }
710
+ if (option.durationInMinutes ===
711
+ metadata.requestDefaults.recommendedDurationInMinutes) {
712
+ label = `${label} (RECOMMENDED)`;
713
+ }
672
714
  return {
673
715
  message: label,
674
716
  value: {
@@ -690,7 +732,7 @@ async function promptForExpiration(metadata) {
690
732
  let selected = await expirationSelect.run();
691
733
  switch (selected.label) {
692
734
  case "Custom": {
693
- selected = await setCustomDuration();
735
+ selected = await setCustomDuration(metadata);
694
736
  break;
695
737
  }
696
738
  case "Permanent": {
@@ -701,7 +743,36 @@ async function promptForExpiration(metadata) {
701
743
  metadata.durationInMinutes = selected.durationInMinutes;
702
744
  metadata.durationLabel = selected.label;
703
745
  }
704
- async function setCustomDuration() {
746
+ function getDurationNumbers(duration) {
747
+ const d = +duration.days || 0;
748
+ const h = +duration.hours || 0;
749
+ const m = +duration.minutes || 0;
750
+ return { d, h, m };
751
+ }
752
+ function getDurationInMinutes(duration) {
753
+ const { d, h, m } = getDurationNumbers(duration);
754
+ const minutesInDay = 1440; // 24 hours * 60 minutes
755
+ const minutesInHour = 60;
756
+ return d * minutesInDay + h * minutesInHour + m;
757
+ }
758
+ function getDHMFromMinutes(minutes) {
759
+ const label = [];
760
+ const d = Math.floor(minutes / 1440);
761
+ if (d > 0) {
762
+ label.push(`${d}d`);
763
+ }
764
+ const remainingMinutes = minutes % 1440;
765
+ const h = Math.floor(remainingMinutes / 60);
766
+ if (h > 0) {
767
+ label.push(`${h}h`);
768
+ }
769
+ const m = remainingMinutes % 60;
770
+ if (m > 0) {
771
+ label.push(`${m}m`);
772
+ }
773
+ return label.join(" ");
774
+ }
775
+ async function setCustomDuration(metadata) {
705
776
  const durationForm = new Form({
706
777
  name: "user",
707
778
  message: "Please set a custom access duration:",
@@ -711,31 +782,27 @@ async function setCustomDuration() {
711
782
  { name: "minutes", message: "Minutes", initial: "0" },
712
783
  ],
713
784
  validate: (answer) => {
714
- const days = Number.parseInt(answer.days);
715
- const hours = Number.parseInt(answer.hours);
716
- const minutes = Number.parseInt(answer.minutes);
717
- if (days < 0 ||
718
- hours < 0 ||
719
- minutes < 0 ||
720
- (days === 0 && hours === 0 && minutes === 0)) {
785
+ var _a, _b, _c;
786
+ const { d, h, m } = getDurationNumbers(answer);
787
+ const durationInMinutes = getDurationInMinutes(answer);
788
+ if (d < 0 || h < 0 || m < 0 || d + h + m === 0 || (h > 23 && m > 59)) {
721
789
  return "Please enter a valid duration.";
722
790
  }
791
+ if (((_a = metadata.requestDefaults) === null || _a === void 0 ? void 0 : _a.maxDurationInMinutes) &&
792
+ durationInMinutes > ((_b = metadata.requestDefaults) === null || _b === void 0 ? void 0 : _b.maxDurationInMinutes)) {
793
+ const maxDHM = getDHMFromMinutes((_c = metadata.requestDefaults) === null || _c === void 0 ? void 0 : _c.maxDurationInMinutes);
794
+ return `The max duration for the selected assets is ${maxDHM}.`;
795
+ }
723
796
  return true;
724
797
  },
798
+ return: (answer) => {
799
+ return getDurationInMinutes(answer);
800
+ },
725
801
  });
726
- const duration = await durationForm.run();
727
- // Convert to minutes, define the new custom label
728
- const durationInMinutes = duration.days * 1440 + duration.hours * 60 + duration.minutes;
729
- let durationLabel = "";
730
- if (duration.days > 0) {
731
- durationLabel += `${duration.days}d `;
732
- }
733
- if (duration.hours > 0) {
734
- durationLabel += `${duration.hours}h `;
735
- }
736
- if (duration.minutes > 0) {
737
- durationLabel += `${duration.minutes}m`;
738
- }
802
+ const durationResult = await durationForm.run();
803
+ const { d, h, m } = getDurationNumbers(durationResult);
804
+ const durationInMinutes = getDurationInMinutes(durationResult);
805
+ const durationLabel = getDHMFromMinutes(durationInMinutes);
739
806
  return {
740
807
  durationInMinutes: durationInMinutes,
741
808
  label: durationLabel,
@@ -815,3 +882,75 @@ async function submitFinalRequest(cmd, client, metadata) {
815
882
  }
816
883
  }
817
884
  }
885
+ async function bypassRequestSelection(cmd, client, flagIds, metadata) {
886
+ var _a, _b;
887
+ try {
888
+ for (const id of flagIds) {
889
+ const resp = await client.query({
890
+ query: CATALOG_ITEM,
891
+ variables: {
892
+ uuid: id || "",
893
+ },
894
+ fetchPolicy: "network-only", // to avoid caching
895
+ });
896
+ switch (resp.data.catalogItem.__typename) {
897
+ case "Resource": {
898
+ const resourceName = resp.data.catalogItem.displayName;
899
+ const roles = (resp.data.catalogItem.accessLevels || [])
900
+ // TODO: Support okta azure apps ?.filter((role) => role.accessLevelName !== "") // This assumes length == 1
901
+ .map((role) => ({
902
+ id: role.accessLevelRemoteId,
903
+ name: role.accessLevelName,
904
+ }));
905
+ if (roles.length > 0 &&
906
+ !(roles.length === 1 && roles[0].name === "")) {
907
+ cmd.log(`Roles not implemented yet for resource ${resourceName}. Skipping roles selection.`); //TODO: Implement roles support
908
+ continue;
909
+ }
910
+ const appId = ((_a = resp.data.catalogItem.connection) === null || _a === void 0 ? void 0 : _a.id) || "";
911
+ if (!(appId in metadata.requestMap)) {
912
+ metadata.requestMap[appId] = {
913
+ appName: ((_b = resp.data.catalogItem.connection) === null || _b === void 0 ? void 0 : _b.displayName) || "Unknown App",
914
+ assets: {},
915
+ };
916
+ }
917
+ const assetEntry = metadata.requestMap[appId].assets[id];
918
+ if (!assetEntry) {
919
+ metadata.requestMap[appId].assets[id] = {
920
+ assetName: resourceName,
921
+ type: "Resource",
922
+ roles: {},
923
+ };
924
+ }
925
+ if (roles) {
926
+ if (!metadata.requestMap[appId].assets[id].roles) {
927
+ metadata.requestMap[appId].assets[id].roles = {};
928
+ }
929
+ for (const role of roles) {
930
+ metadata.requestMap[appId].assets[id].roles[role.id] = {
931
+ roleName: role.name,
932
+ };
933
+ }
934
+ }
935
+ break;
936
+ }
937
+ case "Group": {
938
+ //TODO
939
+ break;
940
+ }
941
+ case "Connection": {
942
+ //TODO
943
+ break;
944
+ }
945
+ default:
946
+ cmd.error("Unknown error occurred.");
947
+ }
948
+ }
949
+ }
950
+ catch (error) {
951
+ if (error instanceof Error || typeof error === "string") {
952
+ cmd.error(error);
953
+ }
954
+ }
955
+ return;
956
+ }
@@ -3,8 +3,8 @@ import type { Command } from "@oclif/core/lib/command";
3
3
  import type { GetRequestQuery, GetRequestsQuery } from "../graphql/graphql";
4
4
  import type { RequestMap, RequestMetadata } from "../lib/requests";
5
5
  export declare function headerMessage(cmd: Command): void;
6
- export declare function treeifyRequestMap(requestMap: RequestMap): string;
6
+ export declare function treeifyRequestMap(cmd: Command, requestMap: RequestMap): void;
7
7
  export declare function displayFinalRequestSummary(cmd: Command, metadata: RequestMetadata): void;
8
8
  export declare function getStyledStatus(status: string): string;
9
9
  export declare function displayRequestDetails(cmd: Command, requestResp: ApolloQueryResult<GetRequestQuery>): void;
10
- export declare function displayRequestList(cmd: Command, requestResp: ApolloQueryResult<GetRequestsQuery>): void;
10
+ export declare function displayRequestListTable(cmd: Command, requestResp: ApolloQueryResult<GetRequestsQuery>): void;
@@ -5,48 +5,64 @@ exports.treeifyRequestMap = treeifyRequestMap;
5
5
  exports.displayFinalRequestSummary = displayFinalRequestSummary;
6
6
  exports.getStyledStatus = getStyledStatus;
7
7
  exports.displayRequestDetails = displayRequestDetails;
8
- exports.displayRequestList = displayRequestList;
8
+ exports.displayRequestListTable = displayRequestListTable;
9
9
  const chalk_1 = require("chalk");
10
- const treeify = require("object-treeify");
11
10
  const Table = require("cli-table3");
11
+ const treeify = require("object-treeify").default;
12
12
  function headerMessage(cmd) {
13
13
  console.clear();
14
14
  cmd.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
15
15
  cmd.log("Opal Access Request ✏️");
16
16
  cmd.log("Press Ctrl+C to cancel at any time.\n");
17
17
  }
18
- function treeifyRequestMap(requestMap) {
19
- const requestTree = {};
20
- // Create a tree structure from the requestMap
21
- // Iterate over apps
18
+ function treeifyRequestMap(cmd, requestMap) {
19
+ // Configuration options for treeify
20
+ const options = {
21
+ joined: true,
22
+ spacerNoNeighbour: " ",
23
+ spacerNeighbour: "│ ",
24
+ keyNoNeighbour: "└── ",
25
+ keyNeighbour: "├── ",
26
+ separator: "",
27
+ };
22
28
  for (const [_appId, appNode] of Object.entries(requestMap)) {
23
- const appKey = `🔧${appNode.appName}`;
24
- requestTree[appKey] = {}; // Initialize the app key
25
- // Iterate over assets
29
+ const assetsTree = {};
26
30
  for (const [_assetId, assetNode] of Object.entries(appNode.assets)) {
27
- const assetKey = `📦${assetNode.assetName}`;
31
+ const assetKey = `${assetNode.assetName} ${chalk_1.default.dim(`[${assetNode.type}]`)}`;
28
32
  if (assetNode.roles !== undefined) {
29
- // If no roles were previously selected
30
- requestTree[appKey][assetKey] = {}; // Initialize the asset key
31
- // Iterate over roles
33
+ assetsTree[assetKey] = {};
32
34
  for (const [_roleId, roleNode] of Object.entries(assetNode.roles)) {
33
- requestTree[appKey][assetKey][roleNode.roleName] = null; // Initialize the role key
35
+ const roleKey = `${roleNode.roleName} ${chalk_1.default.dim("[Role]")}`;
36
+ assetsTree[assetKey][roleKey] = null;
34
37
  }
35
38
  }
36
39
  else {
37
- requestTree[appKey][assetKey] = null;
40
+ assetsTree[assetKey] = null;
38
41
  }
39
42
  }
43
+ // Render tree for this app's assets
44
+ const assetsTreeString = treeify(assetsTree, options);
45
+ // Print App title first (without tree lines)
46
+ cmd.log(`${chalk_1.default.bold(appNode.appName)} ${chalk_1.default.dim("[App]")}`);
47
+ // Print its assets/roles indented underneath
48
+ cmd.log(assetsTreeString);
40
49
  }
41
- return String(treeify(requestTree));
50
+ cmd.log();
42
51
  }
43
52
  function displayFinalRequestSummary(cmd, metadata) {
44
- headerMessage(cmd);
45
- cmd.log("Final Summary of Request\n");
46
- const requestedAssets = treeifyRequestMap(metadata.requestMap);
47
- const table = new Table();
48
- table.push(["Requested Assets", requestedAssets], ["Reason", metadata.reason], ["Expiration", metadata.durationLabel]);
49
- cmd.log(table.toString());
53
+ console.clear();
54
+ cmd.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
55
+ cmd.log("Final Summary of Request ✏️");
56
+ cmd.log("Press Ctrl+C to cancel at any time.\n");
57
+ cmd.log();
58
+ treeifyRequestMap(cmd, metadata.requestMap);
59
+ const durationInMinutes = metadata.durationInMinutes;
60
+ cmd.log(`Duration: ${durationInMinutes ? formatDuration(durationInMinutes) : "Permanent"}`);
61
+ const reason = metadata.reason;
62
+ if (reason) {
63
+ cmd.log(`Reason: "${chalk_1.default.italic(reason)}"`);
64
+ }
65
+ cmd.log();
50
66
  }
51
67
  function getStyledStatus(status) {
52
68
  switch (status) {
@@ -83,9 +99,7 @@ function displayRequestDetails(cmd, requestResp) {
83
99
  cmd.log(`${chalk_1.default.bold("Requested by:")} ${requester} ${chalk_1.default.gray("->")} ${chalk_1.default.bold("Requested for:")} ${targetUser}`);
84
100
  }
85
101
  const durationInMinutes = requestResp.data.request.request.durationInMinutes;
86
- if (durationInMinutes) {
87
- cmd.log(`${chalk_1.default.bold("Duration:")} ${formatDuration(durationInMinutes)}`);
88
- }
102
+ cmd.log(`${chalk_1.default.bold("Duration:")} ${durationInMinutes ? formatDuration(durationInMinutes) : "Permanent"}`);
89
103
  const reason = requestResp.data.request.request.reason;
90
104
  if (reason) {
91
105
  cmd.log(`${chalk_1.default.bold("Reason:")} "${chalk_1.default.italic(reason)}"`);
@@ -110,7 +124,7 @@ function displayRequestDetails(cmd, requestResp) {
110
124
  }
111
125
  }
112
126
  }
113
- function displayRequestList(cmd, requestResp) {
127
+ function displayRequestListTable(cmd, requestResp) {
114
128
  var _a, _b, _c, _d, _e;
115
129
  switch (requestResp.data.requests.__typename) {
116
130
  case "RequestsResult": {
@@ -133,10 +147,9 @@ function displayRequestList(cmd, requestResp) {
133
147
  const targetUser = (_a = request.targetUser) === null || _a === void 0 ? void 0 : _a.displayName;
134
148
  const reason = request.reason;
135
149
  const status = request.status;
136
- let formattedDuration = "";
137
- if (request.durationInMinutes) {
138
- formattedDuration = formatDuration(request.durationInMinutes);
139
- }
150
+ const formattedDuration = request.durationInMinutes
151
+ ? formatDuration(request.durationInMinutes)
152
+ : "Permanent";
140
153
  const requestedResources = (_c = (_b = request.requestedResources) === null || _b === void 0 ? void 0 : _b.map((resource) => {
141
154
  var _a, _b, _c;
142
155
  if (((_a = resource.resource) === null || _a === void 0 ? void 0 : _a.__typename) === "Resource") {
@@ -365,7 +365,7 @@
365
365
  },
366
366
  "id": {
367
367
  "char": "i",
368
- "description": "The Opal ID of the resource. You can find this from the URL, e.g. https://opal.dev/resources/[ID]",
368
+ "description": "The Opal ID of the asset. You can find this from the URL, e.g. https://opal.dev/resources/[ID]",
369
369
  "name": "id",
370
370
  "hasDynamicHelp": false,
371
371
  "multiple": false,
@@ -407,7 +407,7 @@
407
407
  },
408
408
  "id": {
409
409
  "char": "i",
410
- "description": "The Opal ID of the resource. You can find this from the URL, e.g. https://opal.dev/resources/[ID]",
410
+ "description": "The Opal ID of the asset. You can find this from the URL, e.g. https://opal.dev/resources/[ID]",
411
411
  "name": "id",
412
412
  "hasDynamicHelp": false,
413
413
  "multiple": false,
@@ -471,7 +471,7 @@
471
471
  },
472
472
  "id": {
473
473
  "char": "i",
474
- "description": "The Opal ID of the resource. You can find this from the URL, e.g. https://opal.dev/resources/[ID]",
474
+ "description": "The Opal ID of the asset. You can find this from the URL, e.g. https://opal.dev/resources/[ID]",
475
475
  "name": "id",
476
476
  "hasDynamicHelp": false,
477
477
  "multiple": false,
@@ -537,7 +537,7 @@
537
537
  },
538
538
  "id": {
539
539
  "char": "i",
540
- "description": "The Opal ID of the resource. You can find this from the URL, e.g. https://opal.dev/resources/[ID]",
540
+ "description": "The Opal ID of the asset. You can find this from the URL, e.g. https://opal.dev/resources/[ID]",
541
541
  "name": "id",
542
542
  "hasDynamicHelp": false,
543
543
  "multiple": false,
@@ -598,7 +598,23 @@
598
598
  "aliases": [],
599
599
  "args": {},
600
600
  "description": "Creates an Opal access request via an interactive form",
601
- "flags": {},
601
+ "flags": {
602
+ "help": {
603
+ "char": "h",
604
+ "description": "Show CLI help.",
605
+ "name": "help",
606
+ "allowNo": false,
607
+ "type": "boolean"
608
+ },
609
+ "id": {
610
+ "char": "i",
611
+ "description": "The id of the asset (resource, group) to request access to. Append a role ID using a colon if needed, e.g. `--id 123:456`.",
612
+ "name": "id",
613
+ "hasDynamicHelp": false,
614
+ "multiple": true,
615
+ "type": "option"
616
+ }
617
+ },
602
618
  "hasDynamicHelp": false,
603
619
  "hidden": true,
604
620
  "hiddenAliases": [],
@@ -634,7 +650,7 @@
634
650
  },
635
651
  "id": {
636
652
  "char": "i",
637
- "description": "The Opal ID of the resource. You can find this from the URL, e.g. https://opal.dev/resources/[ID]",
653
+ "description": "The Opal ID of the asset. You can find this from the URL, e.g. https://opal.dev/resources/[ID]",
638
654
  "name": "id",
639
655
  "hasDynamicHelp": false,
640
656
  "multiple": false,
@@ -741,7 +757,7 @@
741
757
  },
742
758
  "id": {
743
759
  "char": "i",
744
- "description": "The Opal ID of the resource. You can find this from the URL, e.g. https://opal.dev/resources/[ID]",
760
+ "description": "The Opal ID of the asset. You can find this from the URL, e.g. https://opal.dev/resources/[ID]",
745
761
  "name": "id",
746
762
  "hasDynamicHelp": false,
747
763
  "multiple": false,
@@ -808,7 +824,7 @@
808
824
  },
809
825
  "id": {
810
826
  "char": "i",
811
- "description": "The Opal ID of the resource. You can find this from the URL, e.g. https://opal.dev/resources/[ID]",
827
+ "description": "The Opal ID of the asset. You can find this from the URL, e.g. https://opal.dev/resources/[ID]",
812
828
  "name": "id",
813
829
  "hasDynamicHelp": false,
814
830
  "multiple": false,
@@ -883,7 +899,7 @@
883
899
  },
884
900
  "id": {
885
901
  "char": "i",
886
- "description": "The Opal ID of the resource. You can find this from the URL, e.g. https://opal.dev/resources/[ID]",
902
+ "description": "The Opal ID of the asset. You can find this from the URL, e.g. https://opal.dev/resources/[ID]",
887
903
  "name": "id",
888
904
  "hasDynamicHelp": false,
889
905
  "multiple": false,
@@ -932,7 +948,7 @@
932
948
  },
933
949
  "id": {
934
950
  "char": "i",
935
- "description": "The Opal ID of the resource. You can find this from the URL, e.g. https://opal.dev/resources/[ID]",
951
+ "description": "The Opal ID of the asset. You can find this from the URL, e.g. https://opal.dev/resources/[ID]",
936
952
  "name": "id",
937
953
  "hasDynamicHelp": false,
938
954
  "multiple": false,
@@ -971,5 +987,5 @@
971
987
  ]
972
988
  }
973
989
  },
974
- "version": "3.1.1-beta.55edef9"
990
+ "version": "3.1.1-beta.5641f4d"
975
991
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "opal-security",
3
3
  "description": "Opal allows you to centrally manage access to all of your sensitive systems.",
4
- "version": "3.1.1-beta.55edef9",
4
+ "version": "3.1.1-beta.5641f4d",
5
5
  "author": "Stephen Cobbe",
6
6
  "bin": {
7
7
  "opal": "./bin/run"
@@ -24,6 +24,7 @@
24
24
  "lodash": "^4.17.21",
25
25
  "moment": "^2.30.1",
26
26
  "node-fetch": "^2.6.7",
27
+ "object-treeify": "^5.0.1",
27
28
  "open": "^8.0.4",
28
29
  "openid-client": "^5.6.5",
29
30
  "prettyjson": "^1.2.1",