From 72f96701f05366cec075311782f0a1e5bbd19fc8 Mon Sep 17 00:00:00 2001 From: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com> Date: Wed, 28 Oct 2026 14:06:21 +0100 Subject: [PATCH] feat: cluster group admin permission for regenerate people (#32787) (cherry picked from commit 9f273a604d5bdbd9583758c3a79d2fc0141c7a77) --- open-api/immich-openapi-specs.json | 3 ++- packages/sdk/src/fetch-client.ts | 1 + server/src/controllers/cluster-group.controller.ts | 2 +- server/src/enum.ts | 1 + server/src/services/cluster-group.service.ts | 2 +- server/src/utils/access.ts | 4 ++++ 6 files changed, 10 insertions(+), 3 deletions(-) diff --git a/open-api/immich-openapi-specs.json b/open-api/immich-openapi-specs.json index 8224a575d..ac9fe5811 100644 --- a/open-api/immich-openapi-specs.json +++ b/open-api/immich-openapi-specs.json @@ -6343,7 +6343,7 @@ "state": "Added" } ], - "x-immich-permission": "clusterGroup.read" + "x-immich-permission": "clusterGroup.admin" } }, "/cluster-groups/{id}/requests": { @@ -25811,6 +25811,7 @@ "backup.delete", "clusterGroup.read", "clusterGroup.leave", + "clusterGroup.admin", "clusterGroupRequest.create", "clusterGroupRequest.read", "clusterGroupRequest.delete", diff --git a/packages/sdk/src/fetch-client.ts b/packages/sdk/src/fetch-client.ts index 8c2811d40..d089a2033 100644 --- a/packages/sdk/src/fetch-client.ts +++ b/packages/sdk/src/fetch-client.ts @@ -8351,6 +8351,7 @@ export enum Permission { BackupDelete = "backup.delete", ClusterGroupRead = "clusterGroup.read", ClusterGroupLeave = "clusterGroup.leave", + ClusterGroupAdmin = "clusterGroup.admin", ClusterGroupRequestCreate = "clusterGroupRequest.create", ClusterGroupRequestRead = "clusterGroupRequest.read", ClusterGroupRequestDelete = "clusterGroupRequest.delete", diff --git a/server/src/controllers/cluster-group.controller.ts b/server/src/controllers/cluster-group.controller.ts index d72598cc1..5675c19b0 100644 --- a/server/src/controllers/cluster-group.controller.ts +++ b/server/src/controllers/cluster-group.controller.ts @@ -94,7 +94,7 @@ export class ClusterGroupController { } @Post(':id/regenerate-people') - @Authenticated({ permission: Permission.ClusterGroupRead }) + @Authenticated({ permission: Permission.ClusterGroupAdmin }) @HttpCode(HttpStatus.NO_CONTENT) @Endpoint({ summary: 'Regenerate people of users in cluster group', diff --git a/server/src/enum.ts b/server/src/enum.ts index 6691415e6..4f69ddf25 100644 --- a/server/src/enum.ts +++ b/server/src/enum.ts @@ -193,6 +193,7 @@ export enum Permission { ClusterGroupRead = 'clusterGroup.read', ClusterGroupLeave = 'clusterGroup.leave', + ClusterGroupAdmin = 'clusterGroup.admin', ClusterGroupRequestCreate = 'clusterGroupRequest.create', ClusterGroupRequestRead = 'clusterGroupRequest.read', ClusterGroupRequestDelete = 'clusterGroupRequest.delete', diff --git a/server/src/services/cluster-group.service.ts b/server/src/services/cluster-group.service.ts index cd3e78bb9..dd24f5440 100644 --- a/server/src/services/cluster-group.service.ts +++ b/server/src/services/cluster-group.service.ts @@ -73,7 +73,7 @@ export class ClusterGroupService extends BaseService { } async regeneratePeople(auth: AuthDto, id: string) { - await this.requireAccess({ auth, permission: Permission.ClusterGroupRead, ids: [id] }); + await this.requireAccess({ auth, permission: Permission.ClusterGroupAdmin, ids: [id] }); await this.jobRepository.queue({ name: JobName.FacialRecognitionQueueAll, diff --git a/server/src/utils/access.ts b/server/src/utils/access.ts index b328b18c6..271023c3b 100644 --- a/server/src/utils/access.ts +++ b/server/src/utils/access.ts @@ -356,6 +356,10 @@ const checkOtherAccess = async (access: AccessRepository, request: OtherAccessRe return access.person.checkFaceOwnerAccess(auth.user.id, ids); } + case Permission.ClusterGroupAdmin: { + return access.clusterGroup.checkOwnerAccess(auth.user.id, ids); + } + case Permission.ClusterGroupRead: { const isMember = await access.clusterGroup.checkOwnerAccess(auth.user.id, ids); const isInvited = await access.clusterGroup.checkInviteAccess(auth.user.id, setDifference(ids, isMember));