@xen-orchestra/rest-api 0.28.2 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +108 -1
- package/dist/abstract-classes/base-controller.mjs +28 -3
- package/dist/abstract-classes/listener.mjs +124 -15
- package/dist/acl-privileges/acl-privilege.controller.mjs +172 -0
- package/dist/acl-roles/acl-role.controller.mjs +384 -0
- package/dist/alarms/alarm.controller.mjs +25 -11
- package/dist/alarms/alarm.service.mjs +8 -0
- package/dist/backup-archives/backup-archive.controller.mjs +33 -23
- package/dist/backup-archives/backup-archive.service.mjs +21 -0
- package/dist/backup-jobs/backup-job.controller.mjs +74 -25
- package/dist/backup-jobs/backup-job.service.mjs +7 -0
- package/dist/backup-logs/backup-log.controller.mjs +28 -13
- package/dist/backup-logs/backup-log.service.mjs +19 -0
- package/dist/backup-repositories/backup-repositories.controller.mjs +24 -5
- package/dist/events/event.class.mjs +36 -18
- package/dist/events/event.controller.mjs +3 -0
- package/dist/events/event.service.mjs +4 -4
- package/dist/groups/group.controller.mjs +99 -12
- package/dist/helpers/markdown.helper.mjs +20 -0
- package/dist/helpers/object-wrapper.helper.mjs +3 -3
- package/dist/hosts/host.controller.mjs +90 -15
- package/dist/ioc/ioc.mjs +13 -4
- package/dist/messages/message.controller.mjs +32 -10
- package/dist/middlewares/acl.middleware.mjs +202 -0
- package/dist/middlewares/authentication.middleware.mjs +15 -6
- package/dist/middlewares/tsoa-to-xo-error.middleware.mjs +19 -1
- package/dist/networks/network.controller.mjs +72 -17
- package/dist/open-api/oa-examples/acl-privilege.oa-example.mjs +25 -0
- package/dist/open-api/oa-examples/acl-role.oa-example.mjs +22 -0
- package/dist/open-api/oa-examples/backup-archive.oa-example.mjs +6 -6
- package/dist/open-api/oa-examples/common.oa-example.mjs +3 -0
- package/dist/open-api/routes/routes.js +856 -172
- package/dist/pbds/pbd.controller.mjs +20 -5
- package/dist/pcis/pci.controller.mjs +19 -5
- package/dist/pgpus/pgpu.controller.mjs +19 -5
- package/dist/pifs/pif.controller.mjs +56 -16
- package/dist/pools/pool.controller.mjs +166 -17
- package/dist/proxies/proxy.controller.mjs +25 -6
- package/dist/restore-logs/restore-log.controller.mjs +42 -23
- package/dist/schedules/schedule.controller.mjs +36 -5
- package/dist/servers/server.controller.mjs +71 -9
- package/dist/sms/sm.controller.mjs +17 -4
- package/dist/srs/sr.controller.mjs +74 -18
- package/dist/tasks/task.controller.mjs +74 -13
- package/dist/users/user.controller.mjs +124 -22
- package/dist/vbds/vbd.controller.mjs +76 -38
- package/dist/vdi-snapshots/vdi-snapshot.controller.mjs +48 -14
- package/dist/vdis/vdi.controller.mjs +81 -16
- package/dist/vifs/vif.controller.mjs +118 -16
- package/dist/vm-controller/vm-controller.controller.mjs +77 -19
- package/dist/vm-snapshots/vm-snapshot.controller.mjs +85 -18
- package/dist/vm-templates/vm-template.controller.mjs +86 -18
- package/dist/vms/vm.controller.mjs +182 -24
- package/open-api/spec/swagger.json +12112 -3537
- package/package.json +12 -11
|
@@ -13,8 +13,9 @@ import { invalidParameters } from 'xo-common/api-errors.js';
|
|
|
13
13
|
import { PassThrough } from 'node:stream';
|
|
14
14
|
import { provide } from 'inversify-binding-decorators';
|
|
15
15
|
import { json } from 'express';
|
|
16
|
+
import { acl } from '../middlewares/acl.middleware.mjs';
|
|
16
17
|
import { RestApi } from '../rest-api/rest-api.mjs';
|
|
17
|
-
import { asynchronousActionResp, badRequestResp, createdResp, featureUnauthorized, internalServerErrorResp, invalidParameters as invalidParametersResp, noContentResp, notFoundResp, unauthorizedResp, } from '../open-api/common/response.common.mjs';
|
|
18
|
+
import { asynchronousActionResp, badRequestResp, createdResp, featureUnauthorized, forbiddenOperationResp, internalServerErrorResp, invalidParameters as invalidParametersResp, noContentResp, notFoundResp, unauthorizedResp, } from '../open-api/common/response.common.mjs';
|
|
18
19
|
import { XapiXoController } from '../abstract-classes/xapi-xo-controller.mjs';
|
|
19
20
|
import { AlarmService } from '../alarms/alarm.service.mjs';
|
|
20
21
|
import { genericAlarmsExample } from '../open-api/oa-examples/alarm.oa-example.mjs';
|
|
@@ -40,21 +41,33 @@ let PoolController = class PoolController extends XapiXoController {
|
|
|
40
41
|
this.#networkService = networkService;
|
|
41
42
|
}
|
|
42
43
|
/**
|
|
44
|
+
* Returns all pools that match the following privilege:
|
|
45
|
+
* - resource: pool, action: read
|
|
43
46
|
*
|
|
44
47
|
* @example fields "auto_poweron,name_label,id"
|
|
45
48
|
* @example filter "auto_poweron?"
|
|
46
49
|
* @example limit 42
|
|
47
50
|
*/
|
|
48
|
-
getPools(req, fields, ndjson, filter, limit) {
|
|
49
|
-
return this.sendObjects(Object.values(this.getObjects({ filter
|
|
51
|
+
getPools(req, fields, ndjson, markdown, filter, limit) {
|
|
52
|
+
return this.sendObjects(Object.values(this.getObjects({ filter })), req, {
|
|
53
|
+
limit,
|
|
54
|
+
privilege: { action: 'read', resource: 'pool' },
|
|
55
|
+
});
|
|
50
56
|
}
|
|
51
57
|
/**
|
|
58
|
+
* Required privilege:
|
|
59
|
+
* - resource: pool, action: read
|
|
60
|
+
*
|
|
52
61
|
* @example id "355ee47d-ff4c-4924-3db2-fd86ae629676"
|
|
53
62
|
*/
|
|
54
63
|
getPool(id) {
|
|
55
64
|
return this.getObject(id);
|
|
56
65
|
}
|
|
57
66
|
/**
|
|
67
|
+
* Required privilege:
|
|
68
|
+
* - resource: pool, action: create:network
|
|
69
|
+
* - resource: network, action: create
|
|
70
|
+
*
|
|
58
71
|
* @example id "355ee47d-ff4c-4924-3db2-fd86ae629676"
|
|
59
72
|
* @example body {
|
|
60
73
|
* "name": "awes0me_network",
|
|
@@ -130,6 +143,9 @@ let PoolController = class PoolController extends XapiXoController {
|
|
|
130
143
|
});
|
|
131
144
|
}
|
|
132
145
|
/**
|
|
146
|
+
* Required privilege:
|
|
147
|
+
* - resource: pool, action: emergency-shutdown
|
|
148
|
+
*
|
|
133
149
|
* @example id "355ee47d-ff4c-4924-3db2-fd86ae629677"
|
|
134
150
|
*/
|
|
135
151
|
emergencyShutdown(id, sync) {
|
|
@@ -148,6 +164,9 @@ let PoolController = class PoolController extends XapiXoController {
|
|
|
148
164
|
});
|
|
149
165
|
}
|
|
150
166
|
/**
|
|
167
|
+
* Required privilege:
|
|
168
|
+
* - resource: pool, action: rolling-reboot
|
|
169
|
+
*
|
|
151
170
|
* @example id "355ee47d-ff4c-4924-3db2-fd86ae629677"
|
|
152
171
|
*/
|
|
153
172
|
rollingReboot(id, sync) {
|
|
@@ -167,6 +186,9 @@ let PoolController = class PoolController extends XapiXoController {
|
|
|
167
186
|
});
|
|
168
187
|
}
|
|
169
188
|
/**
|
|
189
|
+
* Required privilege:
|
|
190
|
+
* - resource: pool, action: rolling-update
|
|
191
|
+
*
|
|
170
192
|
* @example id "355ee47d-ff4c-4924-3db2-fd86ae629677"
|
|
171
193
|
*/
|
|
172
194
|
rollingUpdate(id, sync) {
|
|
@@ -189,6 +211,9 @@ let PoolController = class PoolController extends XapiXoController {
|
|
|
189
211
|
/**
|
|
190
212
|
* Import an XVA VM into a pool
|
|
191
213
|
*
|
|
214
|
+
* Required privilege:
|
|
215
|
+
* - resource: sr, action: import:vm
|
|
216
|
+
*
|
|
192
217
|
* @example id "355ee47d-ff4c-4924-3db2-fd86ae629677"
|
|
193
218
|
* @example sr "c787b75c-3e0d-70fa-d0c3-cbfd382d7e33"
|
|
194
219
|
*
|
|
@@ -206,6 +231,14 @@ let PoolController = class PoolController extends XapiXoController {
|
|
|
206
231
|
return { id: vmId };
|
|
207
232
|
}
|
|
208
233
|
/**
|
|
234
|
+
* Required privilege:
|
|
235
|
+
* - resource: pool, action: create:vm
|
|
236
|
+
* - resource: vm-template, action: instantiate
|
|
237
|
+
* - resource: vdi, action: create (if vdis is passed)
|
|
238
|
+
* - resource: vdi, action: boot (if install.repository is passed)
|
|
239
|
+
* - resource: vif, action: create (if vifs is passed)
|
|
240
|
+
* - resource: host, action: allow-vm (if affinity is passed)
|
|
241
|
+
*
|
|
209
242
|
* @example id "355ee47d-ff4c-4924-3db2-fd86ae629677"
|
|
210
243
|
* @example body {
|
|
211
244
|
* "name_label": "new VM from REST API",
|
|
@@ -241,12 +274,18 @@ let PoolController = class PoolController extends XapiXoController {
|
|
|
241
274
|
});
|
|
242
275
|
}
|
|
243
276
|
/**
|
|
277
|
+
* Required privilege:
|
|
278
|
+
* - resource: pool, action: read
|
|
279
|
+
*
|
|
244
280
|
* @example id "355ee47d-ff4c-4924-3db2-fd86ae629677"
|
|
245
281
|
*/
|
|
246
282
|
getStats(id, granularity) {
|
|
247
283
|
return this.restApi.xoApp.getXapiPoolStats(id, granularity);
|
|
248
284
|
}
|
|
249
285
|
/**
|
|
286
|
+
* Required privilege:
|
|
287
|
+
* - resource: pool, action: read
|
|
288
|
+
*
|
|
250
289
|
* @example id "355ee47d-ff4c-4924-3db2-fd86ae629677"
|
|
251
290
|
*/
|
|
252
291
|
async getPoolDashboard(req, id, ndjson) {
|
|
@@ -269,20 +308,29 @@ let PoolController = class PoolController extends XapiXoController {
|
|
|
269
308
|
}
|
|
270
309
|
}
|
|
271
310
|
/**
|
|
311
|
+
* Returns all alarms that match the following privilege:
|
|
312
|
+
* - resource: alarm, action: read
|
|
313
|
+
*
|
|
272
314
|
* @example id "355ee47d-ff4c-4924-3db2-fd86ae629676"
|
|
273
315
|
* @example fields "id,time"
|
|
274
316
|
* @example filter "time:>1747053793"
|
|
275
317
|
* @example limit 42
|
|
276
318
|
*/
|
|
277
|
-
getPoolAlarms(req, id, fields, ndjson, filter, limit) {
|
|
319
|
+
getPoolAlarms(req, id, fields, ndjson, markdown, filter, limit) {
|
|
278
320
|
const pool = this.getObject(id);
|
|
279
321
|
const alarms = this.#alarmService.getAlarms({
|
|
280
322
|
filter: `${escapeUnsafeComplexMatcher(filter) ?? ''} object:uuid:${pool.uuid}`,
|
|
323
|
+
});
|
|
324
|
+
return this.sendObjects(Object.values(alarms), req, {
|
|
325
|
+
path: 'alarms',
|
|
281
326
|
limit,
|
|
327
|
+
privilege: { action: 'read', resource: 'alarm' },
|
|
282
328
|
});
|
|
283
|
-
return this.sendObjects(Object.values(alarms), req, 'alarms');
|
|
284
329
|
}
|
|
285
330
|
/**
|
|
331
|
+
* Required privilege:
|
|
332
|
+
* - resource: pool, action: read
|
|
333
|
+
*
|
|
286
334
|
* @example id "355ee47d-ff4c-4924-3db2-fd86ae629676"
|
|
287
335
|
*/
|
|
288
336
|
async getPoolMissingPatches(id) {
|
|
@@ -291,16 +339,26 @@ let PoolController = class PoolController extends XapiXoController {
|
|
|
291
339
|
return missingPatches;
|
|
292
340
|
}
|
|
293
341
|
/**
|
|
342
|
+
* Returns all messages that match the following privilege:
|
|
343
|
+
* - resource: message, action: read
|
|
344
|
+
*
|
|
294
345
|
* @example id "355ee47d-ff4c-4924-3db2-fd86ae629676"
|
|
295
346
|
* @example fields "name,id,$object"
|
|
296
347
|
* @example filter "name:IP_CONFIGURED_PIF_CAN_UNPLUG"
|
|
297
348
|
* @example limit 42
|
|
298
349
|
*/
|
|
299
|
-
getPoolMessages(req, id, fields, ndjson, filter, limit) {
|
|
300
|
-
const messages = this.getMessagesForObject(id, { filter
|
|
301
|
-
return this.sendObjects(Object.values(messages), req,
|
|
350
|
+
getPoolMessages(req, id, fields, ndjson, markdown, filter, limit) {
|
|
351
|
+
const messages = this.getMessagesForObject(id, { filter });
|
|
352
|
+
return this.sendObjects(Object.values(messages), req, {
|
|
353
|
+
path: 'messages',
|
|
354
|
+
limit,
|
|
355
|
+
privilege: { action: 'read', resource: 'message' },
|
|
356
|
+
});
|
|
302
357
|
}
|
|
303
358
|
/**
|
|
359
|
+
* Required privilege:
|
|
360
|
+
* - resource: pool, action: update:tags
|
|
361
|
+
*
|
|
304
362
|
* @example id "355ee47d-ff4c-4924-3db2-fd86ae629676"
|
|
305
363
|
* @example tag "from-rest-api"
|
|
306
364
|
*/
|
|
@@ -309,6 +367,9 @@ let PoolController = class PoolController extends XapiXoController {
|
|
|
309
367
|
await pool.$call('add_tags', tag);
|
|
310
368
|
}
|
|
311
369
|
/**
|
|
370
|
+
* Required privilege:
|
|
371
|
+
* - resource: pool, action: update:tags
|
|
372
|
+
*
|
|
312
373
|
* @example id "355ee47d-ff4c-4924-3db2-fd86ae629676"
|
|
313
374
|
* @example tag "from-rest-api"
|
|
314
375
|
*/
|
|
@@ -317,13 +378,20 @@ let PoolController = class PoolController extends XapiXoController {
|
|
|
317
378
|
await pool.$call('remove_tags', tag);
|
|
318
379
|
}
|
|
319
380
|
/**
|
|
381
|
+
* Returns all tasks that match the following privilege:
|
|
382
|
+
* - resource: task, action: read
|
|
383
|
+
*
|
|
320
384
|
* @example fields "id,status,properties"
|
|
321
385
|
* @example filter "status:failure"
|
|
322
386
|
* @example limit 42
|
|
323
387
|
*/
|
|
324
|
-
async getPoolTasks(req, id, fields, ndjson, filter, limit) {
|
|
325
|
-
const tasks = await this.getTasksForObject(id, { filter
|
|
326
|
-
return this.sendObjects(Object.values(tasks), req,
|
|
388
|
+
async getPoolTasks(req, id, fields, ndjson, markdown, filter, limit) {
|
|
389
|
+
const tasks = await this.getTasksForObject(id, { filter });
|
|
390
|
+
return this.sendObjects(Object.values(tasks), req, {
|
|
391
|
+
path: 'tasks',
|
|
392
|
+
limit,
|
|
393
|
+
privilege: { action: 'read', resource: 'task' },
|
|
394
|
+
});
|
|
327
395
|
}
|
|
328
396
|
/**
|
|
329
397
|
* Reconfigure the management interface for all hosts in the pool to use the given network.
|
|
@@ -360,15 +428,19 @@ __decorate([
|
|
|
360
428
|
Example(poolIds),
|
|
361
429
|
Example(partialPools),
|
|
362
430
|
Get(''),
|
|
431
|
+
Security('*', ['acl']),
|
|
363
432
|
__param(0, Request()),
|
|
364
433
|
__param(1, Query()),
|
|
365
434
|
__param(2, Query()),
|
|
366
435
|
__param(3, Query()),
|
|
367
|
-
__param(4, Query())
|
|
436
|
+
__param(4, Query()),
|
|
437
|
+
__param(5, Query())
|
|
368
438
|
], PoolController.prototype, "getPools", null);
|
|
369
439
|
__decorate([
|
|
370
440
|
Example(pool),
|
|
371
441
|
Get('{id}'),
|
|
442
|
+
Middlewares(acl({ resource: 'pool', action: 'read', objectId: 'params.id' })),
|
|
443
|
+
Response(forbiddenOperationResp.status, forbiddenOperationResp.description),
|
|
372
444
|
Response(notFoundResp.status, notFoundResp.description),
|
|
373
445
|
__param(0, Path())
|
|
374
446
|
], PoolController.prototype, "getPool", null);
|
|
@@ -376,9 +448,17 @@ __decorate([
|
|
|
376
448
|
Example(taskLocation),
|
|
377
449
|
Example(createNetwork),
|
|
378
450
|
Post('{id}/actions/create_network'),
|
|
379
|
-
Middlewares(
|
|
451
|
+
Middlewares([
|
|
452
|
+
json(),
|
|
453
|
+
acl([
|
|
454
|
+
// these two rights are a bit redundant, but for now this is the only way to restrict network creation on a given pool
|
|
455
|
+
{ resource: 'pool', action: 'create:network', objectId: 'params.id' },
|
|
456
|
+
{ resource: 'network', action: 'create', object: ({ req }) => req.body },
|
|
457
|
+
]),
|
|
458
|
+
]),
|
|
380
459
|
Tags('networks'),
|
|
381
460
|
SuccessResponse(createdResp.status, createdResp.description),
|
|
461
|
+
Response(forbiddenOperationResp.status, forbiddenOperationResp.description),
|
|
382
462
|
Response(asynchronousActionResp.status, asynchronousActionResp.description),
|
|
383
463
|
Response(notFoundResp.status, notFoundResp.description),
|
|
384
464
|
Response(invalidParametersResp.status, invalidParametersResp.description),
|
|
@@ -420,7 +500,9 @@ __decorate([
|
|
|
420
500
|
__decorate([
|
|
421
501
|
Example(taskLocation),
|
|
422
502
|
Post('{id}/actions/emergency_shutdown'),
|
|
503
|
+
Middlewares(acl({ resource: 'pool', action: 'emergency-shutdown', objectId: 'params.id' })),
|
|
423
504
|
SuccessResponse(asynchronousActionResp.status, asynchronousActionResp.description),
|
|
505
|
+
Response(forbiddenOperationResp.status, forbiddenOperationResp.description),
|
|
424
506
|
Response(noContentResp.status, noContentResp.description),
|
|
425
507
|
Response(featureUnauthorized.status, featureUnauthorized.description),
|
|
426
508
|
Response(notFoundResp.status, notFoundResp.description),
|
|
@@ -430,7 +512,9 @@ __decorate([
|
|
|
430
512
|
__decorate([
|
|
431
513
|
Example(taskLocation),
|
|
432
514
|
Post('{id}/actions/rolling_reboot'),
|
|
515
|
+
Middlewares(acl({ resource: 'pool', action: 'rolling-reboot', objectId: 'params.id' })),
|
|
433
516
|
SuccessResponse(asynchronousActionResp.status, asynchronousActionResp.description),
|
|
517
|
+
Response(forbiddenOperationResp.status, forbiddenOperationResp.description),
|
|
434
518
|
Response(noContentResp.status, noContentResp.description),
|
|
435
519
|
Response(featureUnauthorized.status, featureUnauthorized.description),
|
|
436
520
|
Response(notFoundResp.status, notFoundResp.description),
|
|
@@ -440,7 +524,9 @@ __decorate([
|
|
|
440
524
|
__decorate([
|
|
441
525
|
Example(taskLocation),
|
|
442
526
|
Post('{id}/actions/rolling_update'),
|
|
527
|
+
Middlewares(acl({ resource: 'pool', action: 'rolling-update', objectId: 'params.id' })),
|
|
443
528
|
SuccessResponse(asynchronousActionResp.status, asynchronousActionResp.description),
|
|
529
|
+
Response(forbiddenOperationResp.status, forbiddenOperationResp.description),
|
|
444
530
|
Response(noContentResp.status, noContentResp.description),
|
|
445
531
|
Response(featureUnauthorized.status, featureUnauthorized.description),
|
|
446
532
|
Response(notFoundResp.status, notFoundResp.description),
|
|
@@ -450,8 +536,24 @@ __decorate([
|
|
|
450
536
|
__decorate([
|
|
451
537
|
Example(importVm),
|
|
452
538
|
Post('{id}/vms'),
|
|
539
|
+
Middlewares(acl([
|
|
540
|
+
{
|
|
541
|
+
resource: 'sr',
|
|
542
|
+
action: 'import:vm',
|
|
543
|
+
objectId: ({ req, restApi }) => {
|
|
544
|
+
if (req.query.sr) {
|
|
545
|
+
return req.query.sr;
|
|
546
|
+
}
|
|
547
|
+
else {
|
|
548
|
+
const pool = restApi.getObject(req.params.id, 'pool');
|
|
549
|
+
return pool.default_SR;
|
|
550
|
+
}
|
|
551
|
+
},
|
|
552
|
+
},
|
|
553
|
+
])),
|
|
453
554
|
Tags('vms'),
|
|
454
555
|
SuccessResponse(createdResp.status, 'VM imported'),
|
|
556
|
+
Response(forbiddenOperationResp.status, forbiddenOperationResp.description),
|
|
455
557
|
Response(notFoundResp.status, notFoundResp.description),
|
|
456
558
|
Response(internalServerErrorResp.status, internalServerErrorResp.description),
|
|
457
559
|
__param(0, Request()),
|
|
@@ -462,9 +564,40 @@ __decorate([
|
|
|
462
564
|
Example(taskLocation),
|
|
463
565
|
Example(createVm),
|
|
464
566
|
Post('{id}/actions/create_vm'),
|
|
465
|
-
Middlewares(
|
|
567
|
+
Middlewares([
|
|
568
|
+
json(),
|
|
569
|
+
acl([
|
|
570
|
+
{ resource: 'pool', action: 'create:vm', objectId: 'params.id' },
|
|
571
|
+
{
|
|
572
|
+
resource: 'vm-template',
|
|
573
|
+
action: 'instantiate',
|
|
574
|
+
objectId: ({ req, restApi }) => {
|
|
575
|
+
const pool = restApi.getXapiObject(req.params.id, 'pool');
|
|
576
|
+
const template = pool.$xapi.getObject(req.body.template);
|
|
577
|
+
if (template.is_default_template) {
|
|
578
|
+
return `${pool.uuid}-${template.uuid}`;
|
|
579
|
+
}
|
|
580
|
+
return req.body.template;
|
|
581
|
+
},
|
|
582
|
+
},
|
|
583
|
+
{
|
|
584
|
+
resource: 'vdi',
|
|
585
|
+
action: 'boot',
|
|
586
|
+
objectId: ({ req }) => {
|
|
587
|
+
const repository = req.body.install?.repository;
|
|
588
|
+
if (repository !== '') {
|
|
589
|
+
return repository;
|
|
590
|
+
}
|
|
591
|
+
},
|
|
592
|
+
},
|
|
593
|
+
{ resource: 'vdi', action: 'create', objects: ({ req }) => req.body.vdis },
|
|
594
|
+
{ resource: 'vif', action: 'create', objects: ({ req }) => req.body.vifs },
|
|
595
|
+
{ resource: 'host', action: 'allow-vm', objectId: 'body.affinity' },
|
|
596
|
+
]),
|
|
597
|
+
]),
|
|
466
598
|
Tags('vms'),
|
|
467
599
|
SuccessResponse(createdResp.status, createdResp.description),
|
|
600
|
+
Response(forbiddenOperationResp.status, forbiddenOperationResp.description),
|
|
468
601
|
Response(asynchronousActionResp.status, asynchronousActionResp.description),
|
|
469
602
|
Response(notFoundResp.status, notFoundResp.description),
|
|
470
603
|
Response(internalServerErrorResp.status, internalServerErrorResp.description),
|
|
@@ -475,6 +608,8 @@ __decorate([
|
|
|
475
608
|
__decorate([
|
|
476
609
|
Example(poolStats),
|
|
477
610
|
Get('{id}/stats'),
|
|
611
|
+
Middlewares(acl({ resource: 'pool', action: 'read', objectId: 'params.id' })),
|
|
612
|
+
Response(forbiddenOperationResp.status, forbiddenOperationResp.description),
|
|
478
613
|
Response(notFoundResp.status, notFoundResp.description),
|
|
479
614
|
Response(422, 'Invalid granularity'),
|
|
480
615
|
__param(0, Path()),
|
|
@@ -483,6 +618,8 @@ __decorate([
|
|
|
483
618
|
__decorate([
|
|
484
619
|
Example(poolDashboard),
|
|
485
620
|
Get('{id}/dashboard'),
|
|
621
|
+
Middlewares(acl({ resource: 'pool', action: 'read', objectId: 'params.id' })),
|
|
622
|
+
Response(forbiddenOperationResp.status, forbiddenOperationResp.description),
|
|
486
623
|
Response(notFoundResp.status, notFoundResp.description),
|
|
487
624
|
__param(0, Request()),
|
|
488
625
|
__param(1, Path()),
|
|
@@ -491,6 +628,7 @@ __decorate([
|
|
|
491
628
|
__decorate([
|
|
492
629
|
Example(genericAlarmsExample),
|
|
493
630
|
Get('{id}/alarms'),
|
|
631
|
+
Security('*', ['acl']),
|
|
494
632
|
Tags('alarms'),
|
|
495
633
|
Response(notFoundResp.status, notFoundResp.description),
|
|
496
634
|
__param(0, Request()),
|
|
@@ -498,11 +636,14 @@ __decorate([
|
|
|
498
636
|
__param(2, Query()),
|
|
499
637
|
__param(3, Query()),
|
|
500
638
|
__param(4, Query()),
|
|
501
|
-
__param(5, Query())
|
|
639
|
+
__param(5, Query()),
|
|
640
|
+
__param(6, Query())
|
|
502
641
|
], PoolController.prototype, "getPoolAlarms", null);
|
|
503
642
|
__decorate([
|
|
504
643
|
Example(poolMissingPatches),
|
|
505
644
|
Get('{id}/missing_patches'),
|
|
645
|
+
Middlewares(acl({ resource: 'pool', action: 'read', objectId: 'params.id' })),
|
|
646
|
+
Response(forbiddenOperationResp.status, forbiddenOperationResp.description),
|
|
506
647
|
Response(notFoundResp.status, notFoundResp.description),
|
|
507
648
|
Response(featureUnauthorized.status, featureUnauthorized.description),
|
|
508
649
|
__param(0, Path())
|
|
@@ -511,6 +652,7 @@ __decorate([
|
|
|
511
652
|
Example(messageIds),
|
|
512
653
|
Example(partialMessages),
|
|
513
654
|
Get('{id}/messages'),
|
|
655
|
+
Security('*', ['acl']),
|
|
514
656
|
Tags('messages'),
|
|
515
657
|
Response(notFoundResp.status, notFoundResp.description),
|
|
516
658
|
__param(0, Request()),
|
|
@@ -518,18 +660,23 @@ __decorate([
|
|
|
518
660
|
__param(2, Query()),
|
|
519
661
|
__param(3, Query()),
|
|
520
662
|
__param(4, Query()),
|
|
521
|
-
__param(5, Query())
|
|
663
|
+
__param(5, Query()),
|
|
664
|
+
__param(6, Query())
|
|
522
665
|
], PoolController.prototype, "getPoolMessages", null);
|
|
523
666
|
__decorate([
|
|
524
667
|
Put('{id}/tags/{tag}'),
|
|
668
|
+
Middlewares(acl({ resource: 'pool', action: 'update:tags', objectId: 'params.id' })),
|
|
525
669
|
SuccessResponse(noContentResp.status, noContentResp.description),
|
|
670
|
+
Response(forbiddenOperationResp.status, forbiddenOperationResp.description),
|
|
526
671
|
Response(notFoundResp.status, notFoundResp.description),
|
|
527
672
|
__param(0, Path()),
|
|
528
673
|
__param(1, Path())
|
|
529
674
|
], PoolController.prototype, "putPoolTag", null);
|
|
530
675
|
__decorate([
|
|
531
676
|
Delete('{id}/tags/{tag}'),
|
|
677
|
+
Middlewares(acl({ resource: 'pool', action: 'update:tags', objectId: 'params.id' })),
|
|
532
678
|
SuccessResponse(noContentResp.status, noContentResp.description),
|
|
679
|
+
Response(forbiddenOperationResp.status, forbiddenOperationResp.description),
|
|
533
680
|
Response(notFoundResp.status, notFoundResp.description),
|
|
534
681
|
__param(0, Path()),
|
|
535
682
|
__param(1, Path())
|
|
@@ -538,6 +685,7 @@ __decorate([
|
|
|
538
685
|
Example(taskIds),
|
|
539
686
|
Example(partialTasks),
|
|
540
687
|
Get('{id}/tasks'),
|
|
688
|
+
Security('*', ['acl']),
|
|
541
689
|
Tags('tasks'),
|
|
542
690
|
Response(notFoundResp.status, notFoundResp.description),
|
|
543
691
|
__param(0, Request()),
|
|
@@ -545,7 +693,8 @@ __decorate([
|
|
|
545
693
|
__param(2, Query()),
|
|
546
694
|
__param(3, Query()),
|
|
547
695
|
__param(4, Query()),
|
|
548
|
-
__param(5, Query())
|
|
696
|
+
__param(5, Query()),
|
|
697
|
+
__param(6, Query())
|
|
549
698
|
], PoolController.prototype, "getPoolTasks", null);
|
|
550
699
|
__decorate([
|
|
551
700
|
Example(taskLocation),
|
|
@@ -7,10 +7,11 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
8
8
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
9
9
|
};
|
|
10
|
-
import { Example, Get, Path, Query, Request, Response, Route, Security, Tags } from 'tsoa';
|
|
10
|
+
import { Example, Get, Middlewares, Path, Query, Request, Response, Route, Security, Tags } from 'tsoa';
|
|
11
11
|
import { inject } from 'inversify';
|
|
12
12
|
import { provide } from 'inversify-binding-decorators';
|
|
13
|
-
import {
|
|
13
|
+
import { acl } from '../middlewares/acl.middleware.mjs';
|
|
14
|
+
import { badRequestResp, forbiddenOperationResp, notFoundResp, unauthorizedResp, } from '../open-api/common/response.common.mjs';
|
|
14
15
|
import { partialProxies, proxy, proxyIds } from '../open-api/oa-examples/proxy.oa-example.mjs';
|
|
15
16
|
import { XoController } from '../abstract-classes/xo-controller.mjs';
|
|
16
17
|
import { RestApi } from '../rest-api/rest-api.mjs';
|
|
@@ -25,15 +26,24 @@ let ProxyController = class ProxyController extends XoController {
|
|
|
25
26
|
return this.restApi.xoApp.getProxy(id);
|
|
26
27
|
}
|
|
27
28
|
/**
|
|
29
|
+
* Returns all proxies that match the following privilege:
|
|
30
|
+
* - resource: proxy, action: read
|
|
31
|
+
*
|
|
28
32
|
* @example fields "vmUuid,id,name"
|
|
29
33
|
* @example filter "vmUuid?"
|
|
30
34
|
* @example limit 42
|
|
31
35
|
*/
|
|
32
|
-
async getProxies(req, fields, ndjson, filter, limit) {
|
|
33
|
-
const proxies = Object.values(await this.getObjects({ filter
|
|
34
|
-
return this.sendObjects(proxies, req
|
|
36
|
+
async getProxies(req, fields, ndjson, markdown, filter, limit) {
|
|
37
|
+
const proxies = Object.values(await this.getObjects({ filter }));
|
|
38
|
+
return this.sendObjects(proxies, req, {
|
|
39
|
+
limit,
|
|
40
|
+
privilege: { action: 'read', resource: 'proxy' },
|
|
41
|
+
});
|
|
35
42
|
}
|
|
36
43
|
/**
|
|
44
|
+
* Required privilege:
|
|
45
|
+
* - resource: proxy, action: read
|
|
46
|
+
*
|
|
37
47
|
* @example id "e625ea0c-a876-405a-b838-109d762efe88"
|
|
38
48
|
*/
|
|
39
49
|
getProxy(id) {
|
|
@@ -44,15 +54,24 @@ __decorate([
|
|
|
44
54
|
Example(proxyIds),
|
|
45
55
|
Example(partialProxies),
|
|
46
56
|
Get(''),
|
|
57
|
+
Security('*', ['acl']),
|
|
47
58
|
__param(0, Request()),
|
|
48
59
|
__param(1, Query()),
|
|
49
60
|
__param(2, Query()),
|
|
50
61
|
__param(3, Query()),
|
|
51
|
-
__param(4, Query())
|
|
62
|
+
__param(4, Query()),
|
|
63
|
+
__param(5, Query())
|
|
52
64
|
], ProxyController.prototype, "getProxies", null);
|
|
53
65
|
__decorate([
|
|
54
66
|
Example(proxy),
|
|
55
67
|
Get('{id}'),
|
|
68
|
+
Middlewares(acl({
|
|
69
|
+
resource: 'proxy',
|
|
70
|
+
action: 'read',
|
|
71
|
+
objectId: 'params.id',
|
|
72
|
+
getObject: ({ restApi }) => restApi.xoApp.getProxy,
|
|
73
|
+
})),
|
|
74
|
+
Response(forbiddenOperationResp.status, forbiddenOperationResp.description),
|
|
56
75
|
Response(notFoundResp.status, notFoundResp.description),
|
|
57
76
|
__param(0, Path())
|
|
58
77
|
], ProxyController.prototype, "getProxy", null);
|
|
@@ -10,11 +10,11 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
10
10
|
import { createLogger } from '@xen-orchestra/log';
|
|
11
11
|
import { Deprecated, Example, Get, Middlewares, Path, Query, Request, Response, Route, Security, Tags } from 'tsoa';
|
|
12
12
|
import { inject } from 'inversify';
|
|
13
|
-
import { noSuchObject } from 'xo-common/api-errors.js';
|
|
14
13
|
import { provide } from 'inversify-binding-decorators';
|
|
14
|
+
import { acl, autoBindService } from '../middlewares/acl.middleware.mjs';
|
|
15
15
|
import { BackupLogService } from '../backup-logs/backup-log.service.mjs';
|
|
16
16
|
import { RestApi } from '../rest-api/rest-api.mjs';
|
|
17
|
-
import { badRequestResp, unauthorizedResp } from '../open-api/common/response.common.mjs';
|
|
17
|
+
import { badRequestResp, forbiddenOperationResp, notFoundResp, unauthorizedResp, } from '../open-api/common/response.common.mjs';
|
|
18
18
|
import { XoController } from '../abstract-classes/xo-controller.mjs';
|
|
19
19
|
import { partialRestoreLogs, restoreLog, restoreLogIds } from '../open-api/oa-examples/restore-log.oa-example.mjs';
|
|
20
20
|
const log = createLogger('xo:rest-api:restoreLog-controller');
|
|
@@ -28,24 +28,29 @@ let RestoreLogController = class RestoreLogController extends XoController {
|
|
|
28
28
|
const filter = log => !this.#backupLogService.isBackupLog(log);
|
|
29
29
|
return this.restApi.xoApp.getBackupNgLogsSorted({ filter });
|
|
30
30
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (this.#backupLogService.isBackupLog(log)) {
|
|
34
|
-
throw noSuchObject('restore-log');
|
|
35
|
-
}
|
|
36
|
-
return log;
|
|
31
|
+
getCollectionObject(id) {
|
|
32
|
+
return this.#backupLogService.getRestoreLog(id);
|
|
37
33
|
}
|
|
38
34
|
/**
|
|
35
|
+
* Returns all restore logs that match the following privilege:
|
|
36
|
+
* - resource: restore-log, action: read
|
|
37
|
+
*
|
|
39
38
|
* @example fields "jobName,status,data"
|
|
40
39
|
* @example filter "status:success"
|
|
41
40
|
* @example limit 42
|
|
42
41
|
*/
|
|
43
|
-
async getRestoreLogs(req, fields, ndjson, filter, limit) {
|
|
44
|
-
const restoreLogs = await this.getObjects({ filter
|
|
45
|
-
return this.sendObjects(Object.values(restoreLogs), req
|
|
42
|
+
async getRestoreLogs(req, fields, ndjson, markdown, filter, limit) {
|
|
43
|
+
const restoreLogs = await this.getObjects({ filter });
|
|
44
|
+
return this.sendObjects(Object.values(restoreLogs), req, {
|
|
45
|
+
limit,
|
|
46
|
+
privilege: { action: 'read', resource: 'restore-log' },
|
|
47
|
+
});
|
|
46
48
|
}
|
|
47
49
|
/**
|
|
48
|
-
*
|
|
50
|
+
* Required privilege:
|
|
51
|
+
* - resource: restore-log, action: read
|
|
52
|
+
*
|
|
53
|
+
* @example id "1758180544428"
|
|
49
54
|
*/
|
|
50
55
|
getRestoreLog(id) {
|
|
51
56
|
return this.getObject(id);
|
|
@@ -55,15 +60,25 @@ __decorate([
|
|
|
55
60
|
Example(restoreLogIds),
|
|
56
61
|
Example(partialRestoreLogs),
|
|
57
62
|
Get(''),
|
|
63
|
+
Security('*', ['acl']),
|
|
58
64
|
__param(0, Request()),
|
|
59
65
|
__param(1, Query()),
|
|
60
66
|
__param(2, Query()),
|
|
61
67
|
__param(3, Query()),
|
|
62
|
-
__param(4, Query())
|
|
68
|
+
__param(4, Query()),
|
|
69
|
+
__param(5, Query())
|
|
63
70
|
], RestoreLogController.prototype, "getRestoreLogs", null);
|
|
64
71
|
__decorate([
|
|
65
72
|
Example(restoreLog),
|
|
66
73
|
Get('{id}'),
|
|
74
|
+
Middlewares(acl({
|
|
75
|
+
resource: 'restore-log',
|
|
76
|
+
action: 'read',
|
|
77
|
+
objectId: 'params.id',
|
|
78
|
+
getObject: autoBindService(BackupLogService, 'getRestoreLog'),
|
|
79
|
+
})),
|
|
80
|
+
Response(forbiddenOperationResp.status, forbiddenOperationResp.description),
|
|
81
|
+
Response(notFoundResp.status, notFoundResp.description),
|
|
67
82
|
__param(0, Path())
|
|
68
83
|
], RestoreLogController.prototype, "getRestoreLog", null);
|
|
69
84
|
RestoreLogController = __decorate([
|
|
@@ -88,21 +103,24 @@ let DeprecatedRestoreController = class DeprecatedRestoreController extends XoCo
|
|
|
88
103
|
const filter = log => !this.#backupLogService.isBackupLog(log);
|
|
89
104
|
return this.restApi.xoApp.getBackupNgLogsSorted({ filter });
|
|
90
105
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if (this.#backupLogService.isBackupLog(log)) {
|
|
94
|
-
throw noSuchObject('restore-log');
|
|
95
|
-
}
|
|
96
|
-
return log;
|
|
106
|
+
getCollectionObject(id) {
|
|
107
|
+
return this.#backupLogService.getRestoreLog(id);
|
|
97
108
|
}
|
|
98
109
|
/**
|
|
110
|
+
* Returns all restore logs that match the following privilege:
|
|
111
|
+
* - resource: restore-log, action: read
|
|
112
|
+
*
|
|
99
113
|
* @example fields "jobName,status,data"
|
|
100
114
|
* @example filter "status:success"
|
|
101
115
|
* @example limit 42
|
|
102
116
|
*/
|
|
103
|
-
async getDeprecatedRestoreLogs(req, fields, ndjson, filter, limit) {
|
|
104
|
-
const restoreLogs = await this.getObjects({ filter
|
|
105
|
-
return this.sendObjects(Object.values(restoreLogs), req,
|
|
117
|
+
async getDeprecatedRestoreLogs(req, fields, ndjson, markdown, filter, limit) {
|
|
118
|
+
const restoreLogs = await this.getObjects({ filter });
|
|
119
|
+
return this.sendObjects(Object.values(restoreLogs), req, {
|
|
120
|
+
path: 'restore-logs',
|
|
121
|
+
limit,
|
|
122
|
+
privilege: { action: 'read', resource: 'restore-log' },
|
|
123
|
+
});
|
|
106
124
|
}
|
|
107
125
|
/**
|
|
108
126
|
* @example id "1758180544428"
|
|
@@ -120,7 +138,8 @@ __decorate([
|
|
|
120
138
|
__param(1, Query()),
|
|
121
139
|
__param(2, Query()),
|
|
122
140
|
__param(3, Query()),
|
|
123
|
-
__param(4, Query())
|
|
141
|
+
__param(4, Query()),
|
|
142
|
+
__param(5, Query())
|
|
124
143
|
], DeprecatedRestoreController.prototype, "getDeprecatedRestoreLogs", null);
|
|
125
144
|
__decorate([
|
|
126
145
|
Example(restoreLog),
|