@lightdash/cli 2.562.0 → 2.563.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/dist/.tsbuildinfo.build +1 -1
- package/dist/agentConnectionConnectOption.d.ts +8 -0
- package/dist/agentConnectionConnectOption.d.ts.map +1 -0
- package/dist/agentConnectionConnectOption.js +39 -0
- package/dist/agentConnectionOption.d.ts +3 -0
- package/dist/agentConnectionOption.d.ts.map +1 -0
- package/dist/agentConnectionOption.js +48 -0
- package/dist/agentConnections/agentTokenProvider.d.ts +13 -0
- package/dist/agentConnections/agentTokenProvider.d.ts.map +1 -0
- package/dist/agentConnections/agentTokenProvider.js +294 -0
- package/dist/agentConnections/apiUrl.d.ts +4 -0
- package/dist/agentConnections/apiUrl.d.ts.map +1 -0
- package/dist/agentConnections/apiUrl.js +37 -0
- package/dist/agentConnections/commandPolicy.d.ts +14 -0
- package/dist/agentConnections/commandPolicy.d.ts.map +1 -0
- package/dist/agentConnections/commandPolicy.js +108 -0
- package/dist/agentConnections/configLock.d.ts +12 -0
- package/dist/agentConnections/configLock.d.ts.map +1 -0
- package/dist/agentConnections/configLock.js +191 -0
- package/dist/agentConnections/connectInputs.d.ts +20 -0
- package/dist/agentConnections/connectInputs.d.ts.map +1 -0
- package/dist/agentConnections/connectInputs.js +49 -0
- package/dist/agentConnections/fixtures.d.ts +3 -0
- package/dist/agentConnections/fixtures.d.ts.map +1 -0
- package/dist/agentConnections/fixtures.js +36 -0
- package/dist/agentConnections/initialToken.d.ts +26 -0
- package/dist/agentConnections/initialToken.d.ts.map +1 -0
- package/dist/agentConnections/initialToken.js +93 -0
- package/dist/agentConnections/lifecycle.d.ts +17 -0
- package/dist/agentConnections/lifecycle.d.ts.map +1 -0
- package/dist/agentConnections/lifecycle.js +44 -0
- package/dist/agentConnections/personalRecovery.d.ts +27 -0
- package/dist/agentConnections/personalRecovery.d.ts.map +1 -0
- package/dist/agentConnections/personalRecovery.js +71 -0
- package/dist/agentConnections/projectSelection.d.ts +4 -0
- package/dist/agentConnections/projectSelection.d.ts.map +1 -0
- package/dist/agentConnections/projectSelection.js +48 -0
- package/dist/agentConnections/providerProcess.fixture.d.ts +2 -0
- package/dist/agentConnections/providerProcess.fixture.d.ts.map +1 -0
- package/dist/agentConnections/providerProcess.fixture.js +19 -0
- package/dist/agentConnections/requestPolicy.d.ts +11 -0
- package/dist/agentConnections/requestPolicy.d.ts.map +1 -0
- package/dist/agentConnections/requestPolicy.js +76 -0
- package/dist/agentConnections/schema.d.ts +66 -0
- package/dist/agentConnections/schema.d.ts.map +1 -0
- package/dist/agentConnections/schema.js +184 -0
- package/dist/agentConnections/statusResponse.d.ts +10 -0
- package/dist/agentConnections/statusResponse.d.ts.map +1 -0
- package/dist/agentConnections/statusResponse.js +146 -0
- package/dist/agentConnections/store.d.ts +36 -0
- package/dist/agentConnections/store.d.ts.map +1 -0
- package/dist/agentConnections/store.js +275 -0
- package/dist/agentConnections/warehouseStatus.d.ts +30 -0
- package/dist/agentConnections/warehouseStatus.d.ts.map +1 -0
- package/dist/agentConnections/warehouseStatus.js +184 -0
- package/dist/analytics/analytics.d.ts.map +1 -1
- package/dist/analytics/analytics.js +4 -0
- package/dist/config.d.ts +3 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -2
- package/dist/credentials.d.ts +27 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/credentials.js +161 -0
- package/dist/dbt/models.d.ts.map +1 -1
- package/dist/dbt/models.js +45 -14
- package/dist/handlers/agentAccess.d.ts.map +1 -1
- package/dist/handlers/agentAccess.js +9 -1
- package/dist/handlers/agentConnect.d.ts.map +1 -1
- package/dist/handlers/agentConnect.js +2 -0
- package/dist/handlers/agentConnectionConnect.d.ts +5 -0
- package/dist/handlers/agentConnectionConnect.d.ts.map +1 -0
- package/dist/handlers/agentConnectionConnect.js +371 -0
- package/dist/handlers/agentConnectionStatus.d.ts +7 -0
- package/dist/handlers/agentConnectionStatus.d.ts.map +1 -0
- package/dist/handlers/agentConnectionStatus.js +228 -0
- package/dist/handlers/agentRevoke.d.ts +7 -0
- package/dist/handlers/agentRevoke.d.ts.map +1 -0
- package/dist/handlers/agentRevoke.js +144 -0
- package/dist/handlers/agentStatus.d.ts +4 -1
- package/dist/handlers/agentStatus.d.ts.map +1 -1
- package/dist/handlers/agentStatus.js +7 -0
- package/dist/handlers/apps/createApp.d.ts.map +1 -1
- package/dist/handlers/apps/createApp.js +2 -0
- package/dist/handlers/apps/preview.d.ts.map +1 -1
- package/dist/handlers/apps/preview.js +6 -0
- package/dist/handlers/apps/previewProxy.d.ts.map +1 -1
- package/dist/handlers/apps/previewProxy.js +2 -0
- package/dist/handlers/apps/validate.d.ts.map +1 -1
- package/dist/handlers/apps/validate.js +20 -8
- package/dist/handlers/compile.d.ts.map +1 -1
- package/dist/handlers/compile.js +3 -0
- package/dist/handlers/connectSnowflake.d.ts.map +1 -1
- package/dist/handlers/connectSnowflake.js +2 -0
- package/dist/handlers/createProject.d.ts.map +1 -1
- package/dist/handlers/createProject.js +2 -0
- package/dist/handlers/dbt/apiClient.d.ts +4 -2
- package/dist/handlers/dbt/apiClient.d.ts.map +1 -1
- package/dist/handlers/dbt/apiClient.js +138 -4
- package/dist/handlers/dbt/compile.d.ts.map +1 -1
- package/dist/handlers/dbt/compile.js +13 -2
- package/dist/handlers/dbt/getDbtProfileTargetName.d.ts.map +1 -1
- package/dist/handlers/dbt/getDbtProfileTargetName.js +12 -4
- package/dist/handlers/dbt/getDbtVersion.d.ts.map +1 -1
- package/dist/handlers/dbt/getDbtVersion.js +12 -4
- package/dist/handlers/dbt/getWarehouseClient.d.ts.map +1 -1
- package/dist/handlers/dbt/getWarehouseClient.js +15 -5
- package/dist/handlers/dbt/refresh.d.ts.map +1 -1
- package/dist/handlers/dbt/refresh.js +2 -0
- package/dist/handlers/dbt/run.d.ts.map +1 -1
- package/dist/handlers/dbt/run.js +10 -3
- package/dist/handlers/deploy.d.ts.map +1 -1
- package/dist/handlers/deploy.js +17 -1
- package/dist/handlers/diagnostics.d.ts.map +1 -1
- package/dist/handlers/diagnostics.js +2 -0
- package/dist/handlers/download.d.ts.map +1 -1
- package/dist/handlers/download.js +19 -5
- package/dist/handlers/exportChartImage.d.ts.map +1 -1
- package/dist/handlers/exportChartImage.js +2 -0
- package/dist/handlers/generateExposures.d.ts.map +1 -1
- package/dist/handlers/generateExposures.js +4 -1
- package/dist/handlers/getProject.d.ts.map +1 -1
- package/dist/handlers/getProject.js +25 -1
- package/dist/handlers/listProjects.d.ts.map +1 -1
- package/dist/handlers/listProjects.js +2 -0
- package/dist/handlers/login/connectionBrowser.d.ts +2 -0
- package/dist/handlers/login/connectionBrowser.d.ts.map +1 -0
- package/dist/handlers/login/connectionBrowser.js +22 -0
- package/dist/handlers/login/loopback.d.ts +15 -0
- package/dist/handlers/login/loopback.d.ts.map +1 -0
- package/dist/handlers/login/loopback.js +135 -0
- package/dist/handlers/login/oauth.d.ts.map +1 -1
- package/dist/handlers/login/oauth.js +16 -3
- package/dist/handlers/login/pat.d.ts.map +1 -1
- package/dist/handlers/login/pat.js +2 -0
- package/dist/handlers/login.d.ts.map +1 -1
- package/dist/handlers/login.js +8 -1
- package/dist/handlers/oauthLogin.d.ts.map +1 -1
- package/dist/handlers/oauthLogin.js +2 -0
- package/dist/handlers/ordinary/harness.mocks.d.ts +42 -0
- package/dist/handlers/ordinary/harness.mocks.d.ts.map +1 -0
- package/dist/handlers/ordinary/harness.mocks.js +180 -0
- package/dist/handlers/preAggregateAudit.d.ts.map +1 -1
- package/dist/handlers/preAggregateAudit.js +2 -0
- package/dist/handlers/preview.d.ts.map +1 -1
- package/dist/handlers/preview.js +4 -0
- package/dist/handlers/renameHandler.d.ts.map +1 -1
- package/dist/handlers/renameHandler.js +2 -0
- package/dist/handlers/renameProject.d.ts.map +1 -1
- package/dist/handlers/renameProject.js +2 -0
- package/dist/handlers/resolveProjectFlag.d.ts.map +1 -1
- package/dist/handlers/resolveProjectFlag.js +5 -0
- package/dist/handlers/runChart.d.ts.map +1 -1
- package/dist/handlers/runChart.js +7 -2
- package/dist/handlers/selectProject.d.ts.map +1 -1
- package/dist/handlers/selectProject.js +5 -0
- package/dist/handlers/setProject.d.ts.map +1 -1
- package/dist/handlers/setProject.js +5 -0
- package/dist/handlers/setWarehouse.d.ts.map +1 -1
- package/dist/handlers/setWarehouse.js +2 -0
- package/dist/handlers/slugUpdate.d.ts.map +1 -1
- package/dist/handlers/slugUpdate.js +2 -0
- package/dist/handlers/sourceSelection.d.ts.map +1 -1
- package/dist/handlers/sourceSelection.js +13 -2
- package/dist/handlers/sql.d.ts.map +1 -1
- package/dist/handlers/sql.js +7 -2
- package/dist/handlers/utils.d.ts +3 -0
- package/dist/handlers/utils.d.ts.map +1 -1
- package/dist/handlers/utils.js +39 -0
- package/dist/handlers/validate.d.ts.map +1 -1
- package/dist/handlers/validate.js +2 -0
- package/dist/handlers/warehouseCatalog.d.ts.map +1 -1
- package/dist/handlers/warehouseCatalog.js +7 -2
- package/dist/index.js +43 -3
- package/dist/lightdash-config/index.d.ts.map +1 -1
- package/dist/lightdash-config/index.js +4 -1
- package/package.json +3 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providerProcess.fixture.d.ts","sourceRoot":"","sources":["../../src/agentConnections/providerProcess.fixture.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const agentTokenProvider_1 = require("./agentTokenProvider");
|
|
4
|
+
const fixtures_1 = require("./fixtures");
|
|
5
|
+
const store_1 = require("./store");
|
|
6
|
+
const run = async () => {
|
|
7
|
+
const store = new store_1.AgentConnectionStore(process.argv[2]);
|
|
8
|
+
const slot = { ...(0, fixtures_1.slotFixture)(), instanceUrl: process.argv[3] };
|
|
9
|
+
const result = await new agentTokenProvider_1.AgentTokenProvider(store).getToken(slot);
|
|
10
|
+
process.stdout.write(JSON.stringify({
|
|
11
|
+
generation: result.tokens.generation,
|
|
12
|
+
rotated: result.tokens.accessToken === 'new-access' &&
|
|
13
|
+
result.tokens.refreshToken === 'new-refresh',
|
|
14
|
+
}));
|
|
15
|
+
};
|
|
16
|
+
void run().catch((error) => {
|
|
17
|
+
process.stderr.write(error.message);
|
|
18
|
+
process.exitCode = 1;
|
|
19
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
type RequestPolicy = {
|
|
2
|
+
method: string;
|
|
3
|
+
path: string;
|
|
4
|
+
operation: string;
|
|
5
|
+
safeRead: boolean;
|
|
6
|
+
};
|
|
7
|
+
export declare const REQUEST_POLICY: readonly RequestPolicy[];
|
|
8
|
+
export declare const isAgentRequestAllowed: (method: string, url: string) => boolean;
|
|
9
|
+
export declare const assertAgentRequestAllowed: (method: string, url: string) => void;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=requestPolicy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requestPolicy.d.ts","sourceRoot":"","sources":["../../src/agentConnections/requestPolicy.ts"],"names":[],"mappings":"AAAA,KAAK,aAAa,GAAG;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;CACrB,CAAC;AAOF,eAAO,MAAM,cAAc,EAAE,SAAS,aAAa,EAgPlD,CAAC;AAEF,eAAO,MAAM,qBAAqB,WAAY,MAAM,OAAO,MAAM,KAAG,OAenE,CAAC;AAEF,eAAO,MAAM,yBAAyB,WAC1B,MAAM,OACT,MAAM,KACZ,IAKF,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.assertAgentRequestAllowed = exports.isAgentRequestAllowed = exports.REQUEST_POLICY = void 0;
|
|
4
|
+
const route = (method, path, operation) => ({ method, path, operation, safeRead: method === 'GET' });
|
|
5
|
+
exports.REQUEST_POLICY = [
|
|
6
|
+
route('GET', '/api/v1/user', 'UserController.getAuthenticatedUser'),
|
|
7
|
+
route('GET', '/api/v1/health', 'apiV1Router GET /health'),
|
|
8
|
+
route('GET', '/api/v2/user/agent-connections/:grant/status', 'AgentConnectionController.getConnectionStatus'),
|
|
9
|
+
route('DELETE', '/api/v2/user/agent-connections/:grant', 'AgentConnectionController.revoke'),
|
|
10
|
+
route('GET', '/api/v2/projects/:project/ai-access/me', 'AiAccessController.getMyAccess'),
|
|
11
|
+
route('GET', '/api/v1/projects/:project', 'ProjectController.getProject'),
|
|
12
|
+
route('GET', '/api/v1/projects/:project/dbt/manifest', 'ProjectController.getMergedManifest'),
|
|
13
|
+
route('GET', '/api/v1/projects/:project/dbt-exposures', 'ProjectController.GetDbtExposures'),
|
|
14
|
+
route('GET', '/api/v1/projects/:project/explores', 'ExploreController.GetExplores'),
|
|
15
|
+
route('GET', '/api/v1/projects/:project/explores/:explore', 'ExploreController.GetExplore'),
|
|
16
|
+
route('GET', '/api/v2/projects/:project/query/:query', 'QueryController.getAsyncQueryResults'),
|
|
17
|
+
route('POST', '/api/v2/projects/:project/query/sql', 'QueryController.executeAsyncSqlQuery'),
|
|
18
|
+
route('POST', '/api/v2/projects/:project/query/metric-query', 'QueryController.executeAsyncMetricQuery'),
|
|
19
|
+
route('GET', '/api/v1/projects/:project/sqlRunner/fields', 'SqlRunnerController.getTableFields'),
|
|
20
|
+
route('GET', '/api/v1/projects/:project/sqlRunner/tables', 'SqlRunnerController.getTables'),
|
|
21
|
+
route('POST', '/api/v1/projects/:project/sqlRunner/refresh-catalog', 'SqlRunnerController.refreshSqlRunnerCatalog'),
|
|
22
|
+
route('POST', '/api/v1/projects/:project/refresh', 'ProjectController.refresh'),
|
|
23
|
+
route('PUT', '/api/v1/projects/:project/tags/yaml', 'ProjectController.replaceYamlTags'),
|
|
24
|
+
route('PUT', '/api/v2/projects/:project/parameters', 'ParametersController.replaceParameters'),
|
|
25
|
+
route('PUT', '/api/v2/projects/:project/defaults', 'ProjectDefaultsController.replaceProjectDefaults'),
|
|
26
|
+
route('PUT', '/api/v1/projects/:project/table-groups', 'ProjectController.replaceProjectTableGroups'),
|
|
27
|
+
route('POST', '/api/v2/projects/:project/deploy', 'DeployController.startDeploySession'),
|
|
28
|
+
route('POST', '/api/v2/projects/:project/deploy/:session/batch', 'DeployController.addDeployBatch'),
|
|
29
|
+
route('POST', '/api/v2/projects/:project/deploy/:session/finalize', 'DeployController.finalizeDeploySession'),
|
|
30
|
+
route('PUT', '/api/v2/projects/:project/deploy', 'DeployController.deployExplores'),
|
|
31
|
+
route('PUT', '/api/v1/projects/:project/explores', 'ExploreController.SetExplores'),
|
|
32
|
+
route('GET', '/api/v2/content', 'ContentController.listContent'),
|
|
33
|
+
route('GET', '/api/v1/ee/projects/:project/apps', 'AppGenerateController.listProjectApps'),
|
|
34
|
+
route('GET', '/api/v1/ee/projects/:project/apps/chart-types', 'AppGenerateController.listProjectChartTypes'),
|
|
35
|
+
route('GET', '/api/v1/ee/projects/:project/apps/:app/download', 'AppGenerateController.getAppCode'),
|
|
36
|
+
route('GET', '/api/v1/projects/:project/spaces', 'ProjectController.getSpacesInProject'),
|
|
37
|
+
route('GET', '/api/v1/projects/:project/dashboards', 'ProjectController.getDashboards'),
|
|
38
|
+
route('GET', '/api/v1/projects/:project/dbt-sources', 'ProjectDbtSourcesController.listProjectDbtSources'),
|
|
39
|
+
route('GET', '/api/v1/projects/:project/validate', 'ValidationController.get'),
|
|
40
|
+
route('GET', '/api/v1/projects/:project/code/charts', 'ProjectCoderController.getChartsAsCode'),
|
|
41
|
+
route('GET', '/api/v1/projects/:project/code/dashboards', 'ProjectCoderController.getDashboardsAsCode'),
|
|
42
|
+
route('GET', '/api/v1/projects/:project/code/sqlCharts', 'ProjectCoderController.getSqlChartsAsCode'),
|
|
43
|
+
route('GET', '/api/v1/projects/:project/code/virtualViews', 'ProjectCoderController.getVirtualViewsAsCode'),
|
|
44
|
+
route('GET', '/api/v1/projects/:project/code/externalConnections', 'ProjectCoderController.getExternalConnectionsAsCode'),
|
|
45
|
+
route('GET', '/api/v1/projects/:project/code/documents', 'ProjectCoderController.getDocumentsAsCode'),
|
|
46
|
+
route('GET', '/api/v1/projects/:project/code/aiAgents', 'ProjectCoderController.getAiAgentsAsCode'),
|
|
47
|
+
route('GET', '/api/v1/projects/:project/code/alerts', 'ProjectCoderController.getAlertsAsCode'),
|
|
48
|
+
route('GET', '/api/v1/projects/:project/code/googleSheets', 'ProjectCoderController.getGoogleSheetsSyncsAsCode'),
|
|
49
|
+
route('GET', '/api/v1/projects/:project/code/scheduledDeliveries', 'ProjectCoderController.getScheduledDeliveriesAsCode'),
|
|
50
|
+
route('GET', '/api/v1/projects/:project/code/homepages', 'ProjectCoderController.getHomepagesAsCode'),
|
|
51
|
+
route('GET', '/api/v1/projects/:project/code/spaces', 'ProjectCoderController.getCodeSpaces'),
|
|
52
|
+
route('GET', '/api/v1/projects/:project/code/upload-advisory', 'ProjectCoderController.getContentAsCodeUploadAdvisory'),
|
|
53
|
+
route('POST', '/api/v1/projects/:project/code/charts/:slug', 'ProjectCoderController.upsertChartAsCode'),
|
|
54
|
+
route('POST', '/api/v1/projects/:project/code/dashboards/:slug', 'ProjectCoderController.upsertDashboardAsCode'),
|
|
55
|
+
route('POST', '/api/v1/projects/:project/code/sqlCharts/:slug', 'ProjectCoderController.upsertSqlChartAsCode'),
|
|
56
|
+
route('POST', '/api/v1/projects/:project/code/virtualViews/:slug', 'ProjectCoderController.upsertVirtualViewAsCode'),
|
|
57
|
+
];
|
|
58
|
+
const isAgentRequestAllowed = (method, url) => {
|
|
59
|
+
const path = url.split(/[?#]/, 1)[0];
|
|
60
|
+
const parts = path.split('/');
|
|
61
|
+
return exports.REQUEST_POLICY.some((entry) => {
|
|
62
|
+
if (entry.method !== method)
|
|
63
|
+
return false;
|
|
64
|
+
const pattern = entry.path.split('/');
|
|
65
|
+
return (parts.length === pattern.length &&
|
|
66
|
+
pattern.every((part, index) => part.startsWith(':')
|
|
67
|
+
? parts[index].length > 0
|
|
68
|
+
: part === parts[index]));
|
|
69
|
+
});
|
|
70
|
+
};
|
|
71
|
+
exports.isAgentRequestAllowed = isAgentRequestAllowed;
|
|
72
|
+
const assertAgentRequestAllowed = (method, url) => {
|
|
73
|
+
if (!(0, exports.isAgentRequestAllowed)(method, url))
|
|
74
|
+
throw new Error('This request is not available with an agent connection. No request was sent.');
|
|
75
|
+
};
|
|
76
|
+
exports.assertAgentRequestAllowed = assertAgentRequestAllowed;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { AgentCapability } from '@lightdash/common';
|
|
2
|
+
export type SlotKey = {
|
|
3
|
+
instanceUrl: string;
|
|
4
|
+
organizationUuid: string;
|
|
5
|
+
personUuid: string;
|
|
6
|
+
name: string;
|
|
7
|
+
};
|
|
8
|
+
export type AgentConnectionStatusReason = 'invalid_grant' | 'not_supported' | 'revoked' | 'expired' | 'agent_identity_disabled' | 'project_access' | 'person_permission' | 'agent_policy';
|
|
9
|
+
export type AgentConnectionSlot = SlotKey & {
|
|
10
|
+
clientId: 'lightdash-cli';
|
|
11
|
+
resource: string;
|
|
12
|
+
grantUuid: string;
|
|
13
|
+
grantRevision: number | null;
|
|
14
|
+
approvedAt: string;
|
|
15
|
+
grantExpiresAt: string;
|
|
16
|
+
tokens: {
|
|
17
|
+
accessToken: string;
|
|
18
|
+
accessTokenExpiresAt: string;
|
|
19
|
+
refreshToken: string;
|
|
20
|
+
refreshTokenExpiresAt: string | null;
|
|
21
|
+
scopes: string[];
|
|
22
|
+
generation: number;
|
|
23
|
+
lastRefreshAttemptUuid: string | null;
|
|
24
|
+
};
|
|
25
|
+
lastReported: {
|
|
26
|
+
checkedAt: string;
|
|
27
|
+
limitsStatus: 'ok' | 'invalid';
|
|
28
|
+
approvedProjects: {
|
|
29
|
+
projectUuid: string;
|
|
30
|
+
name: string | null;
|
|
31
|
+
approvedCapabilities: AgentCapability[];
|
|
32
|
+
}[];
|
|
33
|
+
effectiveProjects: {
|
|
34
|
+
projectUuid: string;
|
|
35
|
+
capabilities: {
|
|
36
|
+
capability: AgentCapability;
|
|
37
|
+
allowed: boolean;
|
|
38
|
+
reason: AgentConnectionStatusReason | null;
|
|
39
|
+
}[];
|
|
40
|
+
}[];
|
|
41
|
+
status: 'active' | 'expired' | 'revoked';
|
|
42
|
+
lastUsedAt: string | null;
|
|
43
|
+
revokedAt: string | null;
|
|
44
|
+
};
|
|
45
|
+
refreshState: {
|
|
46
|
+
kind: 'idle';
|
|
47
|
+
} | {
|
|
48
|
+
kind: 'in_progress';
|
|
49
|
+
attemptUuid: string;
|
|
50
|
+
startedAt: string;
|
|
51
|
+
} | {
|
|
52
|
+
kind: 'reconnect_required';
|
|
53
|
+
since: string;
|
|
54
|
+
};
|
|
55
|
+
revokeState: {
|
|
56
|
+
kind: 'none';
|
|
57
|
+
} | {
|
|
58
|
+
kind: 'unconfirmed';
|
|
59
|
+
attemptedAt: string;
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
export declare const invalidConnection: () => Error;
|
|
63
|
+
export declare const canonicalInstanceUrl: (input: string) => string;
|
|
64
|
+
export declare const slotValidator: (value: unknown) => value is AgentConnectionSlot;
|
|
65
|
+
export declare const validateSlot: (value: unknown, key: SlotKey) => AgentConnectionSlot;
|
|
66
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/agentConnections/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAIpD,MAAM,MAAM,OAAO,GAAG;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CAChB,CAAC;AACF,MAAM,MAAM,2BAA2B,GACjC,eAAe,GACf,eAAe,GACf,SAAS,GACT,SAAS,GACT,yBAAyB,GACzB,gBAAgB,GAChB,mBAAmB,GACnB,cAAc,CAAC;AACrB,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG;IACxC,QAAQ,EAAE,eAAe,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE;QACJ,WAAW,EAAE,MAAM,CAAC;QACpB,oBAAoB,EAAE,MAAM,CAAC;QAC7B,YAAY,EAAE,MAAM,CAAC;QACrB,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;QACrC,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAC;KACzC,CAAC;IACF,YAAY,EAAE;QACV,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,IAAI,GAAG,SAAS,CAAC;QAC/B,gBAAgB,EAAE;YACd,WAAW,EAAE,MAAM,CAAC;YACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;YACpB,oBAAoB,EAAE,eAAe,EAAE,CAAC;SAC3C,EAAE,CAAC;QACJ,iBAAiB,EAAE;YACf,WAAW,EAAE,MAAM,CAAC;YACpB,YAAY,EAAE;gBACV,UAAU,EAAE,eAAe,CAAC;gBAC5B,OAAO,EAAE,OAAO,CAAC;gBACjB,MAAM,EAAE,2BAA2B,GAAG,IAAI,CAAC;aAC9C,EAAE,CAAC;SACP,EAAE,CAAC;QACJ,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;QACzC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;KAC5B,CAAC;IACF,YAAY,EACN;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAChB;QAAE,IAAI,EAAE,aAAa,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAC/D;QAAE,IAAI,EAAE,oBAAoB,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACpD,WAAW,EACL;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAChB;QAAE,IAAI,EAAE,aAAa,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;CACtD,CAAC;AACF,eAAO,MAAM,iBAAiB,QAAO,KAGhC,CAAC;AACN,eAAO,MAAM,oBAAoB,UAAW,MAAM,KAAG,MAmBpD,CAAC;AAsHF,eAAO,MAAM,aAAa,UAAW,OAAO,KAAG,KAAK,IAAI,mBAGvD,CAAC;AACF,eAAO,MAAM,YAAY,UACd,OAAO,OACT,OAAO,KACb,mBAuDF,CAAC"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateSlot = exports.slotValidator = exports.canonicalInstanceUrl = exports.invalidConnection = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const common_1 = require("@lightdash/common");
|
|
6
|
+
const ajv_1 = tslib_1.__importDefault(require("ajv"));
|
|
7
|
+
const ajv_formats_1 = tslib_1.__importDefault(require("ajv-formats"));
|
|
8
|
+
const invalidConnection = () => new Error('Invalid agent connection data. Reconnect before using this slot.');
|
|
9
|
+
exports.invalidConnection = invalidConnection;
|
|
10
|
+
const canonicalInstanceUrl = (input) => {
|
|
11
|
+
try {
|
|
12
|
+
const url = new URL(input);
|
|
13
|
+
if (url.username ||
|
|
14
|
+
url.password ||
|
|
15
|
+
url.search ||
|
|
16
|
+
url.hash ||
|
|
17
|
+
(url.protocol !== 'https:' &&
|
|
18
|
+
!(url.protocol === 'http:' &&
|
|
19
|
+
['localhost', '127.0.0.1', '[::1]'].includes(url.hostname))))
|
|
20
|
+
throw (0, exports.invalidConnection)();
|
|
21
|
+
return url.href.replace(/\/+$/, '');
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
throw (0, exports.invalidConnection)();
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
exports.canonicalInstanceUrl = canonicalInstanceUrl;
|
|
28
|
+
const text = { type: 'string', minLength: 1 };
|
|
29
|
+
const uuid = { type: 'string', format: 'uuid' };
|
|
30
|
+
const date = {
|
|
31
|
+
type: 'string',
|
|
32
|
+
format: 'date-time',
|
|
33
|
+
pattern: '^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$',
|
|
34
|
+
};
|
|
35
|
+
const nullable = (schema) => ({ anyOf: [schema, { type: 'null' }] });
|
|
36
|
+
const object = (properties) => ({
|
|
37
|
+
type: 'object',
|
|
38
|
+
properties,
|
|
39
|
+
required: Object.keys(properties),
|
|
40
|
+
});
|
|
41
|
+
const array = (items) => ({ type: 'array', items, uniqueItems: true });
|
|
42
|
+
const capability = { enum: Object.values(common_1.AgentCapability) };
|
|
43
|
+
const createSlotValidator = () => {
|
|
44
|
+
const ajv = new ajv_1.default();
|
|
45
|
+
(0, ajv_formats_1.default)(ajv);
|
|
46
|
+
return ajv.compile(object({
|
|
47
|
+
instanceUrl: text,
|
|
48
|
+
organizationUuid: uuid,
|
|
49
|
+
personUuid: uuid,
|
|
50
|
+
name: {
|
|
51
|
+
type: 'string',
|
|
52
|
+
pattern: '^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$',
|
|
53
|
+
},
|
|
54
|
+
clientId: { const: 'lightdash-cli' },
|
|
55
|
+
resource: text,
|
|
56
|
+
grantUuid: uuid,
|
|
57
|
+
grantRevision: nullable({ type: 'integer', minimum: 1 }),
|
|
58
|
+
approvedAt: date,
|
|
59
|
+
grantExpiresAt: date,
|
|
60
|
+
tokens: object({
|
|
61
|
+
accessToken: text,
|
|
62
|
+
accessTokenExpiresAt: date,
|
|
63
|
+
refreshToken: text,
|
|
64
|
+
refreshTokenExpiresAt: nullable(date),
|
|
65
|
+
scopes: {
|
|
66
|
+
...array({
|
|
67
|
+
type: 'string',
|
|
68
|
+
pattern: '^[\\x21\\x23-\\x5B\\x5D-\\x7E]+$',
|
|
69
|
+
}),
|
|
70
|
+
minItems: 1,
|
|
71
|
+
},
|
|
72
|
+
generation: {
|
|
73
|
+
type: 'integer',
|
|
74
|
+
minimum: 1,
|
|
75
|
+
maximum: Number.MAX_SAFE_INTEGER,
|
|
76
|
+
},
|
|
77
|
+
lastRefreshAttemptUuid: nullable(uuid),
|
|
78
|
+
}),
|
|
79
|
+
lastReported: object({
|
|
80
|
+
checkedAt: date,
|
|
81
|
+
limitsStatus: { enum: ['ok', 'invalid'] },
|
|
82
|
+
approvedProjects: array(object({
|
|
83
|
+
projectUuid: uuid,
|
|
84
|
+
name: nullable({ type: 'string' }),
|
|
85
|
+
approvedCapabilities: array(capability),
|
|
86
|
+
})),
|
|
87
|
+
effectiveProjects: array(object({
|
|
88
|
+
projectUuid: uuid,
|
|
89
|
+
capabilities: array(object({
|
|
90
|
+
capability,
|
|
91
|
+
allowed: { type: 'boolean' },
|
|
92
|
+
reason: {
|
|
93
|
+
enum: [
|
|
94
|
+
null,
|
|
95
|
+
'invalid_grant',
|
|
96
|
+
'not_supported',
|
|
97
|
+
'revoked',
|
|
98
|
+
'expired',
|
|
99
|
+
'agent_identity_disabled',
|
|
100
|
+
'project_access',
|
|
101
|
+
'person_permission',
|
|
102
|
+
'agent_policy',
|
|
103
|
+
],
|
|
104
|
+
},
|
|
105
|
+
})),
|
|
106
|
+
})),
|
|
107
|
+
status: { enum: ['active', 'expired', 'revoked'] },
|
|
108
|
+
lastUsedAt: nullable(date),
|
|
109
|
+
revokedAt: nullable(date),
|
|
110
|
+
}),
|
|
111
|
+
refreshState: {
|
|
112
|
+
oneOf: [
|
|
113
|
+
object({ kind: { const: 'idle' } }),
|
|
114
|
+
object({
|
|
115
|
+
kind: { const: 'in_progress' },
|
|
116
|
+
attemptUuid: uuid,
|
|
117
|
+
startedAt: date,
|
|
118
|
+
}),
|
|
119
|
+
object({
|
|
120
|
+
kind: { const: 'reconnect_required' },
|
|
121
|
+
since: date,
|
|
122
|
+
}),
|
|
123
|
+
],
|
|
124
|
+
},
|
|
125
|
+
revokeState: {
|
|
126
|
+
oneOf: [
|
|
127
|
+
object({ kind: { const: 'none' } }),
|
|
128
|
+
object({
|
|
129
|
+
kind: { const: 'unconfirmed' },
|
|
130
|
+
attemptedAt: date,
|
|
131
|
+
}),
|
|
132
|
+
],
|
|
133
|
+
},
|
|
134
|
+
}));
|
|
135
|
+
};
|
|
136
|
+
let validator = null;
|
|
137
|
+
const slotValidator = (value) => {
|
|
138
|
+
validator ??= createSlotValidator();
|
|
139
|
+
return validator(value);
|
|
140
|
+
};
|
|
141
|
+
exports.slotValidator = slotValidator;
|
|
142
|
+
const validateSlot = (value, key) => {
|
|
143
|
+
if (!(0, exports.slotValidator)(value))
|
|
144
|
+
throw (0, exports.invalidConnection)();
|
|
145
|
+
if (value.instanceUrl !== (0, exports.canonicalInstanceUrl)(value.instanceUrl) ||
|
|
146
|
+
value.resource !== value.instanceUrl ||
|
|
147
|
+
value.instanceUrl !== key.instanceUrl ||
|
|
148
|
+
value.organizationUuid !== key.organizationUuid ||
|
|
149
|
+
value.personUuid !== key.personUuid ||
|
|
150
|
+
value.name !== key.name ||
|
|
151
|
+
Date.parse(value.approvedAt) >= Date.parse(value.grantExpiresAt) ||
|
|
152
|
+
Date.parse(value.tokens.accessTokenExpiresAt) >
|
|
153
|
+
Date.parse(value.grantExpiresAt) ||
|
|
154
|
+
(value.tokens.refreshTokenExpiresAt !== null &&
|
|
155
|
+
Date.parse(value.tokens.refreshTokenExpiresAt) >
|
|
156
|
+
Date.parse(value.grantExpiresAt)))
|
|
157
|
+
throw (0, exports.invalidConnection)();
|
|
158
|
+
const approved = new Map(value.lastReported.approvedProjects.map((p) => [
|
|
159
|
+
p.projectUuid,
|
|
160
|
+
p.approvedCapabilities,
|
|
161
|
+
]));
|
|
162
|
+
const effective = new Set(value.lastReported.effectiveProjects.map((p) => p.projectUuid));
|
|
163
|
+
if (approved.size !== value.lastReported.approvedProjects.length ||
|
|
164
|
+
effective.size !== value.lastReported.effectiveProjects.length ||
|
|
165
|
+
approved.size !== effective.size)
|
|
166
|
+
throw (0, exports.invalidConnection)();
|
|
167
|
+
for (const project of value.lastReported.effectiveProjects) {
|
|
168
|
+
const capabilities = approved.get(project.projectUuid);
|
|
169
|
+
if (!capabilities ||
|
|
170
|
+
new Set(project.capabilities.map((c) => c.capability)).size !==
|
|
171
|
+
project.capabilities.length ||
|
|
172
|
+
(value.lastReported.limitsStatus === 'ok' &&
|
|
173
|
+
project.capabilities.length !== capabilities.length) ||
|
|
174
|
+
(value.lastReported.limitsStatus === 'invalid' &&
|
|
175
|
+
(capabilities.length !== 0 ||
|
|
176
|
+
project.capabilities.some((c) => c.allowed || c.reason !== 'invalid_grant'))) ||
|
|
177
|
+
project.capabilities.some((c) => (value.lastReported.limitsStatus === 'ok' &&
|
|
178
|
+
!capabilities.includes(c.capability)) ||
|
|
179
|
+
c.allowed !== (c.reason === null)))
|
|
180
|
+
throw (0, exports.invalidConnection)();
|
|
181
|
+
}
|
|
182
|
+
return value;
|
|
183
|
+
};
|
|
184
|
+
exports.validateSlot = validateSlot;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type AgentConnectionSlot, type AgentConnectionStatusReason } from './schema';
|
|
2
|
+
export declare class ConnectionMismatchError extends Error {
|
|
3
|
+
constructor();
|
|
4
|
+
}
|
|
5
|
+
export declare const responseRecord: (value: unknown) => Record<string, unknown>;
|
|
6
|
+
export declare const publicTextIsSafe: (value: string, secrets: readonly (string | null | undefined)[], maxLength?: number) => boolean;
|
|
7
|
+
export declare const publicConnectionReport: (slot: AgentConnectionSlot, extraSecrets?: readonly (string | null | undefined)[]) => AgentConnectionSlot['lastReported'];
|
|
8
|
+
export declare const connectionResponse: (value: unknown, slot: AgentConnectionSlot, requireEffective: boolean, extraSecrets?: readonly (string | null | undefined)[]) => AgentConnectionSlot;
|
|
9
|
+
export declare const statusReasonMessage: (reason: AgentConnectionStatusReason | null) => string | null;
|
|
10
|
+
//# sourceMappingURL=statusResponse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statusResponse.d.ts","sourceRoot":"","sources":["../../src/agentConnections/statusResponse.ts"],"names":[],"mappings":"AACA,OAAO,EAEH,KAAK,mBAAmB,EACxB,KAAK,2BAA2B,EACnC,MAAM,UAAU,CAAC;AAElB,qBAAa,uBAAwB,SAAQ,KAAK;IAC9C,cAEC;CACJ;AACD,eAAO,MAAM,cAAc,UAAW,OAAO,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAIrE,CAAC;AACF,eAAO,MAAM,gBAAgB,UAClB,MAAM,WACJ,SAAS,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,yBAEhD,OAwBF,CAAC;AACF,eAAO,MAAM,sBAAsB,SACzB,mBAAmB,iBACX,SAAS,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,KACrD,mBAAmB,CAAC,cAAc,CA2BnC,CAAC;AACH,eAAO,MAAM,kBAAkB,UACpB,OAAO,QACR,mBAAmB,oBACP,OAAO,iBACV,SAAS,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,KACtD,mBA0EF,CAAC;AACF,eAAO,MAAM,mBAAmB,WACpB,2BAA2B,GAAG,IAAI,KAC3C,MAAM,GAAG,IA0BX,CAAC"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.statusReasonMessage = exports.connectionResponse = exports.publicConnectionReport = exports.publicTextIsSafe = exports.responseRecord = exports.ConnectionMismatchError = void 0;
|
|
4
|
+
const common_1 = require("@lightdash/common");
|
|
5
|
+
const schema_1 = require("./schema");
|
|
6
|
+
class ConnectionMismatchError extends Error {
|
|
7
|
+
constructor() {
|
|
8
|
+
super('The server returned a different connection.');
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
exports.ConnectionMismatchError = ConnectionMismatchError;
|
|
12
|
+
const responseRecord = (value) => {
|
|
13
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
14
|
+
throw new Error('The server returned invalid connection data.');
|
|
15
|
+
return Object.fromEntries(Object.entries(value));
|
|
16
|
+
};
|
|
17
|
+
exports.responseRecord = responseRecord;
|
|
18
|
+
const publicTextIsSafe = (value, secrets, maxLength = 2048) => {
|
|
19
|
+
if (value.length > maxLength)
|
|
20
|
+
return false;
|
|
21
|
+
const containsSecret = (text) => secrets.some((secret) => secret && text.includes(secret));
|
|
22
|
+
let decoded = value;
|
|
23
|
+
while (true) {
|
|
24
|
+
if (containsSecret(decoded))
|
|
25
|
+
return false;
|
|
26
|
+
if (URL.canParse(decoded)) {
|
|
27
|
+
const url = new URL(decoded);
|
|
28
|
+
if (containsSecret(url.href) ||
|
|
29
|
+
[...url.searchParams].some(([key, item]) => containsSecret(key) || containsSecret(item)))
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
const next = decoded.replace(/(?:%[0-9a-f]{2})+/gi, (encoded) => Buffer.from(encoded.replaceAll('%', ''), 'hex').toString('utf8'));
|
|
33
|
+
if (next === decoded)
|
|
34
|
+
return true;
|
|
35
|
+
decoded = next;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
exports.publicTextIsSafe = publicTextIsSafe;
|
|
39
|
+
const publicConnectionReport = (slot, extraSecrets = []) => ({
|
|
40
|
+
checkedAt: slot.lastReported.checkedAt,
|
|
41
|
+
status: slot.lastReported.status,
|
|
42
|
+
limitsStatus: slot.lastReported.limitsStatus,
|
|
43
|
+
lastUsedAt: slot.lastReported.lastUsedAt,
|
|
44
|
+
revokedAt: slot.lastReported.revokedAt,
|
|
45
|
+
approvedProjects: slot.lastReported.approvedProjects.map((project) => ({
|
|
46
|
+
projectUuid: project.projectUuid,
|
|
47
|
+
name: project.name !== null &&
|
|
48
|
+
!(0, exports.publicTextIsSafe)(project.name, [
|
|
49
|
+
slot.tokens.accessToken,
|
|
50
|
+
slot.tokens.refreshToken,
|
|
51
|
+
...extraSecrets,
|
|
52
|
+
])
|
|
53
|
+
? null
|
|
54
|
+
: project.name,
|
|
55
|
+
approvedCapabilities: project.approvedCapabilities,
|
|
56
|
+
})),
|
|
57
|
+
effectiveProjects: slot.lastReported.effectiveProjects.map((project) => ({
|
|
58
|
+
projectUuid: project.projectUuid,
|
|
59
|
+
capabilities: project.capabilities.map((action) => ({
|
|
60
|
+
capability: action.capability,
|
|
61
|
+
allowed: action.allowed,
|
|
62
|
+
reason: action.reason,
|
|
63
|
+
})),
|
|
64
|
+
})),
|
|
65
|
+
});
|
|
66
|
+
exports.publicConnectionReport = publicConnectionReport;
|
|
67
|
+
const connectionResponse = (value, slot, requireEffective, extraSecrets) => {
|
|
68
|
+
const envelope = (0, exports.responseRecord)(value);
|
|
69
|
+
if (envelope.status !== 'ok')
|
|
70
|
+
throw new Error('The server returned invalid connection data.');
|
|
71
|
+
const record = (0, exports.responseRecord)(envelope.results);
|
|
72
|
+
if (['grantUuid', 'name', 'clientId', 'approvedAt', 'expiresAt'].some((field) => typeof record[field] !== 'string'))
|
|
73
|
+
throw new Error('The server returned invalid connection data.');
|
|
74
|
+
if (record.grantUuid !== slot.grantUuid ||
|
|
75
|
+
record.name !== slot.name ||
|
|
76
|
+
record.clientId !== slot.clientId ||
|
|
77
|
+
record.approvedAt !== slot.approvedAt ||
|
|
78
|
+
record.expiresAt !== slot.grantExpiresAt)
|
|
79
|
+
throw new ConnectionMismatchError();
|
|
80
|
+
const revokedProjects = !requireEffective && Array.isArray(record.approvedProjects)
|
|
81
|
+
? record.approvedProjects.map((entry) => {
|
|
82
|
+
const project = (0, exports.responseRecord)(entry);
|
|
83
|
+
return {
|
|
84
|
+
projectUuid: project.projectUuid,
|
|
85
|
+
capabilities: Array.isArray(project.approvedCapabilities)
|
|
86
|
+
? project.approvedCapabilities.map((capability) => ({
|
|
87
|
+
capability,
|
|
88
|
+
allowed: false,
|
|
89
|
+
reason: 'revoked',
|
|
90
|
+
}))
|
|
91
|
+
: null,
|
|
92
|
+
};
|
|
93
|
+
})
|
|
94
|
+
: null;
|
|
95
|
+
const checked = (0, schema_1.validateSlot)({
|
|
96
|
+
...slot,
|
|
97
|
+
lastReported: {
|
|
98
|
+
checkedAt: new Date().toISOString(),
|
|
99
|
+
limitsStatus: record.limitsStatus,
|
|
100
|
+
approvedProjects: record.approvedProjects,
|
|
101
|
+
effectiveProjects: requireEffective
|
|
102
|
+
? record.effectiveProjects
|
|
103
|
+
: revokedProjects,
|
|
104
|
+
status: record.status,
|
|
105
|
+
lastUsedAt: record.lastUsedAt,
|
|
106
|
+
revokedAt: record.revokedAt,
|
|
107
|
+
},
|
|
108
|
+
}, slot);
|
|
109
|
+
if (checked.lastReported.status === 'revoked' &&
|
|
110
|
+
checked.lastReported.revokedAt === null)
|
|
111
|
+
throw new Error('The server returned invalid revocation data.');
|
|
112
|
+
if (extraSecrets === undefined &&
|
|
113
|
+
checked.lastReported.approvedProjects.some((project) => project.name !== null &&
|
|
114
|
+
[slot.tokens.accessToken, slot.tokens.refreshToken].some((secret) => project.name?.includes(secret))))
|
|
115
|
+
throw new Error('The server returned unsafe connection data.');
|
|
116
|
+
return {
|
|
117
|
+
...checked,
|
|
118
|
+
lastReported: (0, exports.publicConnectionReport)(checked, extraSecrets),
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
exports.connectionResponse = connectionResponse;
|
|
122
|
+
const statusReasonMessage = (reason) => {
|
|
123
|
+
switch (reason) {
|
|
124
|
+
case null:
|
|
125
|
+
return null;
|
|
126
|
+
case 'invalid_grant':
|
|
127
|
+
return 'Connection limits are invalid.';
|
|
128
|
+
case 'not_supported':
|
|
129
|
+
return 'This action is not available to agent connections.';
|
|
130
|
+
case 'revoked':
|
|
131
|
+
return 'This connection was revoked.';
|
|
132
|
+
case 'expired':
|
|
133
|
+
return 'This connection expired.';
|
|
134
|
+
case 'agent_identity_disabled':
|
|
135
|
+
return 'Agent identity is disabled.';
|
|
136
|
+
case 'project_access':
|
|
137
|
+
return 'You no longer have access to this project.';
|
|
138
|
+
case 'person_permission':
|
|
139
|
+
return 'Your role does not allow this action.';
|
|
140
|
+
case 'agent_policy':
|
|
141
|
+
return "Your organisation's agent permissions do not allow this action.";
|
|
142
|
+
default:
|
|
143
|
+
return (0, common_1.assertUnreachable)(reason, 'Unknown connection status reason');
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
exports.statusReasonMessage = statusReasonMessage;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type AgentConnectionSlot, type SlotKey } from './schema';
|
|
2
|
+
export declare const getAgentConnectionsFilePath: () => string;
|
|
3
|
+
export type RefreshJournal = {
|
|
4
|
+
grantUuid: string;
|
|
5
|
+
attemptUuid: string;
|
|
6
|
+
generation: number;
|
|
7
|
+
};
|
|
8
|
+
export type LockedStore = {
|
|
9
|
+
readSlot: (key: SlotKey) => Promise<AgentConnectionSlot | null>;
|
|
10
|
+
saveSlot: (slot: AgentConnectionSlot) => Promise<void>;
|
|
11
|
+
readJournal: (key: SlotKey) => Promise<RefreshJournal | null>;
|
|
12
|
+
writeJournal: (key: SlotKey, journal: RefreshJournal) => Promise<void>;
|
|
13
|
+
clearJournal: (key: SlotKey) => Promise<void>;
|
|
14
|
+
discardStaleJournal: (slot: AgentConnectionSlot) => Promise<void>;
|
|
15
|
+
};
|
|
16
|
+
export declare class AgentConnectionStore {
|
|
17
|
+
readonly filePath: string;
|
|
18
|
+
constructor(filePath?: string);
|
|
19
|
+
private readRoot;
|
|
20
|
+
readSlot(key: SlotKey): Promise<AgentConnectionSlot | null>;
|
|
21
|
+
private saveUnlocked;
|
|
22
|
+
private journalPath;
|
|
23
|
+
private journalIsStale;
|
|
24
|
+
readLifecycleSlot(key: SlotKey): Promise<AgentConnectionSlot | null>;
|
|
25
|
+
withLock<T>(callback: (locked: LockedStore) => Promise<T>): Promise<T>;
|
|
26
|
+
saveSlot(slot: AgentConnectionSlot, precondition?: (previous: AgentConnectionSlot | null) => void): Promise<{
|
|
27
|
+
cleanupIncomplete: boolean;
|
|
28
|
+
}>;
|
|
29
|
+
private update;
|
|
30
|
+
updateTokens(key: SlotKey, tokens: AgentConnectionSlot['tokens']): Promise<void>;
|
|
31
|
+
setRefreshState(key: SlotKey, refreshState: AgentConnectionSlot['refreshState']): Promise<void>;
|
|
32
|
+
setRevokeState(key: SlotKey, revokeState: AgentConnectionSlot['revokeState']): Promise<void>;
|
|
33
|
+
removeSlot(key: SlotKey): Promise<void>;
|
|
34
|
+
removeSlotIfUnchanged(slot: AgentConnectionSlot): Promise<boolean>;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/agentConnections/store.ts"],"names":[],"mappings":"AAWA,OAAO,EAGH,KAAK,mBAAmB,EACxB,KAAK,OAAO,EACf,MAAM,UAAU,CAAC;AAElB,eAAO,MAAM,2BAA2B,QAAO,MACsB,CAAC;AA4CtE,MAAM,MAAM,cAAc,GAAG;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACtB,CAAC;AACF,MAAM,MAAM,WAAW,GAAG;IACtB,QAAQ,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAC;IAChE,QAAQ,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,WAAW,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAC9D,YAAY,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,YAAY,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,mBAAmB,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACrE,CAAC;AAEF,qBAAa,oBAAoB;aAET,QAAQ,EAAE,MAAM;IADpC,YACoB,QAAQ,GAAE,MAAsC,EAChE;YAEU,QAAQ;IAchB,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAIhE;YAEa,YAAY;IA+C1B,OAAO,CAAC,WAAW;YAcL,cAAc;IAkBtB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAQzE;IAEK,QAAQ,CAAC,CAAC,EACZ,QAAQ,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,GAC9C,OAAO,CAAC,CAAC,CAAC,CAqDZ;IAEK,QAAQ,CACV,IAAI,EAAE,mBAAmB,EACzB,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,mBAAmB,GAAG,IAAI,KAAK,IAAI,GAC9D,OAAO,CAAC;QAAE,iBAAiB,EAAE,OAAO,CAAA;KAAE,CAAC,CAmBzC;YAEa,MAAM;IAcd,YAAY,CACd,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,mBAAmB,CAAC,QAAQ,CAAC,GACtC,OAAO,CAAC,IAAI,CAAC,CAKf;IACK,eAAe,CACjB,GAAG,EAAE,OAAO,EACZ,YAAY,EAAE,mBAAmB,CAAC,cAAc,CAAC,GAClD,OAAO,CAAC,IAAI,CAAC,CAEf;IACK,cAAc,CAChB,GAAG,EAAE,OAAO,EACZ,WAAW,EAAE,mBAAmB,CAAC,aAAa,CAAC,GAChD,OAAO,CAAC,IAAI,CAAC,CAEf;IACK,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAS5C;IACK,qBAAqB,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC,CAiBvE;CACJ"}
|