@lightdash/cli 1.16.0 → 1.17.1
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 +1 -1
- package/dist/handlers/connectSnowflake.d.ts.map +1 -1
- package/dist/handlers/connectSnowflake.js +2 -1
- package/dist/handlers/connectSnowflake.test.js +3 -2
- package/dist/vendor/template/package.json +1 -1
- package/package.json +3 -3
- package/dist/handlers/organizationContent/fileNames.d.ts +0 -5
- package/dist/handlers/organizationContent/fileNames.d.ts.map +0 -1
- package/dist/handlers/organizationContent/fileNames.js +0 -12
- package/dist/handlers/organizationContent/fileNames.test.d.ts +0 -2
- package/dist/handlers/organizationContent/fileNames.test.d.ts.map +0 -1
- package/dist/handlers/organizationContent/fileNames.test.js +0 -36
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connectSnowflake.d.ts","sourceRoot":"","sources":["../../src/handlers/connectSnowflake.ts"],"names":[],"mappings":"AAAA,OAAO,EAKH,KAAK,0BAA0B,EAIlC,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAEH,wBAAwB,EAG3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAwB,MAAM,YAAY,CAAC;AAIlD,MAAM,MAAM,uBAAuB,GAAG;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,KAAK,yBAAyB,GAAG,IAAI,CACjC,wBAAwB,EACtB,2BAA2B,GAC3B,+BAA+B,GAC/B,qBAAqB,GACrB,uBAAuB,GACvB,0BAA0B,GAC1B,+BAA+B,GAC/B,kBAAkB,GAClB,oBAAoB,CACzB,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,KAAK,4BAA4B,GAAG;IAChC,sBAAsB,EAAE,CACpB,WAAW,EAAE,0BAA0B,KACtC,yBAAyB,CAAC;IAC/B,eAAe,EAAE,MAAM,gBAAgB,CAAC;IACxC,KAAK,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,GAAG,EAAE,MAAM,IAAI,CAAC;IAChB,KAAK,EAAE,OAAO,KAAK,CAAC;IACpB,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC,CAAC;
|
|
1
|
+
{"version":3,"file":"connectSnowflake.d.ts","sourceRoot":"","sources":["../../src/handlers/connectSnowflake.ts"],"names":[],"mappings":"AAAA,OAAO,EAKH,KAAK,0BAA0B,EAIlC,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAEH,wBAAwB,EAG3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAwB,MAAM,YAAY,CAAC;AAIlD,MAAM,MAAM,uBAAuB,GAAG;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,KAAK,yBAAyB,GAAG,IAAI,CACjC,wBAAwB,EACtB,2BAA2B,GAC3B,+BAA+B,GAC/B,qBAAqB,GACrB,uBAAuB,GACvB,0BAA0B,GAC1B,+BAA+B,GAC/B,kBAAkB,GAClB,oBAAoB,CACzB,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,KAAK,4BAA4B,GAAG;IAChC,sBAAsB,EAAE,CACpB,WAAW,EAAE,0BAA0B,KACtC,yBAAyB,CAAC;IAC/B,eAAe,EAAE,MAAM,gBAAgB,CAAC;IACxC,KAAK,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,GAAG,EAAE,MAAM,IAAI,CAAC;IAChB,KAAK,EAAE,OAAO,KAAK,CAAC;IACpB,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC,CAAC;AA6XF,eAAO,MAAM,uBAAuB,GAChC,SAAS,uBAAuB,EAChC,eAAc,4BAAkD,KACjE,OAAO,CAAC,IAAI,CAwEd,CAAC"}
|
|
@@ -8,7 +8,7 @@ const node_fetch_1 = tslib_1.__importDefault(require("node-fetch"));
|
|
|
8
8
|
const node_crypto_1 = require("node:crypto");
|
|
9
9
|
const analytics_1 = require("../analytics/analytics");
|
|
10
10
|
const PAT_EXPIRY_DAYS = 365;
|
|
11
|
-
const PAT_NETWORK_POLICY_BYPASS_MINUTES =
|
|
11
|
+
const PAT_NETWORK_POLICY_BYPASS_MINUTES = 60;
|
|
12
12
|
const KEY_VERIFICATION_ATTEMPTS = 3;
|
|
13
13
|
const KEY_VERIFICATION_RETRY_DELAY_MS = 5_000;
|
|
14
14
|
const generateSnowflakeKeyPair = () => {
|
|
@@ -235,6 +235,7 @@ const createDurableCredential = async (authorizationCodeCredentials, warehouseCl
|
|
|
235
235
|
const { tokenSecret } = await warehouseClient.createProgrammaticAccessToken(`LIGHTDASH_ONBOARDING_${Date.now()}`, PAT_EXPIRY_DAYS, PAT_NETWORK_POLICY_BYPASS_MINUTES);
|
|
236
236
|
const expiresAt = new Date(dependencies.now().getTime() +
|
|
237
237
|
PAT_EXPIRY_DAYS * 24 * 60 * 60 * 1000);
|
|
238
|
+
dependencies.write(`The token bypasses your Snowflake network policy for the next ${PAT_NETWORK_POLICY_BYPASS_MINUTES} minutes so this connection can be verified. Allowlist Lightdash's IP addresses in your network policy to keep it working afterwards.`);
|
|
238
239
|
return {
|
|
239
240
|
credentials: {
|
|
240
241
|
type: common_1.WarehouseTypes.SNOWFLAKE,
|
|
@@ -291,7 +291,7 @@ describe('connectSnowflakeHandler', () => {
|
|
|
291
291
|
});
|
|
292
292
|
await expect((0, connectSnowflake_1.connectSnowflakeHandler)(options, getDependencies())).resolves.toBeUndefined();
|
|
293
293
|
expect(setUserPublicKey).not.toHaveBeenCalled();
|
|
294
|
-
expect(createProgrammaticAccessToken).toHaveBeenCalledWith(expect.stringMatching(/^LIGHTDASH_ONBOARDING_\d+$/), 365,
|
|
294
|
+
expect(createProgrammaticAccessToken).toHaveBeenCalledWith(expect.stringMatching(/^LIGHTDASH_ONBOARDING_\d+$/), 365, 60);
|
|
295
295
|
const request = {
|
|
296
296
|
code: options.code,
|
|
297
297
|
credentials: {
|
|
@@ -321,8 +321,9 @@ describe('connectSnowflakeHandler', () => {
|
|
|
321
321
|
it('falls back to a PAT when key registration lacks privileges', async () => {
|
|
322
322
|
vi.mocked(setUserPublicKey).mockRejectedValue(new Error('Insufficient privileges to operate on user'));
|
|
323
323
|
await expect((0, connectSnowflake_1.connectSnowflakeHandler)(options, getDependencies())).resolves.toBeUndefined();
|
|
324
|
-
expect(createProgrammaticAccessToken).toHaveBeenCalledWith(expect.stringMatching(/^LIGHTDASH_ONBOARDING_\d+$/), 365,
|
|
324
|
+
expect(createProgrammaticAccessToken).toHaveBeenCalledWith(expect.stringMatching(/^LIGHTDASH_ONBOARDING_\d+$/), 365, 60);
|
|
325
325
|
expect(write).toHaveBeenCalledWith('Secured with a programmatic access token (expires 2027-07-14)');
|
|
326
|
+
expect(write).toHaveBeenCalledWith(expect.stringContaining('bypasses your Snowflake network policy for the next 60 minutes'));
|
|
326
327
|
});
|
|
327
328
|
it('prints administrator remediation when both durable paths fail', async () => {
|
|
328
329
|
vi.mocked(setUserPublicKey).mockRejectedValue(new Error('Insufficient privileges'));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lightdash/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.17.1",
|
|
4
4
|
"description": "Lightdash CLI tool",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
"unique-names-generator": "4.7.1",
|
|
42
42
|
"uuid": "11.1.1",
|
|
43
43
|
"yaml": "2.8.3",
|
|
44
|
-
"@lightdash/common": "1.
|
|
45
|
-
"@lightdash/warehouses": "1.
|
|
44
|
+
"@lightdash/common": "1.17.1",
|
|
45
|
+
"@lightdash/warehouses": "1.17.1"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/inquirer": "8.2.4",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fileNames.d.ts","sourceRoot":"","sources":["../../../src/handlers/organizationContent/fileNames.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,+BAA+B,GAAI,6BAG7C;IACC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;CAC1B,KAAG,MAAM,EAOJ,CAAC"}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getOrganizationContentFileNames = void 0;
|
|
4
|
-
const fileNames_1 = require("../contentAsCode/fileNames");
|
|
5
|
-
const getOrganizationContentFileNames = ({ values, fallbackPrefix, }) => (0, fileNames_1.allocateContentFileNames)({
|
|
6
|
-
items: values.map((value) => ({
|
|
7
|
-
identity: value,
|
|
8
|
-
displayName: value,
|
|
9
|
-
})),
|
|
10
|
-
fallbackPrefix,
|
|
11
|
-
});
|
|
12
|
-
exports.getOrganizationContentFileNames = getOrganizationContentFileNames;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fileNames.test.d.ts","sourceRoot":"","sources":["../../../src/handlers/organizationContent/fileNames.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const crypto_1 = require("crypto");
|
|
4
|
-
const fileNames_1 = require("./fileNames");
|
|
5
|
-
describe('organization content filenames', () => {
|
|
6
|
-
it('uses generateSlug with normalized accents', () => {
|
|
7
|
-
expect((0, fileNames_1.getOrganizationContentFileNames)({
|
|
8
|
-
values: ['Málaga Finance'],
|
|
9
|
-
fallbackPrefix: 'group',
|
|
10
|
-
})).toStrictEqual(['malaga-finance.yml']);
|
|
11
|
-
});
|
|
12
|
-
it('uses a deterministic hash when no slug can be generated', () => {
|
|
13
|
-
const value = '🎉';
|
|
14
|
-
const hash = (0, crypto_1.createHash)('sha256')
|
|
15
|
-
.update(value)
|
|
16
|
-
.digest('hex')
|
|
17
|
-
.slice(0, 8);
|
|
18
|
-
expect((0, fileNames_1.getOrganizationContentFileNames)({
|
|
19
|
-
values: [value],
|
|
20
|
-
fallbackPrefix: 'group',
|
|
21
|
-
})).toStrictEqual([`group-${hash}.yml`]);
|
|
22
|
-
});
|
|
23
|
-
it('adds stable hashes when different values generate the same slug', () => {
|
|
24
|
-
const values = ['Finance?', 'Finance!'];
|
|
25
|
-
expect((0, fileNames_1.getOrganizationContentFileNames)({
|
|
26
|
-
values,
|
|
27
|
-
fallbackPrefix: 'group',
|
|
28
|
-
})).toStrictEqual(values.map((value) => {
|
|
29
|
-
const hash = (0, crypto_1.createHash)('sha256')
|
|
30
|
-
.update(value)
|
|
31
|
-
.digest('hex')
|
|
32
|
-
.slice(0, 8);
|
|
33
|
-
return `finance-${hash}.yml`;
|
|
34
|
-
}));
|
|
35
|
-
});
|
|
36
|
-
});
|