@lightdash/cli 0.1952.0 ā 0.1954.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.
@@ -56,6 +56,8 @@ const askPermissionToStoreWarehouseCredentials = async () => {
|
|
56
56
|
return savedAnswer;
|
57
57
|
};
|
58
58
|
const createProject = async (options) => {
|
59
|
+
// Check permissions before proceeding
|
60
|
+
await (0, apiClient_1.checkProjectCreationPermission)(options.type);
|
59
61
|
const dbtVersion = await (0, getDbtVersion_1.getDbtVersion)();
|
60
62
|
const absoluteProjectPath = path_1.default.resolve(options.projectDir);
|
61
63
|
const context = await (0, context_1.getDbtContext)({ projectDir: absoluteProjectPath });
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import { ApiResponse } from '@lightdash/common';
|
1
|
+
import { ApiResponse, ProjectType, type LightdashUserWithAbilityRules } from '@lightdash/common';
|
2
2
|
import { BodyInit } from 'node-fetch';
|
3
3
|
type LightdashApiProps = {
|
4
4
|
method: 'GET' | 'POST' | 'PATCH' | 'DELETE' | 'PUT';
|
@@ -6,5 +6,7 @@ type LightdashApiProps = {
|
|
6
6
|
body: BodyInit | undefined;
|
7
7
|
};
|
8
8
|
export declare const lightdashApi: <T extends ApiResponse["results"]>({ method, url, body, }: LightdashApiProps) => Promise<T>;
|
9
|
+
export declare const getUserContext: () => Promise<LightdashUserWithAbilityRules>;
|
10
|
+
export declare const checkProjectCreationPermission: (projectType: ProjectType) => Promise<void>;
|
9
11
|
export declare const checkLightdashVersion: () => Promise<void>;
|
10
12
|
export {};
|
@@ -1,7 +1,8 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.checkLightdashVersion = exports.lightdashApi = void 0;
|
3
|
+
exports.checkLightdashVersion = exports.checkProjectCreationPermission = exports.getUserContext = exports.lightdashApi = void 0;
|
4
4
|
const tslib_1 = require("tslib");
|
5
|
+
const ability_1 = require("@casl/ability");
|
5
6
|
const common_1 = require("@lightdash/common");
|
6
7
|
const node_fetch_1 = tslib_1.__importDefault(require("node-fetch"));
|
7
8
|
const url_1 = require("url");
|
@@ -45,6 +46,37 @@ const lightdashApi = async ({ method, url, body, }) => {
|
|
45
46
|
});
|
46
47
|
};
|
47
48
|
exports.lightdashApi = lightdashApi;
|
49
|
+
const getUserContext = async () => (0, exports.lightdashApi)({
|
50
|
+
method: 'GET',
|
51
|
+
url: `/api/v1/user`,
|
52
|
+
body: undefined,
|
53
|
+
});
|
54
|
+
exports.getUserContext = getUserContext;
|
55
|
+
const checkProjectCreationPermission = async (projectType) => {
|
56
|
+
try {
|
57
|
+
const user = await (0, exports.getUserContext)();
|
58
|
+
// Build CASL ability from user's ability rules (same as backend)
|
59
|
+
const ability = new ability_1.Ability(user.abilityRules);
|
60
|
+
// Check if user has permission to create project of the specified type
|
61
|
+
const canCreate = ability.can('create', (0, ability_1.subject)('Project', {
|
62
|
+
organizationUuid: user.organizationUuid || '',
|
63
|
+
type: projectType,
|
64
|
+
}));
|
65
|
+
if (!canCreate) {
|
66
|
+
const projectTypeText = projectType === common_1.ProjectType.PREVIEW ? 'preview ' : '';
|
67
|
+
throw new common_1.ForbiddenError(`You don't have permission to create ${projectTypeText}projects.`);
|
68
|
+
}
|
69
|
+
}
|
70
|
+
catch (err) {
|
71
|
+
if (err instanceof common_1.ForbiddenError ||
|
72
|
+
err instanceof common_1.AuthorizationError) {
|
73
|
+
throw err;
|
74
|
+
}
|
75
|
+
globalState_1.default.debug(`Failed to check permissions: ${err}`);
|
76
|
+
// If we can't check permissions, we'll let the API call fail with proper error
|
77
|
+
}
|
78
|
+
};
|
79
|
+
exports.checkProjectCreationPermission = checkProjectCreationPermission;
|
48
80
|
const checkLightdashVersion = async () => {
|
49
81
|
try {
|
50
82
|
const health = await (0, exports.lightdashApi)({
|
package/dist/index.js
CHANGED
@@ -363,8 +363,18 @@ ${styles.bold('Examples:')}
|
|
363
363
|
.option('--no-defer', 'dbt property. Do not resolve unselected nodes by deferring to the manifest within the --state directory.', undefined)
|
364
364
|
.action(diagnostics_1.diagnosticsHandler);
|
365
365
|
const errorHandler = (err) => {
|
366
|
-
|
367
|
-
|
366
|
+
// Use error message with fallback for safety
|
367
|
+
const errorMessage = (0, common_1.getErrorMessage)(err) || 'An unexpected error occurred';
|
368
|
+
console.error(styles.error(errorMessage));
|
369
|
+
if (err.name === 'ForbiddenError' || err instanceof common_1.ForbiddenError) {
|
370
|
+
// For permission errors, show clear message with fallback
|
371
|
+
const permissionMessage = err.message || "You don't have permission to perform this action";
|
372
|
+
if (permissionMessage !== errorMessage) {
|
373
|
+
console.error(styles.error(permissionMessage));
|
374
|
+
}
|
375
|
+
console.error(`\nš” Contact your Lightdash administrator to request project creation access or if you believe this is incorrect.\n`);
|
376
|
+
}
|
377
|
+
else if (err.name === 'AuthorizationError') {
|
368
378
|
console.error(`Looks like you did not authenticate or the personal access token expired.\n\nš See https://docs.lightdash.com/guides/cli/cli-authentication for help and examples`);
|
369
379
|
}
|
370
380
|
else if (!(err instanceof common_1.LightdashError)) {
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@lightdash/cli",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.1954.0",
|
4
4
|
"license": "MIT",
|
5
5
|
"bin": {
|
6
6
|
"lightdash": "dist/index.js"
|
@@ -11,6 +11,7 @@
|
|
11
11
|
],
|
12
12
|
"dependencies": {
|
13
13
|
"@actions/core": "^1.11.1",
|
14
|
+
"@casl/ability": "^5.4.3",
|
14
15
|
"@types/columnify": "^1.5.1",
|
15
16
|
"ajv": "^8.11.0",
|
16
17
|
"ajv-formats": "^2.1.1",
|
@@ -31,8 +32,8 @@
|
|
31
32
|
"parse-node-version": "^2.0.0",
|
32
33
|
"unique-names-generator": "^4.7.1",
|
33
34
|
"uuid": "^11.0.3",
|
34
|
-
"@lightdash/
|
35
|
-
"@lightdash/
|
35
|
+
"@lightdash/warehouses": "0.1954.0",
|
36
|
+
"@lightdash/common": "0.1954.0"
|
36
37
|
},
|
37
38
|
"description": "Lightdash CLI tool",
|
38
39
|
"devDependencies": {
|