opal-security 3.1.1-beta.e5e99da → 3.1.1-beta.f2bce00
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 +18 -18
- package/lib/commands/request/create.js +3 -3
- package/lib/commands/request/get.d.ts +2 -0
- package/lib/commands/request/get.js +28 -3
- package/lib/commands/request/list.d.ts +8 -1
- package/lib/commands/request/list.js +113 -6
- package/lib/graphql/gql.d.ts +21 -6
- package/lib/graphql/gql.js +6 -3
- package/lib/graphql/graphql.d.ts +210 -94
- package/lib/graphql/graphql.js +1295 -347
- package/lib/lib/requests.d.ts +1 -0
- package/lib/lib/requests.js +368 -108
- package/lib/utils/displays.d.ts +4 -0
- package/lib/utils/displays.js +153 -1
- package/oclif.manifest.json +52 -4
- package/package.json +3 -1
package/lib/lib/requests.d.ts
CHANGED
package/lib/lib/requests.js
CHANGED
|
@@ -11,7 +11,7 @@ exports.promptForExpiration = promptForExpiration;
|
|
|
11
11
|
exports.submitFinalRequest = submitFinalRequest;
|
|
12
12
|
const inquirer = require("inquirer");
|
|
13
13
|
const graphql_1 = require("../graphql");
|
|
14
|
-
|
|
14
|
+
const { AutoComplete, Select, prompt, Form } = require("enquirer");
|
|
15
15
|
function createEmptyRequestMetadata() {
|
|
16
16
|
// Initialize with empty defaults
|
|
17
17
|
const requestDefaults = {
|
|
@@ -73,18 +73,23 @@ async function queryRequestableApps(cmd, client, input) {
|
|
|
73
73
|
});
|
|
74
74
|
return (_b = (_a = resp === null || resp === void 0 ? void 0 : resp.data) === null || _a === void 0 ? void 0 : _a.appsV2) === null || _b === void 0 ? void 0 : _b.edges.map((edge) => {
|
|
75
75
|
let type = undefined;
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
76
|
+
switch (edge.node.__typename) {
|
|
77
|
+
case "Resource":
|
|
78
|
+
type = edge.node.resourceType;
|
|
79
|
+
break;
|
|
80
|
+
case "Connection":
|
|
81
|
+
type = edge.node.connectionType;
|
|
82
|
+
break;
|
|
83
|
+
default:
|
|
84
|
+
type = edge.node.__typename;
|
|
81
85
|
}
|
|
82
86
|
const label = `${edge.node.displayName} (${type})`;
|
|
83
87
|
return {
|
|
84
|
-
|
|
88
|
+
message: label,
|
|
85
89
|
value: {
|
|
86
90
|
id: edge.node.id,
|
|
87
91
|
name: label,
|
|
92
|
+
toString: () => label,
|
|
88
93
|
},
|
|
89
94
|
};
|
|
90
95
|
});
|
|
@@ -147,16 +152,17 @@ async function queryRequestableAssets(cmd, client, appId, input) {
|
|
|
147
152
|
switch (resp.data.app.__typename) {
|
|
148
153
|
case "App":
|
|
149
154
|
return (_d = (_c = (_b = (_a = resp.data) === null || _a === void 0 ? void 0 : _a.app) === null || _b === void 0 ? void 0 : _b.items) === null || _c === void 0 ? void 0 : _c.items) === null || _d === void 0 ? void 0 : _d.map((item) => {
|
|
150
|
-
var _a, _b, _c, _d, _e, _f;
|
|
155
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
151
156
|
const name = ((_a = item.resource) === null || _a === void 0 ? void 0 : _a.name) || ((_b = item.group) === null || _b === void 0 ? void 0 : _b.name);
|
|
152
157
|
const id = ((_c = item.resource) === null || _c === void 0 ? void 0 : _c.id) || ((_d = item.group) === null || _d === void 0 ? void 0 : _d.id);
|
|
153
158
|
const type = ((_e = item.resource) === null || _e === void 0 ? void 0 : _e.__typename) || ((_f = item.group) === null || _f === void 0 ? void 0 : _f.__typename);
|
|
154
159
|
const label = `${name} (${type})`;
|
|
155
160
|
return {
|
|
156
|
-
|
|
161
|
+
message: label,
|
|
157
162
|
value: {
|
|
158
|
-
name: label,
|
|
159
|
-
id: id,
|
|
163
|
+
name: label || "",
|
|
164
|
+
id: id || "",
|
|
165
|
+
type: ((_g = item.resource) === null || _g === void 0 ? void 0 : _g.__typename) || ((_h = item.group) === null || _h === void 0 ? void 0 : _h.__typename) || "",
|
|
160
166
|
},
|
|
161
167
|
};
|
|
162
168
|
});
|
|
@@ -182,7 +188,6 @@ const RESOURCE_ROLES_QUERY = (0, graphql_1.graphql)(`
|
|
|
182
188
|
__typename
|
|
183
189
|
... on ResourceAccessLevelsResult {
|
|
184
190
|
accessLevels {
|
|
185
|
-
__typename
|
|
186
191
|
... on ResourceAccessLevel {
|
|
187
192
|
accessLevelName
|
|
188
193
|
accessLevelRemoteId
|
|
@@ -195,34 +200,82 @@ const RESOURCE_ROLES_QUERY = (0, graphql_1.graphql)(`
|
|
|
195
200
|
}
|
|
196
201
|
}
|
|
197
202
|
`);
|
|
198
|
-
|
|
199
|
-
|
|
203
|
+
const GROUP_ROLES_QUERY = (0, graphql_1.graphql)(`
|
|
204
|
+
query GroupAccessLevels($groupId: GroupId!) {
|
|
205
|
+
groupAccessLevels(
|
|
206
|
+
input: { groupId: $groupId }
|
|
207
|
+
) {
|
|
208
|
+
... on GroupAccessLevelsResult {
|
|
209
|
+
groupId
|
|
210
|
+
accessLevels {
|
|
211
|
+
... on GroupAccessLevel {
|
|
212
|
+
accessLevelName
|
|
213
|
+
accessLevelRemoteId
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
`);
|
|
220
|
+
async function queryAssetRoles(cmd, client, assetType, assetId) {
|
|
221
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
200
222
|
try {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
let x;
|
|
210
|
-
switch (resp.data.accessLevels.__typename) {
|
|
211
|
-
case "ResourceAccessLevelsResult":
|
|
212
|
-
return (_c = (_b = (_a = resp.data) === null || _a === void 0 ? void 0 : _a.accessLevels) === null || _b === void 0 ? void 0 : _b.accessLevels) === null || _c === void 0 ? void 0 : _c.map((role) => {
|
|
213
|
-
return {
|
|
214
|
-
name: role.accessLevelName,
|
|
215
|
-
value: {
|
|
216
|
-
name: role.accessLevelName,
|
|
217
|
-
id: role.accessLevelRemoteId,
|
|
218
|
-
},
|
|
219
|
-
};
|
|
223
|
+
switch (assetType) {
|
|
224
|
+
case "Resource": {
|
|
225
|
+
const resp = await client.query({
|
|
226
|
+
query: RESOURCE_ROLES_QUERY,
|
|
227
|
+
variables: {
|
|
228
|
+
resourceId: assetId,
|
|
229
|
+
},
|
|
230
|
+
fetchPolicy: "network-only", // to avoid caching
|
|
220
231
|
});
|
|
221
|
-
|
|
222
|
-
x
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
232
|
+
// no fall through doesn't consider process.exit();
|
|
233
|
+
let x;
|
|
234
|
+
switch (resp.data.accessLevels.__typename) {
|
|
235
|
+
case "ResourceAccessLevelsResult":
|
|
236
|
+
return (_c = (_b = (_a = resp.data) === null || _a === void 0 ? void 0 : _a.accessLevels) === null || _b === void 0 ? void 0 : _b.accessLevels) === null || _c === void 0 ? void 0 : _c.map((role) => {
|
|
237
|
+
return {
|
|
238
|
+
message: role.accessLevelName || "",
|
|
239
|
+
value: {
|
|
240
|
+
name: role.accessLevelName || "",
|
|
241
|
+
id: role.accessLevelRemoteId || "",
|
|
242
|
+
},
|
|
243
|
+
};
|
|
244
|
+
});
|
|
245
|
+
case "ResourceNotFoundError":
|
|
246
|
+
x = cmd.error((_e = (_d = resp.data) === null || _d === void 0 ? void 0 : _d.accessLevels) === null || _e === void 0 ? void 0 : _e.message);
|
|
247
|
+
break;
|
|
248
|
+
default:
|
|
249
|
+
cmd.error(resp.error || "Unknown error occurred.");
|
|
250
|
+
}
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
case "Group": {
|
|
254
|
+
const resp = await client.query({
|
|
255
|
+
query: GROUP_ROLES_QUERY,
|
|
256
|
+
variables: {
|
|
257
|
+
groupId: assetId,
|
|
258
|
+
},
|
|
259
|
+
fetchPolicy: "network-only", // to avoid caching
|
|
260
|
+
});
|
|
261
|
+
// no fall through doesn't consider process.exit();
|
|
262
|
+
let x;
|
|
263
|
+
switch (resp.data.groupAccessLevels.__typename) {
|
|
264
|
+
case "GroupAccessLevelsResult":
|
|
265
|
+
return (_h = (_g = (_f = resp.data) === null || _f === void 0 ? void 0 : _f.groupAccessLevels) === null || _g === void 0 ? void 0 : _g.accessLevels) === null || _h === void 0 ? void 0 : _h.map((role) => {
|
|
266
|
+
return {
|
|
267
|
+
message: role.accessLevelName,
|
|
268
|
+
value: {
|
|
269
|
+
name: role.accessLevelName,
|
|
270
|
+
id: role.accessLevelRemoteId,
|
|
271
|
+
},
|
|
272
|
+
};
|
|
273
|
+
});
|
|
274
|
+
default:
|
|
275
|
+
x = cmd.error(resp.error || "Unknown error occurred.");
|
|
276
|
+
}
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
226
279
|
}
|
|
227
280
|
}
|
|
228
281
|
catch (error) {
|
|
@@ -241,16 +294,18 @@ const REQUEST_DEFAULTS_QUERY = (0, graphql_1.graphql)(`
|
|
|
241
294
|
requestedGroups: $requestedGroups,
|
|
242
295
|
}
|
|
243
296
|
) {
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
297
|
+
... on RequestDefaults {
|
|
298
|
+
durationOptions {
|
|
299
|
+
durationInMinutes
|
|
300
|
+
label
|
|
301
|
+
}
|
|
302
|
+
recommendedDurationInMinutes
|
|
303
|
+
defaultDurationInMinutes
|
|
304
|
+
maxDurationInMinutes
|
|
305
|
+
requireSupportTicket
|
|
306
|
+
reasonOptional
|
|
307
|
+
requesterIsAdmin
|
|
247
308
|
}
|
|
248
|
-
recommendedDurationInMinutes
|
|
249
|
-
defaultDurationInMinutes
|
|
250
|
-
maxDurationInMinutes
|
|
251
|
-
requireSupportTicket
|
|
252
|
-
reasonOptional
|
|
253
|
-
requesterIsAdmin
|
|
254
309
|
}
|
|
255
310
|
}`);
|
|
256
311
|
async function queryRequestDefaults(cmd, client, requestedResources, requestedGroups) {
|
|
@@ -271,20 +326,176 @@ async function queryRequestDefaults(cmd, client, requestedResources, requestedGr
|
|
|
271
326
|
}
|
|
272
327
|
}
|
|
273
328
|
}
|
|
329
|
+
const CREATE_REQUEST_MUTATION = (0, graphql_1.graphql)(`
|
|
330
|
+
mutation CreateRequest(
|
|
331
|
+
$requestedResources: [RequestedResourceInput!]!
|
|
332
|
+
$requestedGroups: [RequestedGroupInput!]!
|
|
333
|
+
$reason: String!
|
|
334
|
+
$durationInMinutes: Int
|
|
335
|
+
) {
|
|
336
|
+
createRequest(
|
|
337
|
+
input: {
|
|
338
|
+
requestedResources: $requestedResources
|
|
339
|
+
requestedGroups: $requestedGroups
|
|
340
|
+
reason: $reason
|
|
341
|
+
durationInMinutes: $durationInMinutes
|
|
342
|
+
}
|
|
343
|
+
) {
|
|
344
|
+
... on CreateRequestResult {
|
|
345
|
+
request {
|
|
346
|
+
id
|
|
347
|
+
status
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
... on RequestDurationTooLargeError {
|
|
351
|
+
message
|
|
352
|
+
}
|
|
353
|
+
... on RequestRequiresUserAuthTokenForConnectionError {
|
|
354
|
+
message
|
|
355
|
+
}
|
|
356
|
+
... on NoReviewersSetForOwnerError {
|
|
357
|
+
message
|
|
358
|
+
ownerId
|
|
359
|
+
}
|
|
360
|
+
... on NoReviewersSetForResourceError {
|
|
361
|
+
message
|
|
362
|
+
resourceId
|
|
363
|
+
}
|
|
364
|
+
... on NoReviewersSetForGroupError {
|
|
365
|
+
message
|
|
366
|
+
groupId
|
|
367
|
+
}
|
|
368
|
+
... on NoManagerSetForRequestingUserError {
|
|
369
|
+
message
|
|
370
|
+
}
|
|
371
|
+
... on MfaInvalidError {
|
|
372
|
+
message
|
|
373
|
+
}
|
|
374
|
+
... on BulkRequestTooLargeError {
|
|
375
|
+
message
|
|
376
|
+
}
|
|
377
|
+
... on ItemCannotBeRequestedError {
|
|
378
|
+
message
|
|
379
|
+
}
|
|
380
|
+
... on UserCannotRequestAccessForTargetGroupError {
|
|
381
|
+
message
|
|
382
|
+
groupId
|
|
383
|
+
userId
|
|
384
|
+
}
|
|
385
|
+
... on GroupNestingNotAllowedError {
|
|
386
|
+
message
|
|
387
|
+
fromGroupId
|
|
388
|
+
toGroupId
|
|
389
|
+
}
|
|
390
|
+
... on TargetUserHasNestedAccessError {
|
|
391
|
+
message
|
|
392
|
+
groupIds
|
|
393
|
+
}
|
|
394
|
+
... on RequestReasonMissingError {
|
|
395
|
+
message
|
|
396
|
+
}
|
|
397
|
+
... on RequestFieldValueMissingError {
|
|
398
|
+
message
|
|
399
|
+
fieldName
|
|
400
|
+
}
|
|
401
|
+
... on LinkedGroupNotRequestableError {
|
|
402
|
+
message
|
|
403
|
+
sourceGroupId
|
|
404
|
+
groupBindingId
|
|
405
|
+
}
|
|
406
|
+
... on RequestReasonBelowMinLengthError {
|
|
407
|
+
message
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
`);
|
|
413
|
+
async function createRequest(cmd, client, requestedResources, requestedGroups, reason, durationInMinutes) {
|
|
414
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
|
|
415
|
+
try {
|
|
416
|
+
const resp = await client.mutate({
|
|
417
|
+
mutation: CREATE_REQUEST_MUTATION,
|
|
418
|
+
variables: {
|
|
419
|
+
requestedResources: requestedResources,
|
|
420
|
+
requestedGroups: requestedGroups,
|
|
421
|
+
reason: reason,
|
|
422
|
+
durationInMinutes: durationInMinutes,
|
|
423
|
+
},
|
|
424
|
+
});
|
|
425
|
+
let x;
|
|
426
|
+
switch ((_a = resp.data) === null || _a === void 0 ? void 0 : _a.createRequest.__typename) {
|
|
427
|
+
case "CreateRequestResult":
|
|
428
|
+
return (_b = resp.data) === null || _b === void 0 ? void 0 : _b.createRequest.request;
|
|
429
|
+
case "RequestDurationTooLargeError":
|
|
430
|
+
x = cmd.error((_c = resp.data) === null || _c === void 0 ? void 0 : _c.createRequest.message);
|
|
431
|
+
break;
|
|
432
|
+
case "RequestRequiresUserAuthTokenForConnectionError":
|
|
433
|
+
x = cmd.error((_d = resp.data) === null || _d === void 0 ? void 0 : _d.createRequest.message);
|
|
434
|
+
break;
|
|
435
|
+
case "NoReviewersSetForOwnerError":
|
|
436
|
+
x = cmd.error((_e = resp.data) === null || _e === void 0 ? void 0 : _e.createRequest.message);
|
|
437
|
+
break;
|
|
438
|
+
case "NoReviewersSetForResourceError":
|
|
439
|
+
x = cmd.error((_f = resp.data) === null || _f === void 0 ? void 0 : _f.createRequest.message);
|
|
440
|
+
break;
|
|
441
|
+
case "NoReviewersSetForGroupError":
|
|
442
|
+
x = cmd.error((_g = resp.data) === null || _g === void 0 ? void 0 : _g.createRequest.message);
|
|
443
|
+
break;
|
|
444
|
+
case "NoManagerSetForRequestingUserError":
|
|
445
|
+
x = cmd.error((_h = resp.data) === null || _h === void 0 ? void 0 : _h.createRequest.message);
|
|
446
|
+
break;
|
|
447
|
+
case "MfaInvalidError":
|
|
448
|
+
x = cmd.error((_j = resp.data) === null || _j === void 0 ? void 0 : _j.createRequest.message);
|
|
449
|
+
break;
|
|
450
|
+
case "BulkRequestTooLargeError":
|
|
451
|
+
x = cmd.error((_k = resp.data) === null || _k === void 0 ? void 0 : _k.createRequest.message);
|
|
452
|
+
break;
|
|
453
|
+
case "ItemCannotBeRequestedError":
|
|
454
|
+
x = cmd.error((_l = resp.data) === null || _l === void 0 ? void 0 : _l.createRequest.message);
|
|
455
|
+
break;
|
|
456
|
+
case "UserCannotRequestAccessForTargetGroupError":
|
|
457
|
+
x = cmd.error((_m = resp.data) === null || _m === void 0 ? void 0 : _m.createRequest.message);
|
|
458
|
+
break;
|
|
459
|
+
case "GroupNestingNotAllowedError":
|
|
460
|
+
x = cmd.error((_o = resp.data) === null || _o === void 0 ? void 0 : _o.createRequest.message);
|
|
461
|
+
break;
|
|
462
|
+
case "TargetUserHasNestedAccessError":
|
|
463
|
+
x = cmd.error((_p = resp.data) === null || _p === void 0 ? void 0 : _p.createRequest.message);
|
|
464
|
+
break;
|
|
465
|
+
case "RequestReasonMissingError":
|
|
466
|
+
x = cmd.error((_q = resp.data) === null || _q === void 0 ? void 0 : _q.createRequest.message);
|
|
467
|
+
break;
|
|
468
|
+
case "RequestFieldValueMissingError":
|
|
469
|
+
x = cmd.error((_r = resp.data) === null || _r === void 0 ? void 0 : _r.createRequest.message);
|
|
470
|
+
break;
|
|
471
|
+
case "LinkedGroupNotRequestableError":
|
|
472
|
+
x = cmd.error((_s = resp.data) === null || _s === void 0 ? void 0 : _s.createRequest.message);
|
|
473
|
+
break;
|
|
474
|
+
case "RequestReasonBelowMinLengthError":
|
|
475
|
+
x = cmd.error((_t = resp.data) === null || _t === void 0 ? void 0 : _t.createRequest.message);
|
|
476
|
+
break;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
catch (error) {
|
|
480
|
+
if (error instanceof Error || typeof error === "string") {
|
|
481
|
+
cmd.error(error);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
274
485
|
// Helper functions
|
|
275
486
|
async function selectRequestableItems(cmd, client, requestMap) {
|
|
276
|
-
const
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
pageSize: 15,
|
|
487
|
+
const initialChoices = (await queryRequestableApps(cmd, client, "")) || [];
|
|
488
|
+
const appPrompt = new AutoComplete({
|
|
489
|
+
name: "App",
|
|
490
|
+
message: "Select an app:",
|
|
491
|
+
limit: 15,
|
|
492
|
+
choices: initialChoices,
|
|
493
|
+
async suggest(input) {
|
|
494
|
+
const filteredChoices = await queryRequestableApps(cmd, client, input || "");
|
|
495
|
+
return filteredChoices || initialChoices;
|
|
286
496
|
},
|
|
287
|
-
|
|
497
|
+
});
|
|
498
|
+
const App = await appPrompt.run();
|
|
288
499
|
// Set the app in the requestMap and call choose assets step
|
|
289
500
|
if (!(App.id in requestMap)) {
|
|
290
501
|
requestMap[App.id] = {
|
|
@@ -295,13 +506,16 @@ async function selectRequestableItems(cmd, client, requestMap) {
|
|
|
295
506
|
await chooseAssets(cmd, client, App.id, requestMap);
|
|
296
507
|
}
|
|
297
508
|
async function chooseAssets(cmd, client, appId, requestMap) {
|
|
298
|
-
|
|
299
|
-
const
|
|
509
|
+
const initialChoices = (await queryRequestableAssets(cmd, client, appId, "")) || [];
|
|
510
|
+
const assetPrompt = new AutoComplete({
|
|
300
511
|
name: "Assets",
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
choices
|
|
512
|
+
message: "Select one or more assets:",
|
|
513
|
+
limit: 15,
|
|
514
|
+
multiple: true,
|
|
515
|
+
async choices(input) {
|
|
516
|
+
const filteredChoices = await queryRequestableAssets(cmd, client, appId, input);
|
|
517
|
+
return filteredChoices || initialChoices;
|
|
518
|
+
},
|
|
305
519
|
validate: (answer) => {
|
|
306
520
|
if (answer.length < 1) {
|
|
307
521
|
return "You must select at least one item.";
|
|
@@ -309,14 +523,16 @@ async function chooseAssets(cmd, client, appId, requestMap) {
|
|
|
309
523
|
return true;
|
|
310
524
|
},
|
|
311
525
|
});
|
|
526
|
+
const Assets = await assetPrompt.run();
|
|
312
527
|
const entry = requestMap[appId];
|
|
313
528
|
for (const asset of Assets) {
|
|
314
529
|
if (entry === undefined) {
|
|
315
|
-
throw new Error(`
|
|
530
|
+
throw new Error(`Error formatting app ${appId} in request`);
|
|
316
531
|
}
|
|
317
532
|
if (!(asset.id in entry.assets)) {
|
|
318
533
|
entry.assets[asset.id] = {
|
|
319
534
|
assetName: asset.name,
|
|
535
|
+
type: asset.type,
|
|
320
536
|
roles: {},
|
|
321
537
|
};
|
|
322
538
|
}
|
|
@@ -325,29 +541,31 @@ async function chooseAssets(cmd, client, appId, requestMap) {
|
|
|
325
541
|
}
|
|
326
542
|
async function chooseRoles(cmd, client, appId, assetId, requestMap) {
|
|
327
543
|
var _a;
|
|
328
|
-
const
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
544
|
+
const entry = requestMap[appId];
|
|
545
|
+
const assetEntry = entry === null || entry === void 0 ? void 0 : entry.assets[assetId];
|
|
546
|
+
if (entry === undefined || assetEntry === undefined) {
|
|
547
|
+
throw new Error(`App ${appId} or Asset ${assetId} not found in requestMap`);
|
|
548
|
+
}
|
|
549
|
+
const assetRoles = (_a = (await queryAssetRoles(cmd, client, assetEntry.type, assetId))) !== null && _a !== void 0 ? _a : [];
|
|
550
|
+
if (assetRoles !== undefined &&
|
|
551
|
+
(assetRoles.length === 0 ||
|
|
552
|
+
(assetRoles.length === 1 && assetRoles[0].value.name === ""))) {
|
|
332
553
|
return;
|
|
333
554
|
}
|
|
334
|
-
const
|
|
335
|
-
name: "
|
|
336
|
-
type: "checkbox",
|
|
555
|
+
const rolePrompt = new AutoComplete({
|
|
556
|
+
name: "Roles",
|
|
337
557
|
message: `Select one or more roles for ${assetId}:`,
|
|
338
|
-
|
|
558
|
+
limit: 15,
|
|
559
|
+
multiple: true,
|
|
560
|
+
choices: assetRoles,
|
|
339
561
|
validate: (answer) => {
|
|
340
|
-
if (
|
|
341
|
-
return "You must select at least one
|
|
562
|
+
if (answer.length < 1) {
|
|
563
|
+
return "You must select at least one item.";
|
|
342
564
|
}
|
|
343
565
|
return true;
|
|
344
566
|
},
|
|
345
567
|
});
|
|
346
|
-
const
|
|
347
|
-
const assetEntry = entry === null || entry === void 0 ? void 0 : entry.assets[assetId];
|
|
348
|
-
if (entry === undefined || assetEntry === undefined) {
|
|
349
|
-
throw new Error(`App ${appId} or Asset ${assetId} not found in requestMap`);
|
|
350
|
-
}
|
|
568
|
+
const roles = await rolePrompt.run();
|
|
351
569
|
if (!assetEntry.roles) {
|
|
352
570
|
assetEntry.roles = {};
|
|
353
571
|
}
|
|
@@ -360,14 +578,12 @@ async function chooseRoles(cmd, client, appId, assetId, requestMap) {
|
|
|
360
578
|
async function doneSelectingAssets() {
|
|
361
579
|
const submitMessage = "✅ Yes, proceed with request";
|
|
362
580
|
const addMoreMessage = "❌ No, add more items";
|
|
363
|
-
const
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
},
|
|
370
|
-
]);
|
|
581
|
+
const prompt = new Select({
|
|
582
|
+
name: "submitOrAdd",
|
|
583
|
+
message: "Is this all you want to request?",
|
|
584
|
+
choices: [submitMessage, addMoreMessage],
|
|
585
|
+
});
|
|
586
|
+
const submitOrAdd = await prompt.run();
|
|
371
587
|
return submitOrAdd === submitMessage;
|
|
372
588
|
}
|
|
373
589
|
async function setRequestDefaults(cmd, client, metadata) {
|
|
@@ -388,7 +604,7 @@ async function setRequestDefaults(cmd, client, metadata) {
|
|
|
388
604
|
}
|
|
389
605
|
try {
|
|
390
606
|
const requestDefaults = await queryRequestDefaults(cmd, client, requestedResources, requestedGroups);
|
|
391
|
-
if (
|
|
607
|
+
if (requestDefaults !== undefined) {
|
|
392
608
|
metadata.requestDefaults.durationOptions =
|
|
393
609
|
requestDefaults.durationOptions;
|
|
394
610
|
metadata.requestDefaults.recommendedDurationInMinutes =
|
|
@@ -409,47 +625,91 @@ async function setRequestDefaults(cmd, client, metadata) {
|
|
|
409
625
|
}
|
|
410
626
|
}
|
|
411
627
|
async function promptForReason(metadata) {
|
|
412
|
-
|
|
628
|
+
const { reason } = await prompt([
|
|
413
629
|
{
|
|
414
630
|
name: "reason",
|
|
415
631
|
message: "I need access to this because...",
|
|
416
632
|
type: "input",
|
|
417
633
|
validate: (answer) => {
|
|
418
|
-
if (metadata.requestDefaults.reasonOptional && answer.length < 1) {
|
|
634
|
+
if (!metadata.requestDefaults.reasonOptional && answer.length < 1) {
|
|
419
635
|
return "A reason for requesting these assets is required.";
|
|
420
636
|
}
|
|
421
637
|
return true;
|
|
422
638
|
},
|
|
423
639
|
},
|
|
424
640
|
]);
|
|
641
|
+
return reason;
|
|
425
642
|
}
|
|
426
643
|
async function promptForExpiration(metadata) {
|
|
427
644
|
var _a, _b;
|
|
428
645
|
const durations = ((_b = (_a = metadata.requestDefaults) === null || _a === void 0 ? void 0 : _a.durationOptions) === null || _b === void 0 ? void 0 : _b.map((option) => {
|
|
646
|
+
const label = option.durationInMinutes ===
|
|
647
|
+
metadata.requestDefaults.recommendedDurationInMinutes
|
|
648
|
+
? `${option.label} (Recommended)`
|
|
649
|
+
: option.label;
|
|
429
650
|
return {
|
|
430
|
-
|
|
431
|
-
metadata.requestDefaults.recommendedDurationInMinutes
|
|
432
|
-
? `${option.label} (Recommended)`
|
|
433
|
-
: option.label,
|
|
651
|
+
message: label,
|
|
434
652
|
value: {
|
|
435
|
-
label:
|
|
653
|
+
label: label,
|
|
436
654
|
durationInMinutes: option.durationInMinutes,
|
|
655
|
+
toString: () => label,
|
|
437
656
|
},
|
|
438
657
|
};
|
|
439
658
|
})) || [];
|
|
440
|
-
//
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
659
|
+
// Sort durations by minutes
|
|
660
|
+
durations.sort((a, b) => a.value.durationInMinutes - b.value.durationInMinutes);
|
|
661
|
+
const expirationSelect = new AutoComplete({
|
|
662
|
+
name: "expiration",
|
|
663
|
+
message: "When should access expire?",
|
|
664
|
+
type: "list",
|
|
665
|
+
choices: durations,
|
|
666
|
+
pageSize: 15,
|
|
667
|
+
});
|
|
668
|
+
let selected = await expirationSelect.run();
|
|
669
|
+
if (selected.label === "Custom") {
|
|
670
|
+
selected = await setCustomDuration();
|
|
671
|
+
}
|
|
672
|
+
return selected;
|
|
673
|
+
}
|
|
674
|
+
async function setCustomDuration() {
|
|
675
|
+
const durationForm = new Form({
|
|
676
|
+
name: "user",
|
|
677
|
+
message: "Please set a custom access duration:",
|
|
678
|
+
choices: [
|
|
679
|
+
{ name: "days", message: "Days", initial: "0" },
|
|
680
|
+
{ name: "hours", message: "Hours", initial: "0" },
|
|
681
|
+
{ name: "minutes", message: "Minutes", initial: "0" },
|
|
682
|
+
],
|
|
683
|
+
validate: (answer) => {
|
|
684
|
+
const days = Number.parseInt(answer.days);
|
|
685
|
+
const hours = Number.parseInt(answer.hours);
|
|
686
|
+
const minutes = Number.parseInt(answer.minutes);
|
|
687
|
+
if (days < 0 ||
|
|
688
|
+
hours < 0 ||
|
|
689
|
+
minutes < 0 ||
|
|
690
|
+
(days === 0 && hours === 0 && minutes === 0)) {
|
|
691
|
+
return "Please enter a valid duration.";
|
|
692
|
+
}
|
|
693
|
+
return true;
|
|
451
694
|
},
|
|
452
|
-
|
|
695
|
+
});
|
|
696
|
+
const duration = await durationForm.run();
|
|
697
|
+
// Convert to minutes, define the new custom label
|
|
698
|
+
const durationInMinutes = duration.days * 1440 + duration.hours * 60 + duration.minutes;
|
|
699
|
+
let durationLabel = "";
|
|
700
|
+
if (duration.days > 0) {
|
|
701
|
+
durationLabel += `${duration.days}d `;
|
|
702
|
+
}
|
|
703
|
+
if (duration.hours > 0) {
|
|
704
|
+
durationLabel += `${duration.hours}h `;
|
|
705
|
+
}
|
|
706
|
+
if (duration.minutes > 0) {
|
|
707
|
+
durationLabel += `${duration.minutes}m`;
|
|
708
|
+
}
|
|
709
|
+
return {
|
|
710
|
+
durationInMinutes: durationInMinutes,
|
|
711
|
+
label: durationLabel,
|
|
712
|
+
};
|
|
453
713
|
}
|
|
454
714
|
async function submitFinalRequest(cmd) {
|
|
455
715
|
const submitMessage = "✅ Yes, submit request";
|
package/lib/utils/displays.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
import type { ApolloQueryResult } from "@apollo/client";
|
|
1
2
|
import type { Command } from "@oclif/core/lib/command";
|
|
3
|
+
import type { GetRequestQuery, GetRequestsQuery } from "../graphql/graphql";
|
|
2
4
|
import type { RequestMap } from "../lib/requests";
|
|
3
5
|
export declare function headerMessage(cmd: Command): void;
|
|
4
6
|
export declare function treeifyRequestMap(requestMap: RequestMap): string;
|
|
5
7
|
export declare function displayFinalRequestSummary(cmd: Command, requestMap: RequestMap, reason: string, expiration: string): void;
|
|
8
|
+
export declare function displayRequestDetails(cmd: Command, requestResp: ApolloQueryResult<GetRequestQuery>): void;
|
|
9
|
+
export declare function displayRequestList(cmd: Command, requestResp: ApolloQueryResult<GetRequestsQuery>): void;
|