@uipath/audit-commands 1.204.0-preview.255 → 1.205.0-preview.256

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.
Files changed (2) hide show
  1. package/dist/index.js +141 -29
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -2186,7 +2186,9 @@ var ErrorDimensions = {
2186
2186
  Result: "Result",
2187
2187
  ErrorCode: "ErrorCode",
2188
2188
  Retry: "Retry",
2189
- ErrorMessage: "ErrorMessage"
2189
+ ErrorMessage: "ErrorMessage",
2190
+ HttpStatus: "HttpStatus",
2191
+ UpstreamErrorCode: "UpstreamErrorCode"
2190
2192
  };
2191
2193
  var AuthDimensions = {
2192
2194
  AuthenticationMethod: "AuthenticationMethod",
@@ -2622,7 +2624,7 @@ var package_default = {
2622
2624
  name: "@uipath/audit-sdk",
2623
2625
  author: "UiPath",
2624
2626
  license: "SEE LICENSE IN LICENSE.txt",
2625
- version: "1.204.0",
2627
+ version: "1.205.0",
2626
2628
  description: "SDK for the UiPath Audit Service — query audit event sources, list events, download long-term-store exports, and manage audit exclusion rules.",
2627
2629
  repository: {
2628
2630
  type: "git",
@@ -3214,22 +3216,12 @@ var resolveConfigAsync = async ({
3214
3216
  baseUrl = DEFAULT_BASE_URL;
3215
3217
  }
3216
3218
  baseUrl = normalizeAndValidateBaseUrl(baseUrl);
3217
- let clientId = customClientId;
3218
- if (!clientId && fileAuth.clientId) {
3219
- clientId = fileAuth.clientId;
3220
- }
3221
- if (!clientId) {
3222
- clientId = DEFAULT_CLIENT_ID;
3223
- }
3224
- let clientSecret = customClientSecret;
3225
- if (!clientSecret && fileAuth.clientSecret) {
3226
- clientSecret = fileAuth.clientSecret;
3227
- }
3228
- const isExternalAppAuth = clientId !== DEFAULT_CLIENT_ID && (Boolean(clientSecret) || Boolean(customClientAssertion));
3219
+ const clientId = customClientId || DEFAULT_CLIENT_ID;
3220
+ const isExternalAppAuth = clientId !== DEFAULT_CLIENT_ID && (Boolean(customClientSecret) || Boolean(customClientAssertion));
3229
3221
  const scopes = resolveScopes(isExternalAppAuth, customScopes, fileAuth.scopes);
3230
3222
  return {
3231
3223
  clientId,
3232
- clientSecret,
3224
+ clientSecret: customClientSecret,
3233
3225
  scopes,
3234
3226
  baseUrl,
3235
3227
  authorizationEndpoint: `${baseUrl}/identity_/connect/authorize`,
@@ -3422,6 +3414,16 @@ class NodeFileSystem {
3422
3414
  async rename(oldPath, newPath) {
3423
3415
  await fs.rename(oldPath, newPath);
3424
3416
  }
3417
+ async isSymbolicLink(filePath) {
3418
+ try {
3419
+ return (await fs.lstat(filePath)).isSymbolicLink();
3420
+ } catch (error) {
3421
+ if (this.isEnoent(error) || this.hasErrnoCode(error, "ENOTDIR")) {
3422
+ return false;
3423
+ }
3424
+ throw error;
3425
+ }
3426
+ }
3425
3427
  async realpath(filePath) {
3426
3428
  try {
3427
3429
  return await fs.realpath(filePath);
@@ -3633,6 +3635,16 @@ var resolveIdentityType = (claims, authFlow, email) => {
3633
3635
  }
3634
3636
  return;
3635
3637
  };
3638
+ var resolveApplicationSubtype = (claims, authFlow) => {
3639
+ switch (asString(claims?.sub_type)) {
3640
+ case "service.external":
3641
+ return "External";
3642
+ case "service.internal":
3643
+ return "Internal";
3644
+ default:
3645
+ return authFlow === "client_credentials" || authFlow === "federated_credentials" ? "External" : undefined;
3646
+ }
3647
+ };
3636
3648
  var looksLikeEmail = (value) => value?.includes("@") ?? false;
3637
3649
  var pickEmail = (claims) => {
3638
3650
  for (const candidate of [claims?.email, claims?.preferred_username]) {
@@ -3674,6 +3686,12 @@ var resolveSessionIdentity = (accessToken, authFlow) => {
3674
3686
  const clientId = asString(claims?.client_id);
3675
3687
  if (clientId)
3676
3688
  identity.clientId = clientId;
3689
+ const subType = asString(claims?.sub_type);
3690
+ if (subType)
3691
+ identity.subType = subType;
3692
+ const applicationSubtype = resolveApplicationSubtype(claims, authFlow);
3693
+ if (applicationSubtype)
3694
+ identity.applicationSubtype = applicationSubtype;
3677
3695
  return identity;
3678
3696
  };
3679
3697
  var readTokenScopes = (accessToken) => accessToken ? pickScopes(decodeClaims(accessToken)) : undefined;
@@ -3966,6 +3984,40 @@ var tryRobotClientFallback = async (options = {}) => {
3966
3984
  }
3967
3985
  };
3968
3986
 
3987
+ // ../../auth/src/tenantSelection.ts
3988
+ var LOGIN_STATUS_HINT = "Run 'uip login status' to see the organization the CLI is signed in to.";
3989
+ var organizationHint = (organizationId) => `The request used '${organizationId}' as the organization. ${LOGIN_STATUS_HINT}`;
3990
+ var IDENTIFIER_STATUSES = new Set([400, 403, 404]);
3991
+ var describeNonJsonResponse = (organizationId, response, parseError) => {
3992
+ if (response.redirected) {
3993
+ return `Could not find organization '${organizationId}': the request was ` + `redirected to a sign-in page instead of the organization's tenant ` + `list. ${LOGIN_STATUS_HINT}`;
3994
+ }
3995
+ const contentType = response.headers.get("content-type") ?? "unknown";
3996
+ return `The organization service returned a '${contentType}' response instead ` + `of JSON: ${parseError.message}. ${organizationHint(organizationId)}`;
3997
+ };
3998
+ var fetchTenantsAndOrganizations = async (baseUrl, accessToken, organizationId, signal) => {
3999
+ const url = `${baseUrl}/${organizationId}/portal_/api/filtering/leftnav/tenantsAndOrganizationInfo`;
4000
+ const response = await fetch(url, {
4001
+ headers: {
4002
+ Authorization: `Bearer ${accessToken}`
4003
+ },
4004
+ ...signal ? { signal } : {}
4005
+ });
4006
+ if (!response.ok) {
4007
+ if (response.status === 401) {
4008
+ throw new Error(`Unauthorized: the access token was rejected, it was not ` + `issued for organization '${organizationId}', or ` + `'${organizationId}' was not accepted as an organization ` + `URL segment in this environment. ` + LOGIN_STATUS_HINT);
4009
+ }
4010
+ const errorText = await response.text();
4011
+ const message = `Failed to get tenants and organizations: ${response.status} ${errorText}`;
4012
+ throw new Error(IDENTIFIER_STATUSES.has(response.status) ? `${message}. ${organizationHint(organizationId)}` : message);
4013
+ }
4014
+ const [parseError, data] = await catchError(response.json());
4015
+ if (parseError) {
4016
+ throw new Error(describeNonJsonResponse(organizationId, response, parseError));
4017
+ }
4018
+ return data;
4019
+ };
4020
+
3969
4021
  // ../../auth/src/tokenRefresh.ts
3970
4022
  var TOKEN_REFRESH_REAUTHENTICATE_MESSAGE = "Token refresh failed. Run 'uip login' to re-authenticate.";
3971
4023
 
@@ -4178,6 +4230,8 @@ var saveEnvFileAsync = async ({
4178
4230
  };
4179
4231
 
4180
4232
  // ../../auth/src/loginStatus.ts
4233
+ var defaultRobotTenantIdCache = new Map;
4234
+ var ROBOT_TENANT_LOOKUP_TIMEOUT_MS = 5000;
4181
4235
  var getLoginStatusAsync = async (options = {}) => {
4182
4236
  return getLoginStatusWithDeps(options);
4183
4237
  };
@@ -4190,12 +4244,20 @@ var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
4190
4244
  refreshToken: refreshTokenFn = refreshAccessToken,
4191
4245
  resolveConfig = resolveConfigAsync,
4192
4246
  robotFallback = tryRobotClientFallback,
4247
+ fetchTenantsAndOrgs = fetchTenantsAndOrganizations,
4248
+ robotTenantIdCache = defaultRobotTenantIdCache,
4249
+ robotTenantLookupTimeoutMs = ROBOT_TENANT_LOOKUP_TIMEOUT_MS,
4193
4250
  loadBreaker = loadRefreshBreaker,
4194
4251
  saveBreaker = saveRefreshBreaker,
4195
4252
  clearBreaker = clearRefreshBreaker
4196
4253
  } = deps;
4254
+ const robotDeps = {
4255
+ fetchTenantsAndOrgs,
4256
+ cache: robotTenantIdCache,
4257
+ lookupTimeoutMs: robotTenantLookupTimeoutMs
4258
+ };
4197
4259
  if (isRobotAuthEnforced()) {
4198
- return resolveRobotEnforcedStatus(robotFallback);
4260
+ return resolveRobotEnforcedStatus(robotFallback, robotDeps);
4199
4261
  }
4200
4262
  if (isEnvAuthEnabled()) {
4201
4263
  return readAuthFromEnv();
@@ -4213,7 +4275,7 @@ var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
4213
4275
  hint: `No credentials found for profile "${activeProfile}". Run 'uip login --profile ${activeProfile}' to authenticate this profile.`
4214
4276
  };
4215
4277
  }
4216
- return resolveBorrowedRobotStatus(robotFallback);
4278
+ return resolveBorrowedRobotStatus(robotFallback, robotDeps);
4217
4279
  }
4218
4280
  const loaded = await loadFileCredentials(loadEnvFile, absolutePath);
4219
4281
  if ("status" in loaded) {
@@ -4255,7 +4317,7 @@ var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
4255
4317
  }
4256
4318
  return buildFileStatus(tokens, credentials, globalHint);
4257
4319
  };
4258
- async function resolveRobotEnforcedStatus(robotFallback) {
4320
+ async function resolveRobotEnforcedStatus(robotFallback, deps) {
4259
4321
  if (isEnvAuthEnabled()) {
4260
4322
  throw new EnvAuthConfigError(`${ENV_AUTH_ENABLE_VAR}=true and ${ENFORCE_ROBOT_AUTH_VAR}=true ` + `are mutually exclusive. Unset one of them and re-run.`);
4261
4323
  }
@@ -4266,11 +4328,11 @@ async function resolveRobotEnforcedStatus(robotFallback) {
4266
4328
  hint: `${ENFORCE_ROBOT_AUTH_VAR}=true but the UiPath Robot ` + `session is unavailable. Start and sign in to the Assistant, ` + `or unset ${ENFORCE_ROBOT_AUTH_VAR} to fall back to file or ` + `env-var authentication.`
4267
4329
  };
4268
4330
  }
4269
- return buildRobotStatus(robotCreds);
4331
+ return buildRobotStatus(robotCreds, deps);
4270
4332
  }
4271
- async function resolveBorrowedRobotStatus(robotFallback) {
4333
+ async function resolveBorrowedRobotStatus(robotFallback, deps) {
4272
4334
  const robotCreds = await robotFallback();
4273
- return robotCreds ? buildRobotStatus(robotCreds) : { loginStatus: "Not logged in" };
4335
+ return robotCreds ? buildRobotStatus(robotCreds, deps) : { loginStatus: "Not logged in" };
4274
4336
  }
4275
4337
  async function loadFileCredentials(loadEnvFile, absolutePath) {
4276
4338
  let credentials;
@@ -4405,9 +4467,10 @@ function identityFields(accessToken, credentials) {
4405
4467
  ...scopes ? { scopes } : {}
4406
4468
  };
4407
4469
  }
4408
- function buildRobotStatus(robotCreds) {
4470
+ async function buildRobotStatus(robotCreds, deps) {
4409
4471
  const identity = resolveSessionIdentity(robotCreds.accessToken);
4410
4472
  const scopes = readTokenScopes(robotCreds.accessToken);
4473
+ const tenant = robotCreds.tenantId ? { tenantId: robotCreds.tenantId } : await resolveRobotTenantId(robotCreds, deps);
4411
4474
  return {
4412
4475
  loginStatus: "Logged in",
4413
4476
  accessToken: robotCreds.accessToken,
@@ -4415,14 +4478,62 @@ function buildRobotStatus(robotCreds) {
4415
4478
  organizationName: robotCreds.organizationName,
4416
4479
  organizationId: robotCreds.organizationId,
4417
4480
  tenantName: robotCreds.tenantName,
4418
- tenantId: robotCreds.tenantId,
4481
+ tenantId: tenant.tenantId,
4419
4482
  issuer: robotCreds.issuer,
4420
4483
  expiration: getTokenExpiration(robotCreds.accessToken),
4421
4484
  source: "robot" /* Robot */,
4485
+ ...tenant.hint ? { hint: tenant.hint } : {},
4422
4486
  ...identity ? { identity } : {},
4423
4487
  ...scopes ? { scopes } : {}
4424
4488
  };
4425
4489
  }
4490
+ async function resolveRobotTenantId(robotCreds, deps) {
4491
+ const { baseUrl, accessToken, tenantName } = robotCreds;
4492
+ const organization = robotCreds.organizationName ?? robotCreds.organizationId;
4493
+ if (!tenantName || !organization) {
4494
+ return {};
4495
+ }
4496
+ const key = `${baseUrl}|${organization}|${tenantName}|${accessToken}`;
4497
+ let pending = deps.cache.get(key);
4498
+ if (!pending) {
4499
+ pending = catchError(lookupRobotTenantId({ baseUrl, accessToken, organization, tenantName }, deps)).then(([error, resolution]) => {
4500
+ const settled = error ? { hint: tenantLookupFailureHint(tenantName, error.message) } : resolution;
4501
+ if (!settled.tenantId) {
4502
+ deps.cache.delete(key);
4503
+ }
4504
+ return settled;
4505
+ });
4506
+ deps.cache.set(key, pending);
4507
+ }
4508
+ return pending;
4509
+ }
4510
+ async function lookupRobotTenantId(target, deps) {
4511
+ const { baseUrl, accessToken, organization, tenantName } = target;
4512
+ const [error, data] = await catchError(deps.fetchTenantsAndOrgs(baseUrl, accessToken, organization, AbortSignal.timeout(deps.lookupTimeoutMs)));
4513
+ if (error) {
4514
+ const reason = error.name === "TimeoutError" ? `the tenant list did not answer within ${deps.lookupTimeoutMs} ms.` : error.message;
4515
+ return { hint: tenantLookupFailureHint(tenantName, reason) };
4516
+ }
4517
+ const rows = data?.tenants;
4518
+ const tenants = Array.isArray(rows) ? rows.filter((tenant) => typeof tenant?.id === "string" && typeof tenant?.name === "string") : [];
4519
+ const wantedName = decodePathSegment(tenantName);
4520
+ const wanted = wantedName.toLowerCase();
4521
+ const match = tenants.find((tenant) => tenant.name === wantedName) ?? tenants.find((tenant) => tenant.name.toLowerCase() === wanted);
4522
+ if (!match) {
4523
+ const names = tenants.map((tenant) => tenant.name).join(", ");
4524
+ return {
4525
+ hint: `The Robot session targets tenant '${tenantName}', but ` + `organization '${organization}' lists no tenant of that name` + `${names ? ` (available: ${names})` : ""}. Commands that need ` + `the tenant id will fail until it can be resolved.`
4526
+ };
4527
+ }
4528
+ return { tenantId: match.id };
4529
+ }
4530
+ function tenantLookupFailureHint(tenantName, reason) {
4531
+ return `Could not resolve the id of tenant '${tenantName}' from the ` + `Robot session: ${reason} Commands that need the tenant id will ` + `fail until it can be resolved.`;
4532
+ }
4533
+ function decodePathSegment(segment) {
4534
+ const [error, decoded] = catchError(() => decodeURIComponent(segment));
4535
+ return error ? segment : decoded;
4536
+ }
4426
4537
  var isFileNotFoundError = (error) => {
4427
4538
  if (!(error instanceof Object))
4428
4539
  return false;
@@ -4658,9 +4769,6 @@ function normalizeTokenRefreshUnavailableFailure() {
4658
4769
  function errorMessage(error) {
4659
4770
  return error instanceof Error ? error.message : String(error);
4660
4771
  }
4661
- // ../../auth/src/tenantSelection.ts
4662
- var IDENTIFIER_STATUSES = new Set([400, 403, 404]);
4663
-
4664
4772
  // ../../auth/src/selectTenant.ts
4665
4773
  var TENANT_SELECTION_REQUIRED_CODE = "TENANT_SELECTION_REQUIRED";
4666
4774
  var INVALID_TENANT_CODE = "INVALID_TENANT";
@@ -5698,7 +5806,7 @@ function setGlobalLogFilePath(path2) {
5698
5806
  function getGlobalLogFilePath() {
5699
5807
  return logFilePathSlot.get("");
5700
5808
  }
5701
- var DEFAULT_LOG_LEVEL = 3 /* ERROR */;
5809
+ var DEFAULT_LOG_LEVEL = 2 /* WARN */;
5702
5810
 
5703
5811
  class SimpleLogger {
5704
5812
  __brand = "SimpleLogger";
@@ -6800,7 +6908,9 @@ var CLI_ERROR_CODES = [
6800
6908
  "timeout",
6801
6909
  "server_error",
6802
6910
  "method_not_allowed",
6911
+ "not_supported",
6803
6912
  "configuration_error",
6913
+ "execution_failed",
6804
6914
  "unknown_error"
6805
6915
  ];
6806
6916
  var RETRY_HINTS = [
@@ -7757,7 +7867,9 @@ var OutputFormatter;
7757
7867
  [ErrorDimensions.Result]: data.Result,
7758
7868
  [ErrorDimensions.ErrorCode]: data.ErrorCode,
7759
7869
  [ErrorDimensions.Retry]: data.Retry,
7760
- [ErrorDimensions.ErrorMessage]: data.Message
7870
+ [ErrorDimensions.ErrorMessage]: data.Message,
7871
+ [ErrorDimensions.HttpStatus]: data.Context?.httpStatus?.toString(),
7872
+ [ErrorDimensions.UpstreamErrorCode]: data.Context?.errorCode
7761
7873
  });
7762
7874
  }
7763
7875
  logOutput(normalizeOutputKeys(envelope), getOutputFormat());
@@ -10187,4 +10299,4 @@ export {
10187
10299
  registerCommands
10188
10300
  };
10189
10301
 
10190
- //# debugId=FEE007CE1BA928C664756E2164756E21
10302
+ //# debugId=64318D2053D53E7864756E2164756E21
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@uipath/audit-commands",
3
3
  "author": "UiPath",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
- "version": "1.204.0-preview.255",
5
+ "version": "1.205.0-preview.256",
6
6
  "description": "Admin CLI commands for the UiPath Audit Service — query event sources, paginate events, export ZIPs from the long-term store, and configure the exclusion rules that stop events being recorded. Library composed by admin-tool, not a standalone CLI tool.",
7
7
  "private": false,
8
8
  "repository": {
@@ -26,5 +26,5 @@
26
26
  "files": [
27
27
  "dist"
28
28
  ],
29
- "gitHead": "699c58dabb59414557755a8933bcbe40aa420df3"
29
+ "gitHead": "63740c6cbb7ff282fa9118cc16a148eb030b245f"
30
30
  }