@lightdash/common 0.1342.1 → 0.1344.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.
@@ -205,6 +205,10 @@ exports.organizationMemberAbilities = {
205
205
  organizationUuid: member.organizationUuid,
206
206
  type: projects_1.ProjectType.PREVIEW,
207
207
  });
208
+ can('delete', 'Project', {
209
+ organizationUuid: member.organizationUuid,
210
+ type: projects_1.ProjectType.PREVIEW,
211
+ });
208
212
  },
209
213
  admin(member, { can }) {
210
214
  exports.organizationMemberAbilities.developer(member, { can });
@@ -221,6 +225,9 @@ exports.organizationMemberAbilities = {
221
225
  organizationUuid: member.organizationUuid,
222
226
  type: { $in: [projects_1.ProjectType.DEFAULT, projects_1.ProjectType.PREVIEW] },
223
227
  });
228
+ can('delete', 'Project', {
229
+ organizationUuid: member.organizationUuid,
230
+ });
224
231
  can('manage', 'Project', {
225
232
  organizationUuid: member.organizationUuid,
226
233
  });
@@ -911,33 +911,45 @@ describe('Organization member permissions', () => {
911
911
  membership: organizationMemberAbility_mock_1.ORGANIZATION_ADMIN,
912
912
  canCreateProject: true,
913
913
  canCreatePreview: true,
914
+ canDeleteProject: true,
915
+ canDeletePreview: true,
914
916
  },
915
917
  {
916
918
  membership: organizationMemberAbility_mock_1.ORGANIZATION_DEVELOPER,
917
919
  canCreateProject: false,
918
920
  canCreatePreview: true,
921
+ canDeleteProject: false,
922
+ canDeletePreview: true,
919
923
  },
920
924
  {
921
925
  membership: organizationMemberAbility_mock_1.ORGANIZATION_MEMBER,
922
926
  canCreateProject: false,
923
927
  canCreatePreview: false,
928
+ canDeleteProject: false,
929
+ canDeletePreview: false,
924
930
  },
925
931
  {
926
932
  membership: organizationMemberAbility_mock_1.ORGANIZATION_VIEWER,
927
933
  canCreateProject: false,
928
934
  canCreatePreview: false,
935
+ canDeleteProject: false,
936
+ canDeletePreview: false,
929
937
  },
930
938
  {
931
939
  membership: organizationMemberAbility_mock_1.ORGANIZATION_INTERACTIVE_VIEWER,
932
940
  canCreateProject: false,
933
941
  canCreatePreview: false,
942
+ canDeleteProject: false,
943
+ canDeletePreview: false,
934
944
  },
935
945
  {
936
946
  membership: organizationMemberAbility_mock_1.ORGANIZATION_EDITOR,
937
947
  canCreateProject: false,
938
948
  canCreatePreview: false,
949
+ canDeleteProject: false,
950
+ canDeletePreview: false,
939
951
  },
940
- ].forEach(({ membership, canCreateProject, canCreatePreview }) => {
952
+ ].forEach(({ membership, canCreateProject, canCreatePreview, canDeleteProject, canDeletePreview, }) => {
941
953
  const ability = defineAbilityForOrganizationMember(membership);
942
954
  describe(`user is '${membership.role}' role`, () => {
943
955
  it('checks if users can create project in organization they belong to', () => {
@@ -964,6 +976,28 @@ describe('Organization member permissions', () => {
964
976
  type: projects_1.ProjectType.PREVIEW,
965
977
  }))).toEqual(false);
966
978
  });
979
+ it('checks if users can delete a project in organization they belong to', () => {
980
+ expect(ability.can('delete', (0, ability_1.subject)('Project', {
981
+ organizationUuid: membership.organizationUuid,
982
+ }))).toEqual(canDeleteProject);
983
+ });
984
+ it('checks that users cannot delete a project in another organization', () => {
985
+ expect(ability.can('delete', (0, ability_1.subject)('Project', {
986
+ organizationUuid: '789',
987
+ }))).toEqual(false);
988
+ });
989
+ it('checks if users can delete a PREVIEW project in organization they belong to', () => {
990
+ expect(ability.can('delete', (0, ability_1.subject)('Project', {
991
+ organizationUuid: membership.organizationUuid,
992
+ type: projects_1.ProjectType.PREVIEW,
993
+ }))).toEqual(canDeletePreview);
994
+ });
995
+ it('checks that users cannot delete a PREVIEW project in another organization', () => {
996
+ expect(ability.can('delete', (0, ability_1.subject)('Project', {
997
+ organizationUuid: '789',
998
+ type: projects_1.ProjectType.PREVIEW,
999
+ }))).toEqual(false);
1000
+ });
967
1001
  });
968
1002
  });
