Enhance role-check system with stricter checks (#15392)
## Overview This PR strengthens our permission system by introducing more granular role-based access control across the platform. ## Changes ### New Permissions Added - **Applications** - Control who can install and manage applications - **Layouts** - Control who can customize page layouts and UI structure - **AI** - Control access to AI features and agents - **Upload File** - Separate permission for file uploads - **Download File** - Separate permission for file downloads (frontend visibility) ### Security Enhancements - Implemented whitelist-based validation for workspace field updates - Added explicit permission guards to core entity resolvers - Enhanced ESLint rule to enforce permission checks on all mutations - Created `CustomPermissionGuard` and `NoPermissionGuard` for better code documentation ### Affected Components - Core entity resolvers: webhooks, files, domains, applications, layouts, postgres credentials - Workspace update mutations now use whitelist validation - Settings UI updated with new permission controls ### Developer Experience - ESLint now catches missing permission guards during development - Explicit guard markers make permission requirements clear in code review - Comprehensive test coverage for new permission logic ## Testing - ✅ All TypeScript type checks pass - ✅ ESLint validation passes - ✅ New permission guards properly enforced - ✅ Frontend UI displays new permissions correctly ## Migration Notes Existing workspaces will need to assign the new permissions to roles as needed. By default, all new permissions are set to `false` for non-admin roles.
This commit is contained in:
+2
@@ -12,6 +12,7 @@ import { ThrottlerModule } from 'src/engine/core-modules/throttler/throttler.mod
|
||||
import { CronTriggerEntity } from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity';
|
||||
import { DatabaseEventTriggerEntity } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
|
||||
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
|
||||
import { RouteTriggerEntity } from 'src/engine/metadata-modules/route-trigger/route-trigger.entity';
|
||||
import { ServerlessFunctionLayerModule } from 'src/engine/metadata-modules/serverless-function-layer/serverless-function-layer.module';
|
||||
import { ServerlessFunctionTriggerJob } from 'src/engine/metadata-modules/serverless-function/jobs/serverless-function-trigger.job';
|
||||
@@ -36,6 +37,7 @@ import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspa
|
||||
ThrottlerModule,
|
||||
AuditModule,
|
||||
FeatureFlagModule,
|
||||
PermissionsModule,
|
||||
WorkspaceManyOrAllFlatEntityMapsCacheModule,
|
||||
WorkspaceMigrationV2Module,
|
||||
ServerlessFunctionLayerModule,
|
||||
|
||||
+8
-1
@@ -10,7 +10,10 @@ import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/re
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
|
||||
import { FeatureFlagGuard } from 'src/engine/guards/feature-flag.guard';
|
||||
import { SettingsPermissionsGuard } from 'src/engine/guards/settings-permissions.guard';
|
||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||
import { PermissionFlagType } from 'src/engine/metadata-modules/permissions/constants/permission-flag-type.constants';
|
||||
import { CreateServerlessFunctionInput } from 'src/engine/metadata-modules/serverless-function/dtos/create-serverless-function.input';
|
||||
import { ExecuteServerlessFunctionInput } from 'src/engine/metadata-modules/serverless-function/dtos/execute-serverless-function.input';
|
||||
import { GetServerlessFunctionSourceCodeInput } from 'src/engine/metadata-modules/serverless-function/dtos/get-serverless-function-source-code.input';
|
||||
import { PublishServerlessFunctionInput } from 'src/engine/metadata-modules/serverless-function/dtos/publish-serverless-function.input';
|
||||
@@ -21,7 +24,6 @@ import { UpdateServerlessFunctionInput } from 'src/engine/metadata-modules/serve
|
||||
import { ServerlessFunctionEntity } from 'src/engine/metadata-modules/serverless-function/serverless-function.entity';
|
||||
import { ServerlessFunctionService } from 'src/engine/metadata-modules/serverless-function/serverless-function.service';
|
||||
import { serverlessFunctionGraphQLApiExceptionHandler } from 'src/engine/metadata-modules/serverless-function/utils/serverless-function-graphql-api-exception-handler.utils';
|
||||
import { CreateServerlessFunctionInput } from 'src/engine/metadata-modules/serverless-function/dtos/create-serverless-function.input';
|
||||
|
||||
@UseGuards(WorkspaceAuthGuard, FeatureFlagGuard)
|
||||
@Resolver()
|
||||
@@ -92,6 +94,7 @@ export class ServerlessFunctionResolver {
|
||||
}
|
||||
|
||||
@Mutation(() => ServerlessFunctionDTO)
|
||||
@UseGuards(SettingsPermissionsGuard(PermissionFlagType.WORKFLOWS))
|
||||
async deleteOneServerlessFunction(
|
||||
@Args('input') input: ServerlessFunctionIdInput,
|
||||
@AuthWorkspace() { id: workspaceId }: WorkspaceEntity,
|
||||
@@ -107,6 +110,7 @@ export class ServerlessFunctionResolver {
|
||||
}
|
||||
|
||||
@Mutation(() => ServerlessFunctionDTO)
|
||||
@UseGuards(SettingsPermissionsGuard(PermissionFlagType.WORKFLOWS))
|
||||
async updateOneServerlessFunction(
|
||||
@Args('input')
|
||||
input: UpdateServerlessFunctionInput,
|
||||
@@ -123,6 +127,7 @@ export class ServerlessFunctionResolver {
|
||||
}
|
||||
|
||||
@Mutation(() => ServerlessFunctionDTO)
|
||||
@UseGuards(SettingsPermissionsGuard(PermissionFlagType.WORKFLOWS))
|
||||
async createOneServerlessFunction(
|
||||
@Args('input')
|
||||
input: CreateServerlessFunctionInput,
|
||||
@@ -139,6 +144,7 @@ export class ServerlessFunctionResolver {
|
||||
}
|
||||
|
||||
@Mutation(() => ServerlessFunctionExecutionResultDTO)
|
||||
@UseGuards(SettingsPermissionsGuard(PermissionFlagType.WORKFLOWS))
|
||||
async executeOneServerlessFunction(
|
||||
@Args('input') input: ExecuteServerlessFunctionInput,
|
||||
@AuthWorkspace() { id: workspaceId }: WorkspaceEntity,
|
||||
@@ -158,6 +164,7 @@ export class ServerlessFunctionResolver {
|
||||
}
|
||||
|
||||
@Mutation(() => ServerlessFunctionDTO)
|
||||
@UseGuards(SettingsPermissionsGuard(PermissionFlagType.WORKFLOWS))
|
||||
async publishServerlessFunction(
|
||||
@Args('input') input: PublishServerlessFunctionInput,
|
||||
@AuthWorkspace() { id: workspaceId }: WorkspaceEntity,
|
||||
|
||||
Reference in New Issue
Block a user