securewithtrace 0.14.1 → 0.16.0
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 +9 -4
- package/dist/index.js +60 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -66,12 +66,17 @@ tracecli vulnerabilities list --severity HIGH
|
|
|
66
66
|
tracecli auth login
|
|
67
67
|
tracecli auth status
|
|
68
68
|
tracecli auth logout
|
|
69
|
-
tracecli auth org list
|
|
70
|
-
tracecli auth org current
|
|
71
|
-
tracecli auth org switch <organization-id-or-slug>
|
|
72
69
|
```
|
|
73
70
|
|
|
74
|
-
|
|
71
|
+
### Organization context
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
tracecli org list
|
|
75
|
+
tracecli org current
|
|
76
|
+
tracecli org switch <organization-id-or-slug>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
When your account belongs to multiple organizations, use `tracecli org switch` to set the active organization context used by repository, vulnerability, and pentest commands.
|
|
75
80
|
|
|
76
81
|
### Repositories
|
|
77
82
|
|
package/dist/index.js
CHANGED
|
@@ -22645,6 +22645,7 @@ var PatchCapabilitiesResponseSchema = external_exports.object({
|
|
|
22645
22645
|
});
|
|
22646
22646
|
var OrganizationResponseSchema = external_exports.object({
|
|
22647
22647
|
organizationId: external_exports.uuid(),
|
|
22648
|
+
workosOrganizationId: external_exports.string().optional(),
|
|
22648
22649
|
name: external_exports.string(),
|
|
22649
22650
|
slug: external_exports.string(),
|
|
22650
22651
|
logoUrl: external_exports.string().nullable(),
|
|
@@ -22671,6 +22672,15 @@ var organizationContract = c9.router({
|
|
|
22671
22672
|
500: ErrorResponseSchema
|
|
22672
22673
|
}
|
|
22673
22674
|
},
|
|
22675
|
+
listMyOrganizations: {
|
|
22676
|
+
method: "GET",
|
|
22677
|
+
path: "/users/me/organizations",
|
|
22678
|
+
responses: {
|
|
22679
|
+
200: ListOrganizationsResponseSchema,
|
|
22680
|
+
401: ErrorResponseSchema,
|
|
22681
|
+
500: ErrorResponseSchema
|
|
22682
|
+
}
|
|
22683
|
+
},
|
|
22674
22684
|
getOrganization: {
|
|
22675
22685
|
method: "GET",
|
|
22676
22686
|
path: "/organizations/:organizationId",
|
|
@@ -24692,17 +24702,21 @@ async function pollForToken(clientId, deviceCode, options = {}) {
|
|
|
24692
24702
|
}
|
|
24693
24703
|
throw new Error("Authorization timed out. Please try again.");
|
|
24694
24704
|
}
|
|
24695
|
-
async function refreshAccessToken(clientId, refreshToken) {
|
|
24705
|
+
async function refreshAccessToken(clientId, refreshToken, organizationId) {
|
|
24706
|
+
const body = new URLSearchParams({
|
|
24707
|
+
grant_type: "refresh_token",
|
|
24708
|
+
client_id: clientId,
|
|
24709
|
+
refresh_token: refreshToken
|
|
24710
|
+
});
|
|
24711
|
+
if (organizationId && organizationId.trim().length > 0) {
|
|
24712
|
+
body.set("organization_id", organizationId);
|
|
24713
|
+
}
|
|
24696
24714
|
const response = await fetch(WORKOS_TOKEN_URL, {
|
|
24697
24715
|
method: "POST",
|
|
24698
24716
|
headers: {
|
|
24699
24717
|
"Content-Type": "application/x-www-form-urlencoded"
|
|
24700
24718
|
},
|
|
24701
|
-
body
|
|
24702
|
-
grant_type: "refresh_token",
|
|
24703
|
-
client_id: clientId,
|
|
24704
|
-
refresh_token: refreshToken
|
|
24705
|
-
})
|
|
24719
|
+
body
|
|
24706
24720
|
});
|
|
24707
24721
|
if (!response.ok) {
|
|
24708
24722
|
const text = await response.text();
|
|
@@ -24890,6 +24904,24 @@ async function refreshStoredAccessToken() {
|
|
|
24890
24904
|
return null;
|
|
24891
24905
|
}
|
|
24892
24906
|
}
|
|
24907
|
+
async function refreshStoredAccessTokenForOrganization(workosOrganizationId) {
|
|
24908
|
+
const clientId = getWorkosClientId();
|
|
24909
|
+
const refreshToken = readRefreshToken();
|
|
24910
|
+
if (!clientId || !refreshToken) {
|
|
24911
|
+
return false;
|
|
24912
|
+
}
|
|
24913
|
+
try {
|
|
24914
|
+
const tokenResponse = await refreshAccessToken(clientId, refreshToken, workosOrganizationId);
|
|
24915
|
+
const nextRefreshToken = tokenResponse.refresh_token ?? refreshToken;
|
|
24916
|
+
writeTokens(tokenResponse.access_token, nextRefreshToken);
|
|
24917
|
+
return true;
|
|
24918
|
+
} catch (error48) {
|
|
24919
|
+
if (error48 instanceof Error && (error48.message.includes(" 400 ") || error48.message.includes(" 401 "))) {
|
|
24920
|
+
removeToken();
|
|
24921
|
+
}
|
|
24922
|
+
return false;
|
|
24923
|
+
}
|
|
24924
|
+
}
|
|
24893
24925
|
async function authenticatedRequest(request) {
|
|
24894
24926
|
const token = readToken();
|
|
24895
24927
|
if (!token) {
|
|
@@ -24953,8 +24985,8 @@ function determineActiveOrganization(organizations, selectedOrganizationId) {
|
|
|
24953
24985
|
};
|
|
24954
24986
|
}
|
|
24955
24987
|
async function resolveOrganizationId(client) {
|
|
24956
|
-
const result = client ? await client.organization.
|
|
24957
|
-
(authenticatedClient) => authenticatedClient.organization.
|
|
24988
|
+
const result = client ? await client.organization.listMyOrganizations() : await authenticatedRequest(
|
|
24989
|
+
(authenticatedClient) => authenticatedClient.organization.listMyOrganizations()
|
|
24958
24990
|
);
|
|
24959
24991
|
if (result.status !== 200) {
|
|
24960
24992
|
console.error(`Failed to resolve organization (status ${result.status}).`);
|
|
@@ -24987,8 +25019,8 @@ async function resolveOrganizationId(client) {
|
|
|
24987
25019
|
}
|
|
24988
25020
|
async function resolveOrganizationIdSafe(client) {
|
|
24989
25021
|
try {
|
|
24990
|
-
const result = client ? await client.organization.
|
|
24991
|
-
(authenticatedClient) => authenticatedClient.organization.
|
|
25022
|
+
const result = client ? await client.organization.listMyOrganizations() : await authenticatedRequestSafe(
|
|
25023
|
+
(authenticatedClient) => authenticatedClient.organization.listMyOrganizations()
|
|
24992
25024
|
);
|
|
24993
25025
|
if (!result) {
|
|
24994
25026
|
return null;
|
|
@@ -25083,7 +25115,7 @@ function isSafeOrganizationId(organizationId) {
|
|
|
25083
25115
|
return SAFE_ORGANIZATION_ID_PATTERN.test(organizationId);
|
|
25084
25116
|
}
|
|
25085
25117
|
async function fetchOrganizationContext() {
|
|
25086
|
-
const result = await authenticatedRequest((client) => client.organization.
|
|
25118
|
+
const result = await authenticatedRequest((client) => client.organization.listMyOrganizations());
|
|
25087
25119
|
if (result.status !== 200) {
|
|
25088
25120
|
console.error(`Failed to list organizations (status ${result.status}).`);
|
|
25089
25121
|
process.exit(1);
|
|
@@ -25163,9 +25195,15 @@ Use an organization ID or exact slug.`
|
|
|
25163
25195
|
};
|
|
25164
25196
|
}
|
|
25165
25197
|
return {
|
|
25166
|
-
error: `Organization '${input}' not found. Run \`tracecli
|
|
25198
|
+
error: `Organization '${input}' not found. Run \`tracecli org list\` to see available organizations.`
|
|
25167
25199
|
};
|
|
25168
25200
|
}
|
|
25201
|
+
async function refreshAfterOrganizationSwitch(workosOrganizationId, refreshForOrganization = (organizationId) => refreshStoredAccessTokenForOrganization(organizationId)) {
|
|
25202
|
+
if (!workosOrganizationId || workosOrganizationId.trim().length === 0) {
|
|
25203
|
+
return false;
|
|
25204
|
+
}
|
|
25205
|
+
return refreshForOrganization(workosOrganizationId);
|
|
25206
|
+
}
|
|
25169
25207
|
function createLoginCommand() {
|
|
25170
25208
|
return new Command("login").description("Authenticate with Trace").action(async () => {
|
|
25171
25209
|
const existingToken = readToken();
|
|
@@ -25342,10 +25380,18 @@ function createOrgSwitchCommand() {
|
|
|
25342
25380
|
process.exit(1);
|
|
25343
25381
|
}
|
|
25344
25382
|
writeSelectedOrganizationId(match.organization.organizationId);
|
|
25383
|
+
const refreshed = await refreshAfterOrganizationSwitch(
|
|
25384
|
+
match.organization.workosOrganizationId
|
|
25385
|
+
);
|
|
25345
25386
|
console.log(
|
|
25346
25387
|
`Active organization set to ${sanitizeForOutput(match.organization.name)} (${sanitizeForOutput(match.organization.slug)})`
|
|
25347
25388
|
);
|
|
25348
25389
|
console.log(` Org ID: ${match.organization.organizationId}`);
|
|
25390
|
+
if (!refreshed) {
|
|
25391
|
+
console.warn(
|
|
25392
|
+
"Token refresh for the selected organization was not completed. If repository commands fail, run `tracecli auth login` again."
|
|
25393
|
+
);
|
|
25394
|
+
}
|
|
25349
25395
|
});
|
|
25350
25396
|
}
|
|
25351
25397
|
function createOrgCommand() {
|
|
@@ -25360,7 +25406,7 @@ function createAuthCommand() {
|
|
|
25360
25406
|
auth.addCommand(createLoginCommand());
|
|
25361
25407
|
auth.addCommand(createLogoutCommand());
|
|
25362
25408
|
auth.addCommand(createStatusCommand());
|
|
25363
|
-
auth.addCommand(createOrgCommand());
|
|
25409
|
+
auth.addCommand(createOrgCommand(), { hidden: true });
|
|
25364
25410
|
return auth;
|
|
25365
25411
|
}
|
|
25366
25412
|
|
|
@@ -26737,6 +26783,7 @@ program2.action(() => {
|
|
|
26737
26783
|
program2.outputHelp();
|
|
26738
26784
|
});
|
|
26739
26785
|
program2.addCommand(createAuthCommand());
|
|
26786
|
+
program2.addCommand(createOrgCommand());
|
|
26740
26787
|
program2.addCommand(createRepoCommand());
|
|
26741
26788
|
program2.addCommand(createVulnerabilitiesCommand());
|
|
26742
26789
|
program2.addCommand(createPentestCommand());
|