Merge branch 'main' of https://github.com/ToolJet/ToolJet into feat/new-table-mod

This commit is contained in:
Kavin Venkatachalam 2025-04-02 14:43:51 +05:30
commit a31a25510d
7 changed files with 52 additions and 9 deletions

View file

@ -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> {}
}

View file

@ -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;
}

View file

@ -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': ['*'],
},

View file

@ -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;
}
);

View file

@ -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);

View file

@ -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);
}

View file

@ -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,
});
});
}
}