969
1003
  });
@@ -187,6 +187,10 @@ exports.projectMemberAbilities = {
187
187
  can('manage', 'CompileProject', {
188
188
  projectUuid: member.projectUuid,
189
189
  });
190
+ can('delete', 'Project', {
191
+ type: projects_1.ProjectType.PREVIEW,
192
+ createdByUserUuid: member.userUuid,
193
+ });
190
194
  can('create', 'Project', {
191
195
  upstreamProjectUuid: member.projectUuid,
192
196
  type: projects_1.ProjectType.PREVIEW,
@@ -194,6 +198,9 @@ exports.projectMemberAbilities = {
194
198
  },
195
199
  admin(member, { can }) {
196
200
  exports.projectMemberAbilities.developer(member, { can });
201
+ can('delete', 'Project', {
202
+ projectUuid: member.projectUuid,
203
+ });
197
204
  can('manage', 'Project', {
198
205
  projectUuid: member.projectUuid,
199
206
  });
@@ -737,24 +737,29 @@ describe('Project member permissions', () => {
737
737
  {
738
738
  membership: projectMemberAbility_mock_1.PROJECT_ADMIN,
739
739
  canCreatePreview: true,
740
+ canDeleteTheirOwnPreview: true,
740
741
  },
741
742
  {
742
743
  membership: projectMemberAbility_mock_1.PROJECT_DEVELOPER,
743
744
  canCreatePreview: true,
745
+ canDeleteTheirOwnPreview: true,
744
746
  },
745
747
  {
746
748
  membership: projectMemberAbility_mock_1.PROJECT_EDITOR,
747
749
  canCreatePreview: false,
750
+ canDeleteTheirOwnPreview: false,
748
751
  },
749
752
  {
750
753
  membership: projectMemberAbility_mock_1.PROJECT_INTERACTIVE_VIEWER,
751
754
  canCreatePreview: false,
755
+ canDeleteTheirOwnPreview: false,
752
756
  },
753
757
  {
754
758
  membership: projectMemberAbility_mock_1.PROJECT_VIEWER,
755
759
  canCreatePreview: false,
760
+ canDeleteTheirOwnPreview: false,
756
761
  },
757
- ].forEach(({ membership, canCreatePreview }) => {
762
+ ].forEach(({ membership, canCreatePreview, canDeleteTheirOwnPreview }) => {
758
763
  describe('test project preview permissions', () => {
759
764
  const ability = defineAbilityForProjectMember(membership);
760
765
  it('checks if user can create PREVIEW projects', () => {
@@ -769,6 +774,18 @@ describe('Project member permissions', () => {
769
774
  type: projects_1.ProjectType.DEFAULT,
770
775
  }))).toEqual(false);
771
776
  });
777
+ it('checks if user can delete their own PREVIEW projects', () => {
778
+ expect(ability.can('delete', (0, ability_1.subject)('Project', {
779
+ createdByUserUuid: membership.userUuid,
780
+ type: projects_1.ProjectType.PREVIEW,
781
+ }))).toEqual(canDeleteTheirOwnPreview);
782
+ });
783
+ it('checks that users cannot delete other users PREVIEW projects', () => {
784
+ expect(ability.can('delete', (0, ability_1.subject)('Project', {
785
+ createdByUserUuid: '1234',
786
+ type: projects_1.ProjectType.PREVIEW,
787
+ }))).toEqual(false);
788
+ });
772
789
  });
773
790
  });
774
791
  });
package/dist/index.d.ts CHANGED
@@ -11,6 +11,7 @@ import { type ApiCalculateTotalResponse, type ChartHistory, type ChartVersion, t
11
11
  import { type SearchResults } from './types/search';
12
12
  import { type ShareUrl } from './types/share';
13
13
  import { type SlackSettings } from './types/slackSettings';
14
+ import { type ApiCreateTagResponse } from './types/tags';
14
15
  import { type ApiCreateComment, type ApiDeleteComment, type ApiGetComments } from './types/api/comments';
15
16
  import { type Email } from './types/api/email';
16
17
  import { type ApiSuccessEmpty } from './types/api/success';
@@ -374,7 +375,7 @@ export type ApiAiGetDashboardSummaryResponse = {
374
375
  status: 'ok';
375
376
  results: DashboardSummary;
376
377
  };
377
- type ApiResults = ApiQueryResults | ApiSqlQueryResults | ApiCompiledQueryResults | ApiExploresResults | ApiExploreResults | ApiStatusResults | ApiRefreshResults | ApiHealthResults | Organization | LightdashUser | LoginOptions | SavedChart | SavedChart[] | Space[] | InviteLink | OrganizationProject[] | Project | WarehouseCredentials | OrganizationMemberProfile[] | ProjectCatalog | TablesConfiguration | Dashboard | DashboardBasicDetails[] | OnboardingStatus | Dashboard[] | DeleteOpenIdentity | ApiFlashResults | Record<OpenIdIdentitySummary['issuerType'], OpenIdIdentitySummary[]> | FilterableField[] | DashboardAvailableFilters | ProjectSavedChartStatus | null | Array<unknown> | ApiJobStartedResults | ApiCreateUserTokenResults | CreatePersonalAccessToken | PersonalAccessToken | ProjectMemberProfile[] | ProjectGroupAccess | SearchResults | Space | ShareUrl | SlackSettings | ApiSlackChannelsResponse['results'] | UserActivity | SchedulerAndTargets | SchedulerAndTargets[] | FieldValueSearchResult | ApiDownloadCsv | AllowedEmailDomains | UpdateAllowedEmailDomains | UserAllowedOrganization[] | EmailStatusExpiring | ApiScheduledDownloadCsv | PinnedItems | ViewStatistics | SchedulerWithLogs | ValidationResponse[] | ChartHistory | ChartVersion | Array<GitRepo> | PullRequestCreated | GitIntegrationConfiguration | UserWarehouseCredentials | ApiJobStatusResponse['results'] | ApiJobScheduledResponse['results'] | ApiSshKeyPairResponse['results'] | MostPopularAndRecentlyUpdated | ApiCalculateTotalResponse['results'] | Record<string, DbtExposure> | ApiCreateComment['results'] | ApiGetComments['results'] | ApiDeleteComment | ApiSuccessEmpty | ApiCreateProjectResults | ApiAiDashboardSummaryResponse['results'] | ApiAiGetDashboardSummaryResponse['results'] | ApiCatalogMetadataResults | ApiCatalogAnalyticsResults | ApiPromotionChangesResponse['results'] | ApiWarehouseTableFields['results'] | ApiTogglePinnedItem['results'] | ApiOrganizationMemberProfiles['results'] | ApiSqlChart['results'] | ApiCreateSqlChart['results'] | ApiUpdateSqlChart['results'] | ApiContentResponse['results'] | ApiChartContentResponse['results'] | ApiSqlRunnerJobStatusResponse['results'] | ApiSemanticLayerClientInfo['results'] | ApiSemanticViewerChartCreate['results'] | ApiSemanticViewerChartGet['results'] | ApiSemanticViewerChartUpdate['results'] | ApiCreateVirtualView['results'] | ApiGithubDbtWritePreview['results'] | ApiMetricsCatalog['results'] | ApiGroupListResponse['results'];
378
+ type ApiResults = ApiQueryResults | ApiSqlQueryResults | ApiCompiledQueryResults | ApiExploresResults | ApiExploreResults | ApiStatusResults | ApiRefreshResults | ApiHealthResults | Organization | LightdashUser | LoginOptions | SavedChart | SavedChart[] | Space[] | InviteLink | OrganizationProject[] | Project | WarehouseCredentials | OrganizationMemberProfile[] | ProjectCatalog | TablesConfiguration | Dashboard | DashboardBasicDetails[] | OnboardingStatus | Dashboard[] | DeleteOpenIdentity | ApiFlashResults | Record<OpenIdIdentitySummary['issuerType'], OpenIdIdentitySummary[]> | FilterableField[] | DashboardAvailableFilters | ProjectSavedChartStatus | null | Array<unknown> | ApiJobStartedResults | ApiCreateUserTokenResults | CreatePersonalAccessToken | PersonalAccessToken | ProjectMemberProfile[] | ProjectGroupAccess | SearchResults | Space | ShareUrl | SlackSettings | ApiSlackChannelsResponse['results'] | UserActivity | SchedulerAndTargets | SchedulerAndTargets[] | FieldValueSearchResult | ApiDownloadCsv | AllowedEmailDomains | UpdateAllowedEmailDomains | UserAllowedOrganization[] | EmailStatusExpiring | ApiScheduledDownloadCsv | PinnedItems | ViewStatistics | SchedulerWithLogs | ValidationResponse[] | ChartHistory | ChartVersion | Array<GitRepo> | PullRequestCreated | GitIntegrationConfiguration | UserWarehouseCredentials | ApiJobStatusResponse['results'] | ApiJobScheduledResponse['results'] | ApiSshKeyPairResponse['results'] | MostPopularAndRecentlyUpdated | ApiCalculateTotalResponse['results'] | Record<string, DbtExposure> | ApiCreateComment['results'] | ApiGetComments['results'] | ApiDeleteComment | ApiSuccessEmpty | ApiCreateProjectResults | ApiAiDashboardSummaryResponse['results'] | ApiAiGetDashboardSummaryResponse['results'] | ApiCatalogMetadataResults | ApiCatalogAnalyticsResults | ApiPromotionChangesResponse['results'] | ApiWarehouseTableFields['results'] | ApiTogglePinnedItem['results'] | ApiOrganizationMemberProfiles['results'] | ApiSqlChart['results'] | ApiCreateSqlChart['results'] | ApiUpdateSqlChart['results'] | ApiContentResponse['results'] | ApiChartContentResponse['results'] | ApiSqlRunnerJobStatusResponse['results'] | ApiSemanticLayerClientInfo['results'] | ApiSemanticViewerChartCreate['results'] | ApiSemanticViewerChartGet['results'] | ApiSemanticViewerChartUpdate['results'] | ApiCreateVirtualView['results'] | ApiGithubDbtWritePreview['results'] | ApiMetricsCatalog['results'] | ApiGroupListResponse['results'] | ApiCreateTagResponse['results'];
378
379
  export type ApiResponse<T extends ApiResults = ApiResults> = {
379
380
  status: 'ok';
380
381
  results: T;
@@ -502,10 +503,10 @@ export declare enum DBFieldTypes {
502
503
  }
503
504
  export declare const sensitiveDbtCredentialsFieldNames: readonly ["personal_access_token", "api_key"];
504
505
  export declare const DbtProjectTypeLabels: Record<DbtProjectType, string>;
505
- export type CreateProject = Omit<Project, 'projectUuid' | 'organizationUuid' | 'schedulerTimezone'> & {
506
+ export type CreateProject = Omit<Project, 'projectUuid' | 'organizationUuid' | 'schedulerTimezone' | 'createdByUserUuid'> & {
506
507
  warehouseConnection: CreateWarehouseCredentials;
507
508
  };
508
- export type UpdateProject = Omit<Project, 'projectUuid' | 'organizationUuid' | 'type' | 'schedulerTimezone'> & {
509
+ export type UpdateProject = Omit<Project, 'projectUuid' | 'organizationUuid' | 'type' | 'schedulerTimezone' | 'createdByUserUuid'> & {
509
510
  warehouseConnection: CreateWarehouseCredentials;
510
511
  };
511
512
  export declare const getResultValueArray: (rows: ResultRow[], preferRaw?: boolean, calculateMinAndMax?: boolean) => {
@@ -44,6 +44,7 @@ export type OrganizationProject = {
44
44
  projectUuid: string;
45
45
  name: string;
46
46
  type: ProjectType;
47
+ createdByUserUuid: string | null;
47
48
  warehouseType: WarehouseTypes;
48
49
  requireUserCredentials: boolean;
49
50
  };
@@ -231,6 +231,7 @@ export type Project = {
231
231
  dbtVersion: SupportedDbtVersions;
232
232
  semanticLayerConnection?: SemanticLayerConnection;
233
233
  schedulerTimezone: string;
234
+ createdByUserUuid: string | null;
234
235
  };
235
236
  export type ProjectSummary = Pick<Project, 'name' | 'projectUuid' | 'organizationUuid' | 'type' | 'upstreamProjectUuid'>;
236
237
  export type ApiProjectResponse = {
@@ -11,3 +11,9 @@ export type ApiGetTagsResponse = {
11
11
  status: 'ok';
12
12
  results: Tag[];
13
13
  };
14
+ export type ApiCreateTagResponse = {
15
+ status: 'ok';
16
+ results: {
17
+ tagUuid: string;
18
+ };
19
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightdash/common",
3
- "version": "0.1342.1",
3
+ "version": "0.1344.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [