From bd5937366a2ada55e42fc5ac475f77a85490c2f1 Mon Sep 17 00:00:00 2001 From: MathieuRA Date: Tue, 7 Jul 2026 08:42:40 -0400 Subject: [PATCH] feat(rest-api): expose groups/:id/acl-roles --- @vates/types/src/xo-app.mts | 1 + .../rest-api/src/groups/group.controller.mts | 38 ++++++++++++++++++- CHANGELOG.unreleased.md | 1 + .../xo-server/src/xo-mixins/acls-v2/index.mjs | 2 +- 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/@vates/types/src/xo-app.mts b/@vates/types/src/xo-app.mts index 395c218315..5d9bb79393 100644 --- a/@vates/types/src/xo-app.mts +++ b/@vates/types/src/xo-app.mts @@ -248,6 +248,7 @@ export type XoApp = { getAclV2RolePrivileges(roleId: XoAclRole['id']): Promise getAclV2Role(id: XoAclRole['id']): Promise deleteAclV2UserRole(userId: XoUser['id'], roleId: XoAclRole['id']): Promise + getAclV2GroupRoles(groupId: XoGroup['id']): Promise[]> getAclV2Roles(): Promise getAclV2UserPrivileges(userId: XoUser['id']): Promise getAllGroups(): Promise diff --git a/@xen-orchestra/rest-api/src/groups/group.controller.mts b/@xen-orchestra/rest-api/src/groups/group.controller.mts index 4cc6dd8025..dfed386b6a 100644 --- a/@xen-orchestra/rest-api/src/groups/group.controller.mts +++ b/@xen-orchestra/rest-api/src/groups/group.controller.mts @@ -20,7 +20,7 @@ import { import { inject } from 'inversify' import { json, type Request as ExRequest } from 'express' import { provide } from 'inversify-binding-decorators' -import type { XoGroup, XoTask, XoUser } from '@vates/types' +import type { XoAclRole, XoGroup, XoTask, XoUser } from '@vates/types' import { forbiddenOperation } from 'xo-common/api-errors.js' import { @@ -44,6 +44,7 @@ import { limitAndFilterArray } from '../helpers/utils.helper.mjs' import { partialUsers, userIds } from '../open-api/oa-examples/user.oa-example.mjs' import { partialTasks, taskIds } from '../open-api/oa-examples/task.oa-example.mjs' import { acl, actionFromBody } from '../middlewares/acl.middleware.mjs' +import { aclRoleIds, partialAclRoles } from '../open-api/oa-examples/acl-role.oa-example.mjs' @Route('groups') @Security('*') @@ -328,4 +329,39 @@ export class GroupController extends XoController { privilege: { action: 'read', resource: 'task' }, }) } + + /** + * Returns all acl-roles that match the following privilege: + * - resource: acl-role, action: read + * + * @example id "6c81b5e1-afc1-43ea-8f8d-939ceb5f3f90" + * @example fields "id,name,isTemplate" + * @example filter "name:read only" + * @example limit 42 + */ + @Example(aclRoleIds) + @Example(partialAclRoles) + @Extension('x-mcp-exposure', 'allow') + @Get('{id}/acl-roles') + @Security('*', ['acl']) + @Tags('rbacs') + @Response(notFoundResp.status, notFoundResp.description) + async getGroupAclRoles( + @Request() req: ExRequest, + @Path() id: string, + @Query() fields?: string, + @Query() ndjson?: boolean, + @Query() markdown?: boolean, + @Query() filter?: string, + @Query() limit?: number + ): SendObjects>>> { + const group = await this.getObject(id as XoGroup['id']) + const roles = await Promise.all(group.aclRoleIds.map(roleId => this.restApi.xoApp.getAclV2Role(roleId))) + + return this.sendObjects(limitAndFilterArray(roles, { filter }), req, { + path: 'acl-roles', + limit, + privilege: { action: 'read', resource: 'acl-role' }, + }) + } } diff --git a/CHANGELOG.unreleased.md b/CHANGELOG.unreleased.md index dbc91fec4f..ce3d67b399 100644 --- a/CHANGELOG.unreleased.md +++ b/CHANGELOG.unreleased.md @@ -38,6 +38,7 @@ - [REST API] Possibility to set the HA restart priority (`high_availability`) when creating a VM (PR [#10070](https://github.com/vatesfr/xen-orchestra/pull/10070)) - [XO6/Traffic rules] Show only traffic rules of VMs. Don't include vm-snapshots or vm-templates. In the VM selector, disable VMs that don't have any VIF (PR [#9977](https://github.com/vatesfr/xen-orchestra/pull/9977)) - [Pool] Add new VM and disconnect actions to the pool infrastructure tree (PR [#10046](https://github.com/vatesfr/xen-orchestra/pull/10046)) +- [REST API] Expose `/rest/v0/groups/:id/acl-roles` (PR [#10085](https://github.com/vatesfr/xen-orchestra/pull/10085)) ### Bug fixes diff --git a/packages/xo-server/src/xo-mixins/acls-v2/index.mjs b/packages/xo-server/src/xo-mixins/acls-v2/index.mjs index 8b6dc15185..504a5dc8f7 100644 --- a/packages/xo-server/src/xo-mixins/acls-v2/index.mjs +++ b/packages/xo-server/src/xo-mixins/acls-v2/index.mjs @@ -610,7 +610,7 @@ export default class { /** * @param {XoGroup['id']} groupId - * @returns {Promise} + * @returns {Promise[]>} */ async getAclV2GroupRoles(groupId) { await this._app.checkFeatureAuthorization('RBAC')