diff --git a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/create-view-field-permission.guard.ts b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/create-view-field-permission.guard.ts index ad2bc62a83..b5cda6f4b0 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/create-view-field-permission.guard.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/create-view-field-permission.guard.ts @@ -40,6 +40,7 @@ export class CreateViewFieldPermissionGuard implements CanActivate { viewId, request.userWorkspaceId, request.workspace.id, + request.apiKey?.id, ); } } diff --git a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/create-view-filter-group-permission.guard.ts b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/create-view-filter-group-permission.guard.ts index a79da1a2f3..f57d6bc02c 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/create-view-filter-group-permission.guard.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/create-view-filter-group-permission.guard.ts @@ -33,6 +33,7 @@ export class CreateViewFilterGroupPermissionGuard implements CanActivate { viewId, request.userWorkspaceId, request.workspace.id, + request.apiKey?.id, ); } } diff --git a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/create-view-filter-permission.guard.ts b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/create-view-filter-permission.guard.ts index a48699bb4d..a94cb91b3f 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/create-view-filter-permission.guard.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/create-view-filter-permission.guard.ts @@ -33,6 +33,7 @@ export class CreateViewFilterPermissionGuard implements CanActivate { viewId, request.userWorkspaceId, request.workspace.id, + request.apiKey?.id, ); } } diff --git a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/create-view-group-permission.guard.ts b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/create-view-group-permission.guard.ts index 958b209d3b..2ef73d4acb 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/create-view-group-permission.guard.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/create-view-group-permission.guard.ts @@ -40,6 +40,7 @@ export class CreateViewGroupPermissionGuard implements CanActivate { viewId, request.userWorkspaceId, request.workspace.id, + request.apiKey?.id, ); } } diff --git a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/create-view-permission.guard.ts b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/create-view-permission.guard.ts index 5f1baf9050..0d267eddcf 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/create-view-permission.guard.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/create-view-permission.guard.ts @@ -34,6 +34,7 @@ export class CreateViewPermissionGuard implements CanActivate { visibility, request.userWorkspaceId, request.workspace.id, + request.apiKey?.id, ); } } diff --git a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/create-view-sort-permission.guard.ts b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/create-view-sort-permission.guard.ts index d15537b71e..33b4d5c7cb 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/create-view-sort-permission.guard.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/create-view-sort-permission.guard.ts @@ -33,6 +33,7 @@ export class CreateViewSortPermissionGuard implements CanActivate { viewId, request.userWorkspaceId, request.workspace.id, + request.apiKey?.id, ); } } diff --git a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/delete-view-field-permission.guard.ts b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/delete-view-field-permission.guard.ts index a00ee8cd0f..9d6d967928 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/delete-view-field-permission.guard.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/delete-view-field-permission.guard.ts @@ -45,6 +45,7 @@ export class DeleteViewFieldPermissionGuard implements CanActivate { viewId, request.userWorkspaceId, request.workspace.id, + request.apiKey?.id, ); } } diff --git a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/delete-view-filter-group-permission.guard.ts b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/delete-view-filter-group-permission.guard.ts index 9f30a662d9..1a31c1d8cd 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/delete-view-filter-group-permission.guard.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/delete-view-filter-group-permission.guard.ts @@ -45,6 +45,7 @@ export class DeleteViewFilterGroupPermissionGuard implements CanActivate { viewId, request.userWorkspaceId, request.workspace.id, + request.apiKey?.id, ); } } diff --git a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/delete-view-filter-permission.guard.ts b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/delete-view-filter-permission.guard.ts index 90ab35416e..82312a22c5 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/delete-view-filter-permission.guard.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/delete-view-filter-permission.guard.ts @@ -45,6 +45,7 @@ export class DeleteViewFilterPermissionGuard implements CanActivate { viewId, request.userWorkspaceId, request.workspace.id, + request.apiKey?.id, ); } } diff --git a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/delete-view-group-permission.guard.ts b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/delete-view-group-permission.guard.ts index f8f4ae014e..d36398a279 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/delete-view-group-permission.guard.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/delete-view-group-permission.guard.ts @@ -45,6 +45,7 @@ export class DeleteViewGroupPermissionGuard implements CanActivate { viewId, request.userWorkspaceId, request.workspace.id, + request.apiKey?.id, ); } } diff --git a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/delete-view-permission.guard.ts b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/delete-view-permission.guard.ts index 39da34d675..a9324ce4b5 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/delete-view-permission.guard.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/delete-view-permission.guard.ts @@ -33,6 +33,7 @@ export class DeleteViewPermissionGuard implements CanActivate { viewId, request.userWorkspaceId, request.workspace.id, + request.apiKey?.id, ); } } diff --git a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/delete-view-sort-permission.guard.ts b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/delete-view-sort-permission.guard.ts index 6c9fc51938..a69a7f59a4 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/delete-view-sort-permission.guard.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/delete-view-sort-permission.guard.ts @@ -45,6 +45,7 @@ export class DeleteViewSortPermissionGuard implements CanActivate { viewId, request.userWorkspaceId, request.workspace.id, + request.apiKey?.id, ); } } diff --git a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/destroy-view-field-permission.guard.ts b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/destroy-view-field-permission.guard.ts index 095e375656..93e6c5c64f 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/destroy-view-field-permission.guard.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/destroy-view-field-permission.guard.ts @@ -45,6 +45,7 @@ export class DestroyViewFieldPermissionGuard implements CanActivate { viewId, request.userWorkspaceId, request.workspace.id, + request.apiKey?.id, ); } } diff --git a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/destroy-view-filter-group-permission.guard.ts b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/destroy-view-filter-group-permission.guard.ts index ec6b427484..c836641662 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/destroy-view-filter-group-permission.guard.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/destroy-view-filter-group-permission.guard.ts @@ -45,6 +45,7 @@ export class DestroyViewFilterGroupPermissionGuard implements CanActivate { viewId, request.userWorkspaceId, request.workspace.id, + request.apiKey?.id, ); } } diff --git a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/destroy-view-filter-permission.guard.ts b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/destroy-view-filter-permission.guard.ts index bc59c21861..ef88ae11f5 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/destroy-view-filter-permission.guard.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/destroy-view-filter-permission.guard.ts @@ -45,6 +45,7 @@ export class DestroyViewFilterPermissionGuard implements CanActivate { viewId, request.userWorkspaceId, request.workspace.id, + request.apiKey?.id, ); } } diff --git a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/destroy-view-group-permission.guard.ts b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/destroy-view-group-permission.guard.ts index dea1be66f3..b1c83a2da1 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/destroy-view-group-permission.guard.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/destroy-view-group-permission.guard.ts @@ -45,6 +45,7 @@ export class DestroyViewGroupPermissionGuard implements CanActivate { viewId, request.userWorkspaceId, request.workspace.id, + request.apiKey?.id, ); } } diff --git a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/destroy-view-permission.guard.ts b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/destroy-view-permission.guard.ts index 686328ff92..d671f858df 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/destroy-view-permission.guard.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/destroy-view-permission.guard.ts @@ -33,6 +33,7 @@ export class DestroyViewPermissionGuard implements CanActivate { viewId, request.userWorkspaceId, request.workspace.id, + request.apiKey?.id, ); } } diff --git a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/destroy-view-sort-permission.guard.ts b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/destroy-view-sort-permission.guard.ts index e127634f06..9e3717e38e 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/destroy-view-sort-permission.guard.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/destroy-view-sort-permission.guard.ts @@ -45,6 +45,7 @@ export class DestroyViewSortPermissionGuard implements CanActivate { viewId, request.userWorkspaceId, request.workspace.id, + request.apiKey?.id, ); } } diff --git a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/update-view-field-permission.guard.ts b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/update-view-field-permission.guard.ts index c1b7573f7c..79e5e83c62 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/update-view-field-permission.guard.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/update-view-field-permission.guard.ts @@ -45,6 +45,7 @@ export class UpdateViewFieldPermissionGuard implements CanActivate { viewId, request.userWorkspaceId, request.workspace.id, + request.apiKey?.id, ); } } diff --git a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/update-view-filter-group-permission.guard.ts b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/update-view-filter-group-permission.guard.ts index 9e6406fb2a..7280e5ca9d 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/update-view-filter-group-permission.guard.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/update-view-filter-group-permission.guard.ts @@ -45,6 +45,7 @@ export class UpdateViewFilterGroupPermissionGuard implements CanActivate { viewId, request.userWorkspaceId, request.workspace.id, + request.apiKey?.id, ); } } diff --git a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/update-view-filter-permission.guard.ts b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/update-view-filter-permission.guard.ts index 473c105acf..0f17eaccf5 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/update-view-filter-permission.guard.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/update-view-filter-permission.guard.ts @@ -45,6 +45,7 @@ export class UpdateViewFilterPermissionGuard implements CanActivate { viewId, request.userWorkspaceId, request.workspace.id, + request.apiKey?.id, ); } } diff --git a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/update-view-group-permission.guard.ts b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/update-view-group-permission.guard.ts index f44c134afd..e2b7ceebe3 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/update-view-group-permission.guard.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/update-view-group-permission.guard.ts @@ -45,6 +45,7 @@ export class UpdateViewGroupPermissionGuard implements CanActivate { viewId, request.userWorkspaceId, request.workspace.id, + request.apiKey?.id, ); } } diff --git a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/update-view-permission.guard.ts b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/update-view-permission.guard.ts index ca6d8e32e2..81c803c42f 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/update-view-permission.guard.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/update-view-permission.guard.ts @@ -33,6 +33,7 @@ export class UpdateViewPermissionGuard implements CanActivate { viewId, request.userWorkspaceId, request.workspace.id, + request.apiKey?.id, ); } } diff --git a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/update-view-sort-permission.guard.ts b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/update-view-sort-permission.guard.ts index 800a42630a..f75526014c 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/update-view-sort-permission.guard.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-permissions/guards/update-view-sort-permission.guard.ts @@ -45,6 +45,7 @@ export class UpdateViewSortPermissionGuard implements CanActivate { viewId, request.userWorkspaceId, request.workspace.id, + request.apiKey?.id, ); } } diff --git a/packages/twenty-server/src/engine/metadata-modules/view-permissions/services/view-access.service.ts b/packages/twenty-server/src/engine/metadata-modules/view-permissions/services/view-access.service.ts index 16a98b721c..9cbf49cbd7 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-permissions/services/view-access.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-permissions/services/view-access.service.ts @@ -26,6 +26,7 @@ export class ViewAccessService { viewId: string | null, userWorkspaceId: string | undefined, workspaceId: string, + apiKeyId?: string, ): Promise { // If viewId is null, the entity doesn't exist - allow the operation // so the service can handle the NOT_FOUND error properly @@ -43,13 +44,14 @@ export class ViewAccessService { return true; } - return this.checkViewAccess(view, userWorkspaceId, workspaceId); + return this.checkViewAccess(view, userWorkspaceId, workspaceId, apiKeyId); } async canUserModifyViewByChildEntity( viewId: string | null, userWorkspaceId: string | undefined, workspaceId: string, + apiKeyId?: string, ): Promise { // If viewId is null, the child entity doesn't exist // Allow through so the service can throw the proper entity-specific error @@ -68,24 +70,36 @@ export class ViewAccessService { return true; } - return this.checkViewAccess(view, userWorkspaceId, workspaceId); + return this.checkViewAccess(view, userWorkspaceId, workspaceId, apiKeyId); } async canUserCreateView( visibility: ViewVisibility, userWorkspaceId: string | undefined, workspaceId: string, + apiKeyId?: string, ): Promise { - // For WORKSPACE visibility views, user must have VIEWS permission - if (visibility === ViewVisibility.WORKSPACE && isDefined(userWorkspaceId)) { - const permissions = - await this.permissionsService.getUserWorkspacePermissions({ - userWorkspaceId, - workspaceId, - }); + // For WORKSPACE visibility views, check VIEWS permission + if (visibility === ViewVisibility.WORKSPACE) { + let hasViewsPermission = false; - const hasViewsPermission = - permissions.permissionFlags[PermissionFlagType.VIEWS] ?? false; + if (isDefined(userWorkspaceId)) { + const permissions = + await this.permissionsService.getUserWorkspacePermissions({ + userWorkspaceId, + workspaceId, + }); + + hasViewsPermission = + permissions.permissionFlags[PermissionFlagType.VIEWS] ?? false; + } else if (isDefined(apiKeyId)) { + hasViewsPermission = + await this.permissionsService.userHasWorkspaceSettingPermission({ + workspaceId, + apiKeyId, + setting: PermissionFlagType.VIEWS, + }); + } if (!hasViewsPermission) { throw new ViewException( @@ -102,7 +116,7 @@ export class ViewAccessService { } } - // For UNLISTED views or users without userWorkspaceId, allow creation + // For UNLISTED views, allow creation return true; } @@ -110,18 +124,29 @@ export class ViewAccessService { view: ViewEntity, userWorkspaceId: string | undefined, workspaceId: string, + apiKeyId?: string, ): Promise { - const permissions = isDefined(userWorkspaceId) - ? await this.permissionsService.getUserWorkspacePermissions({ + let hasViewsPermission = false; + + if (isDefined(userWorkspaceId)) { + const permissions = + await this.permissionsService.getUserWorkspacePermissions({ userWorkspaceId, workspaceId, - }) - : null; + }); - const hasViewsPermission = - permissions?.permissionFlags[PermissionFlagType.VIEWS] ?? false; + hasViewsPermission = + permissions.permissionFlags[PermissionFlagType.VIEWS] ?? false; + } else if (isDefined(apiKeyId)) { + hasViewsPermission = + await this.permissionsService.userHasWorkspaceSettingPermission({ + workspaceId, + apiKeyId, + setting: PermissionFlagType.VIEWS, + }); + } - // Users with VIEWS permission can manipulate all views + // Users/API keys with VIEWS permission can manipulate all views if (hasViewsPermission) { return true; } diff --git a/packages/twenty-server/src/engine/metadata-modules/view/resolvers/view.resolver.ts b/packages/twenty-server/src/engine/metadata-modules/view/resolvers/view.resolver.ts index 6e21bb572e..b76efc4b10 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view/resolvers/view.resolver.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view/resolvers/view.resolver.ts @@ -153,7 +153,7 @@ export class ViewResolver { return await this.viewService.createOne({ createViewInput: input, workspaceId: workspace.id, - createdByUserWorkspaceId: userWorkspaceId ?? '', + createdByUserWorkspaceId: userWorkspaceId, }); }