From a0eb1956e2c05be0ba6ff041569f99dc5fcc96bf Mon Sep 17 00:00:00 2001 From: devanshu052000 Date: Mon, 26 May 2025 12:00:28 +0530 Subject: [PATCH] Implemented import-export logic --- server/src/dto/import-resources.dto.ts | 2 +- server/src/helpers/error_type.constant.ts | 2 +- .../services/app-import-export.service.ts | 76 ++++++++++++++++++- .../import-export-resources/service.ts | 8 +- 4 files changed, 81 insertions(+), 7 deletions(-) diff --git a/server/src/dto/import-resources.dto.ts b/server/src/dto/import-resources.dto.ts index 89b3ee182c..3ad6d2cee0 100644 --- a/server/src/dto/import-resources.dto.ts +++ b/server/src/dto/import-resources.dto.ts @@ -31,7 +31,7 @@ export class ImportResourcesDto { @IsOptional() @IsBoolean() - skip_page_permissions_group_check?: boolean; + skip_permissions_group_check?: boolean; } export class ImportAppDto { diff --git a/server/src/helpers/error_type.constant.ts b/server/src/helpers/error_type.constant.ts index cb483e8896..e34ce5b69d 100644 --- a/server/src/helpers/error_type.constant.ts +++ b/server/src/helpers/error_type.constant.ts @@ -1,7 +1,7 @@ export const APP_ERROR_TYPE = { IMPORT_EXPORT_SERVICE: { UNSUPPORTED_VERSION_ERROR: 'Apps built on later versions of ToolJet cannot be imported', - PAGE_PERMISSION_GROUP_ERROR: 'Following groups are missing from the workspace', + PERMISSION_GROUP_ERROR: 'Following groups are missing from the workspace', PERMISSION_CHECK: 'permission-check', }, }; diff --git a/server/src/modules/apps/services/app-import-export.service.ts b/server/src/modules/apps/services/app-import-export.service.ts index 5d6da2ea7d..6522690675 100644 --- a/server/src/modules/apps/services/app-import-export.service.ts +++ b/server/src/modules/apps/services/app-import-export.service.ts @@ -39,6 +39,8 @@ import { PAGE_PERMISSION_TYPE } from '@modules/app-permissions/constants'; import { PagePermission } from '@entities/page_permissions.entity'; import { PageUser } from '@entities/page_users.entity'; import { UsersUtilService } from '@modules/users/util.service'; +import { QueryPermission } from '@entities/query_permissions.entity'; +import { QueryUser } from '@entities/query_users.entity'; interface AppResourceMappings { defaultDataSourceIdMapping: Record; dataQueryMapping: Record; @@ -164,6 +166,9 @@ export class AppImportExportService { if (dataSources?.length) { dataQueries = await manager .createQueryBuilder(DataQuery, 'data_queries') + .leftJoinAndSelect('data_queries.permissions', 'permission') + .leftJoinAndSelect('permission.users', 'queryUser') + .leftJoinAndSelect('queryUser.permissionGroup', 'permissionGroup') .where('data_queries.dataSourceId IN(:...dataSourceId)', { dataSourceId: dataSources?.map((v) => v.id), }) @@ -216,6 +221,21 @@ export class AppImportExportService { }; }); + const queriesWithPermissionGroups = dataQueries.map((query) => { + const groupPermission = query.permissions.find((perm) => perm.type === 'GROUP'); + + return { + ...query, + permissions: groupPermission + ? { + permissionGroup: groupPermission.users + .map((user) => user.permissionGroup?.name) + .filter((name): name is string => Boolean(name)), + } + : undefined, + }; + }); + const components = pages.length > 0 ? await manager @@ -239,7 +259,7 @@ export class AppImportExportService { appToExport['components'] = components; appToExport['pages'] = pagesWithPermissionGroups; appToExport['events'] = events; - appToExport['dataQueries'] = dataQueries; + appToExport['dataQueries'] = queriesWithPermissionGroups; appToExport['dataSources'] = dataSources; appToExport['appVersions'] = appVersions; appToExport['appEnvironments'] = appEnvironments; @@ -1116,7 +1136,15 @@ export class AppImportExportService { }); await manager.save(newQuery); + + if (importingQuery.permissions) { + newQuery.permissions = importingQuery.permissions; + } + appResourceMappings.dataQueryMapping[importingQuery.id] = newQuery.id; + + //create query permissions of query if flag enabled in dto + await this.createQueryPermissionsForGroups(newQuery, organizationId, manager); } return appResourceMappings; @@ -1358,7 +1386,7 @@ export class AppImportExportService { return pageSettings; } - async checkIfGroupPermissionsExist(pages, organizationId) { + async checkIfGroupPermissionsExist(pages, queries, organizationId) { const allGroupNames = new Set(); for (const page of pages) { @@ -1368,6 +1396,15 @@ export class AppImportExportService { } } + for (const query of queries) { + const groupNames = query.permissions?.permissionGroup || []; + for (const name of groupNames) { + if (!allGroupNames.has(name)) { + allGroupNames.add(name); + } + } + } + if (!allGroupNames.size) return; return await dbTransactionWrap(async (manager: EntityManager) => { @@ -1428,6 +1465,41 @@ export class AppImportExportService { await manager.save(pageUsers); } + async createQueryPermissionsForGroups(query, organizationId: string, manager: EntityManager) { + const groupNames = query.permissions?.permissionGroup || []; + if (!groupNames.length) return; + + const existingGroups = await manager + .createQueryBuilder(GroupPermissions, 'gp') + .where('gp.name IN (:...names)', { names: groupNames }) + .andWhere('gp.organizationId = :organizationId', { organizationId }) + .getMany(); + + const groupMap = new Map(existingGroups.map((g) => [g.name, g])); + + // Filter to only existing group names + const validGroupNames = groupNames.filter((name) => groupMap.has(name)); + + // If no valid group names exist, do not create permissions + if (!validGroupNames.length) return; + + const permission = manager.create(QueryPermission, { + queryId: query.id, + type: PAGE_PERMISSION_TYPE.GROUP, + }); + + const savedPermission = await manager.save(permission); + + const queryUsers = validGroupNames.map((name) => + manager.create(QueryUser, { + queryPermissionsId: savedPermission.id, + permissionGroupsId: groupMap.get(name).id, + }) + ); + + await manager.save(queryUsers); + } + async createAppVersionsForImportedApp( manager: EntityManager, user: User, diff --git a/server/src/modules/import-export-resources/service.ts b/server/src/modules/import-export-resources/service.ts index e47205258e..7b50ca6076 100644 --- a/server/src/modules/import-export-resources/service.ts +++ b/server/src/modules/import-export-resources/service.ts @@ -69,15 +69,17 @@ export class ImportExportResourcesService { let tableNameMapping = {}; const imports = { app: [], tooljet_database: [], tableNameMapping: {} }; const importingVersion = importResourcesDto.tooljet_version; - const skipPagePermissionsGroupCheck = importResourcesDto.skip_page_permissions_group_check; + const skipPermissionsGroupCheck = importResourcesDto.skip_permissions_group_check; - if (!isEmpty(importResourcesDto.app) && !skipPagePermissionsGroupCheck) { + if (!isEmpty(importResourcesDto.app) && !skipPermissionsGroupCheck) { for (const appImportDto of importResourcesDto.app) { let appParams = appImportDto.definition; if (appParams?.appV2) { appParams = { ...appParams.appV2 }; const pages = appParams?.pages; - pages?.length && (await this.appImportExportService.checkIfGroupPermissionsExist(pages, user.organizationId)); + const queries = appParams?.dataQueries; + (pages?.length || queries?.length) && + (await this.appImportExportService.checkIfGroupPermissionsExist(pages, queries, user.organizationId)); } } }