feat(@xen-orchestra/rest-api): expose users authentication_tokens (#8865)

This commit is contained in:
MlssFrncJrg
2025-09-23 15:51:09 +02:00
committed by GitHub
parent b01adbe2e1
commit 4453bbc16c
6 changed files with 81 additions and 4 deletions

View File

@@ -593,6 +593,19 @@ export type XoUser = {
preferences: Record<string, string>
}
export type XoAuthenticationToken = {
client?: {
id: string
[key: string]: unknown
}
created_at?: number
description?: string
user_id: XoUser['id']
expiration: number
last_uses?: Record<string, { timestamp: number }>
id: Branded<'authentication-token'>
}
export type XoVbd = BaseXapiXo & {
attached: boolean
bootable: boolean

View File

@@ -28,3 +28,37 @@ export const user = {
}
export const userId = { id: '722d17b9-699b-49d2-8193-be1ac573d3de' }
export const authenticationTokens = [
{
client: {
id: 'w574r066b5',
},
created_at: 1754383334192,
description: 'xo-cli@0.32.2 - fedora-2.home - Linux x86_64',
user_id: '722d17b9-699b-49d2-8193-be1ac573d3de',
expiration: 1756975334192,
last_uses: {
'::1': {
timestamp: 1754383346794,
},
},
id: 'LB_DqCNhcmAoyiioNnajySHIYHrWfsIhYSYn3n8FfJA',
},
{
client: {
id: 'nemyw6m3dx',
},
created_at: 1754471974241,
description: 'Mozilla/5.0 (X11; Linux x86_64; rv:141.0) Gecko/20100101 Firefox/141.0',
user_id: '722d17b9-699b-49d2-8193-be1ac573d3de',
expiration: 1754507974241,
last_uses: {
'::ffff:127.0.0.1': {
timestamp: 1754475904704,
},
},
id: 'ktdlq-BX_GdS5N8MR0v7QIuoSymBw4Ys4EOxsOdqpnE',
},
]

View File

@@ -35,6 +35,7 @@ import type {
XoPool,
XoTask,
XoProxy,
XoAuthenticationToken,
AnyXoBackupJob,
AnyXoLog,
} from '@vates/types/xo'
@@ -126,6 +127,7 @@ export type XoApp = {
getAllSchedules(): Promise<XoSchedule[]>
getAllUsers(): Promise<XoUser[]>
getAllXenServers(): Promise<XoServer[]>
getAuthenticationTokensForUser(userId: XoUser['id']): Promise<XoAuthenticationToken[]>
getBackupNgLogs(): Promise<Record<string, AnyXoLog>>
getBackupNgLogs(id: AnyXoLog['id']): Promise<AnyXoLog>
getBackupNgLogsSorted(opts: {

View File

@@ -18,7 +18,7 @@ import {
import { inject } from 'inversify'
import { json, type Request as ExRequest, type Response as ExResponse } from 'express'
import { provide } from 'inversify-binding-decorators'
import type { XoGroup, XoUser } from '@vates/types'
import type { XoAuthenticationToken, XoGroup, XoUser } from '@vates/types'
import {
createdResp,
@@ -31,13 +31,13 @@ import {
type Unbrand,
} from '../open-api/common/response.common.mjs'
import { forbiddenOperation } from 'xo-common/api-errors.js'
import { partialUsers, user, userId, userIds } from '../open-api/oa-examples/user.oa-example.mjs'
import { partialUsers, user, authenticationTokens, userId, userIds } from '../open-api/oa-examples/user.oa-example.mjs'
import { RestApi } from '../rest-api/rest-api.mjs'
import type { SendObjects } from '../helpers/helper.type.mjs'
import { limitAndFilterArray } from '../helpers/utils.helper.mjs'
import type { UpdateUserRequestBody } from './user.type.mjs'
import { UserService } from './user.service.mjs'
import { XoController } from '../abstract-classes/xo-controller.mjs'
import { limitAndFilterArray } from '../helpers/utils.helper.mjs'
import { groupIds, partialGroups } from '../open-api/oa-examples/group.oa-example.mjs'
@Route('users')
@@ -209,4 +209,31 @@ export class UserController extends XoController<XoUser> {
return this.sendObjects(limitAndFilterArray(groups, { filter, limit }), req, 'groups')
}
/**
* @example id "722d17b9-699b-49d2-8193-be1ac573d3de"
* @example filter "expiration:>1757371582496"
* @example limit 42
*/
@Example(authenticationTokens)
@Get('{id}/authentication_tokens')
@Response(notFoundResp.status, notFoundResp.description)
@Response(forbiddenOperationResp.status, forbiddenOperationResp.description)
async getAuthenticationTokens(
@Request() req: ExRequest,
@Path() id: string,
@Query() filter?: string,
@Query() limit?: number
): Promise<Unbrand<XoAuthenticationToken>[]> {
const user = await this.getObject(id as XoUser['id'])
const me = this.restApi.getCurrentUser()
if (me.id !== user.id) {
throw forbiddenOperation('get authentication tokens', 'can only see own authentication tokens')
}
const tokens = await this.restApi.xoApp.getAuthenticationTokensForUser(user.id)
return limitAndFilterArray(tokens, { filter, limit })
}
}

View File

@@ -42,7 +42,7 @@
- **deprecated** `GET /rest/v0/restore/logs` (PR [#8987](https://github.com/vatesfr/xen-orchestra/pull/8987))
- **deprecated** `GET /rest/v0/restore/logs/<restore-log-id>` (PR [#8987](https://github.com/vatesfr/xen-orchestra/pull/8987))
- `GET /rest/v0/vms/<vm-id>/messages` (PR [#8988](https://github.com/vatesfr/xen-orchestra/pull/8988))
- `GET /rest/v0/users/<user-id>/authentication_tokens` (PR [#8865](https://github.com/vatesfr/xen-orchestra/pull/8865))
- [REST API] Expose `/rest/v0/proxies` and `/rest/v0/proxies/<proxy-id>` (PR [#8920](https://github.com/vatesfr/xen-orchestra/pull/8920))
- [XO5/Templates] Show template id when expanded the templates list (PR [#8949](https://github.com/vatesfr/xen-orchestra/pull/8949))

View File

@@ -256,6 +256,7 @@ export default class RestApi {
users: {
routes: {
groups: true,
authentication_tokens: true,
},
},
vifs: {