mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-23 17:08:34 +00:00
Merge branch 'main' of https://github.com/ToolJet/ToolJet into feat/new-table-mod
This commit is contained in:
commit
a31a25510d
7 changed files with 52 additions and 9 deletions
|
|
@ -0,0 +1,21 @@
|
|||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
export class UpdateGlobalDataSources1743058812003 implements MigrationInterface {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
// Step 1: Set app_version_id to NULL for existing global data sources
|
||||
await queryRunner.query(`
|
||||
UPDATE data_sources
|
||||
SET app_version_id = NULL
|
||||
WHERE scope = 'global'
|
||||
`);
|
||||
|
||||
// Step 2: Add a check constraint to ensure app_version_id is NULL for global data sources
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE data_sources
|
||||
ADD CONSTRAINT chk_global_data_source_app_version_id
|
||||
CHECK (scope != 'global' OR app_version_id IS NULL)
|
||||
`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {}
|
||||
}
|
||||
|
|
@ -28,6 +28,7 @@ import { OnboardingDetails } from './onboarding_details.entity';
|
|||
import { OnboardingStatus } from '@modules/onboarding/constants';
|
||||
import { AiConversation } from './ai_conversation.entity';
|
||||
import { AiResponseVote } from './ai_response_vote.entity';
|
||||
import { USER_ROLE } from '@modules/group-permissions/constants';
|
||||
|
||||
@Entity({ name: 'users' })
|
||||
export class User extends BaseEntity {
|
||||
|
|
@ -189,4 +190,5 @@ export class User extends BaseEntity {
|
|||
isPasswordLogin: boolean;
|
||||
isSSOLogin: boolean;
|
||||
sessionId: string;
|
||||
roleGroup: USER_ROLE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,6 +106,8 @@ function setSecurityHeaders(app, configService) {
|
|||
'https://esm.sh',
|
||||
'www.googletagmanager.com',
|
||||
],
|
||||
'object-src': ["'self'", 'data:'],
|
||||
'media-src': ["'self'", 'data:'],
|
||||
'default-src': [
|
||||
'maps.googleapis.com',
|
||||
'storage.googleapis.com',
|
||||
|
|
@ -116,7 +118,7 @@ function setSecurityHeaders(app, configService) {
|
|||
'blob:',
|
||||
'www.googletagmanager.com',
|
||||
],
|
||||
'connect-src': ['ws://' + domain, "'self'", '*'],
|
||||
'connect-src': ['ws://' + domain, "'self'", '*', 'data:'],
|
||||
'frame-ancestors': ['*'],
|
||||
'frame-src': ['*'],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
|
||||
import { UserPermissions } from '@modules/ability/types';
|
||||
|
||||
export const UserPermissionsDecorator = createParamDecorator(
|
||||
(data: unknown, ctx: ExecutionContext): UserPermissions => {
|
||||
const request = ctx.switchToHttp().getRequest();
|
||||
return request.tj_user_permissions as UserPermissions;
|
||||
}
|
||||
);
|
||||
|
|
@ -1222,8 +1222,7 @@ export class AppImportExportService {
|
|||
name: dataSource.name,
|
||||
kind: dataSource.kind,
|
||||
type: DataSourceTypes.DEFAULT,
|
||||
appVersionId,
|
||||
scope: 'global',
|
||||
scope: 'global', // No appVersionId for global data sources
|
||||
pluginId: plugin.id,
|
||||
});
|
||||
await manager.save(newDataSource);
|
||||
|
|
@ -1238,8 +1237,7 @@ export class AppImportExportService {
|
|||
name: dataSource.name,
|
||||
kind: dataSource.kind,
|
||||
type: DataSourceTypes.DEFAULT,
|
||||
appVersionId,
|
||||
scope: 'global',
|
||||
scope: 'global', // No appVersionId for global data sources
|
||||
pluginId: null,
|
||||
});
|
||||
await manager.save(newDataSource);
|
||||
|
|
|
|||
|
|
@ -2,12 +2,15 @@ import { Controller, Param, Post, Put, UseGuards, Get, Query, Body } from '@nest
|
|||
import { decamelizeKeys } from 'humps';
|
||||
import { JwtAuthGuard } from '@modules/session/guards/jwt-auth.guard';
|
||||
import { FolderAppsService } from './service';
|
||||
import { User } from '@modules/app/decorators/user.decorator';
|
||||
import { User, UserEntity } from '@modules/app/decorators/user.decorator';
|
||||
import { FeatureAbilityGuard } from './ability/guard';
|
||||
import { InitModule } from '@modules/app/decorators/init-module';
|
||||
import { InitFeature } from '@modules/app/decorators/init-feature.decorator';
|
||||
import { MODULES } from '@modules/app/constants/modules';
|
||||
import { FEATURE_KEY } from './constants';
|
||||
import { UserPermissionsDecorator } from '@modules/app/decorators/user-permission.decorator';
|
||||
import { UserPermissions } from '@modules/ability/types';
|
||||
import { USER_ROLE } from '@modules/group-permissions/constants';
|
||||
@InitModule(MODULES.FOLDER_APPS)
|
||||
@UseGuards(JwtAuthGuard, FeatureAbilityGuard)
|
||||
@Controller('folder-apps')
|
||||
|
|
@ -16,7 +19,8 @@ export class FolderAppsController {
|
|||
|
||||
@InitFeature(FEATURE_KEY.GET_FOLDERS)
|
||||
@Get()
|
||||
async index(@User() user, @Query() query) {
|
||||
async index(@User() user: UserEntity, @Query() query, @UserPermissionsDecorator() userPermissions: UserPermissions) {
|
||||
user.roleGroup = userPermissions.isEndUser ? USER_ROLE.END_USER : undefined;
|
||||
return await this.folderAppsService.getFolders(user, query);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import { FolderAppsUtilService } from './util.service';
|
|||
import { IFolderAppsService } from './interfaces/IService';
|
||||
import { MODULES } from '@modules/app/constants/modules';
|
||||
import { AbilityService } from '@modules/ability/interfaces/IService';
|
||||
import { User } from '@entities/user.entity';
|
||||
import { USER_ROLE } from '@modules/group-permissions/constants';
|
||||
@Injectable()
|
||||
export class FolderAppsService implements IFolderAppsService {
|
||||
constructor(
|
||||
|
|
@ -47,7 +49,7 @@ export class FolderAppsService implements IFolderAppsService {
|
|||
return await manager.delete(FolderApp, { folderId, appId });
|
||||
});
|
||||
}
|
||||
async getFolders(user, query) {
|
||||
async getFolders(user: User, query) {
|
||||
return dbTransactionWrap(async (manager: EntityManager) => {
|
||||
const type = query.type;
|
||||
const searchKey = query.searchKey;
|
||||
|
|
@ -78,7 +80,12 @@ export class FolderAppsService implements IFolderAppsService {
|
|||
allFolderList[index].generateCount();
|
||||
}
|
||||
});
|
||||
return decamelizeKeys({ folders: allFolderList });
|
||||
return decamelizeKeys({
|
||||
folders:
|
||||
user.roleGroup === USER_ROLE.END_USER
|
||||
? allFolderList.filter((folder) => folder.folderApps.length > 0)
|
||||
: allFolderList,
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue