## 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.
38 lines
1.1 KiB
TypeScript
38 lines
1.1 KiB
TypeScript
import { createOneCoreView } from 'test/integration/metadata/suites/view/utils/create-one-core-view.util';
|
|
|
|
import { type CreateViewInput } from 'src/engine/metadata-modules/view/dtos/inputs/create-view.input';
|
|
import { type ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
|
|
|
|
import { createViewData } from './view-data-factory.util';
|
|
|
|
export const createTestViewWithGraphQL = async (
|
|
overrides: Partial<ViewEntity> = {},
|
|
): Promise<ViewEntity> => {
|
|
const viewData = createViewData(overrides);
|
|
const input: CreateViewInput = {
|
|
name: viewData.name,
|
|
objectMetadataId: viewData.objectMetadataId as string,
|
|
icon: viewData.icon,
|
|
type: viewData.type,
|
|
position: viewData.position,
|
|
isCompact: viewData.isCompact,
|
|
openRecordIn: viewData.openRecordIn,
|
|
visibility: viewData.visibility,
|
|
};
|
|
|
|
const { data, errors } = await createOneCoreView({
|
|
input,
|
|
expectToFail: false,
|
|
});
|
|
|
|
if (errors) {
|
|
throw new Error(`Failed to create test view: ${JSON.stringify(errors)}`);
|
|
}
|
|
|
|
if (!data) {
|
|
throw new Error('No data returned from createTestViewWithGraphQL');
|
|
}
|
|
|
|
return data.createCoreView;
|
|
};
|