@xen-orchestra/rest-api 0.15.0 → 0.17.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.
Files changed (36) hide show
  1. package/dist/abstract-classes/base-controller.mjs +4 -2
  2. package/dist/abstract-classes/xapi-xo-controller.mjs +2 -6
  3. package/dist/alarms/alarm.service.mjs +2 -1
  4. package/dist/backup-jobs/backup-job.controller.mjs +284 -0
  5. package/dist/backup-jobs/backup-job.service.mjs +25 -0
  6. package/dist/backup-jobs/backup-job.type.mjs +1 -0
  7. package/dist/backup-logs/backup-log.controller.mjs +75 -0
  8. package/dist/backup-logs/backup-log.service.mjs +5 -0
  9. package/dist/groups/group.controller.mjs +37 -1
  10. package/dist/ioc/ioc.mjs +36 -0
  11. package/dist/open-api/common/response.common.mjs +4 -0
  12. package/dist/open-api/oa-examples/backup-job.oa-example.mjs +128 -0
  13. package/dist/open-api/oa-examples/backup-log.oa-example.mjs +93 -0
  14. package/dist/open-api/oa-examples/proxy.oa-example.mjs +25 -0
  15. package/dist/open-api/oa-examples/restore-log.oa-example.mjs +53 -0
  16. package/dist/open-api/oa-examples/user.oa-example.mjs +32 -0
  17. package/dist/open-api/oa-examples/vdi.oa-example.mjs +3 -0
  18. package/dist/open-api/routes/routes.js +2083 -609
  19. package/dist/proxies/proxy.controller.mjs +61 -0
  20. package/dist/rest-api/rest-api.mjs +6 -2
  21. package/dist/restore-logs/restore-log.controller.mjs +144 -0
  22. package/dist/srs/sr.controller.mjs +39 -2
  23. package/dist/tasks/task.controller.mjs +49 -3
  24. package/dist/tasks/task.service.mjs +24 -0
  25. package/dist/users/user.controller.mjs +91 -12
  26. package/dist/users/user.service.mjs +21 -0
  27. package/dist/vdi-snapshots/vdi-snapshot.controller.mjs +46 -4
  28. package/dist/vdis/vdi.controller.mjs +43 -4
  29. package/dist/vdis/vdi.service.mjs +21 -0
  30. package/dist/vm-snapshots/vm-snapshot.controller.mjs +72 -3
  31. package/dist/vm-templates/vm-template.controller.mjs +72 -3
  32. package/dist/vms/vm.controller.mjs +135 -5
  33. package/dist/vms/vm.service.mjs +18 -0
  34. package/open-api/spec/swagger.json +8469 -4048
  35. package/package.json +4 -4
  36. package/tsoa.json +15 -0
@@ -53,8 +53,10 @@ export class BaseController extends Controller {
53
53
  }
54
54
  maybeCompressResponse(req, res) {
55
55
  let transform;
56
- let acceptEncoding = req.headers['accept-encoding'];
57
- acceptEncoding = Array.isArray(acceptEncoding) ? acceptEncoding : acceptEncoding?.split(',');
56
+ const _acceptEncoding = req.headers['accept-encoding'];
57
+ const acceptEncoding = Array.isArray(_acceptEncoding)
58
+ ? _acceptEncoding
59
+ : _acceptEncoding?.split(',');
58
60
  if (acceptEncoding !== undefined &&
59
61
  acceptEncoding.some(encoding => {
60
62
  const value = encoding.split(';')[0].trim().toLowerCase();
@@ -1,4 +1,3 @@
1
- import * as CM from 'complex-matcher';
2
1
  import { BaseController } from './base-controller.mjs';
3
2
  export class XapiXoController extends BaseController {
4
3
  #type;
@@ -6,11 +5,8 @@ export class XapiXoController extends BaseController {
6
5
  super(restApi);
7
6
  this.#type = type;
8
7
  }
9
- getObjects({ filter, limit } = {}) {
10
- if (filter !== undefined && typeof filter === 'string') {
11
- filter = CM.parse(filter).createPredicate();
12
- }
13
- return this.restApi.getObjectsByType(this.#type, { filter: filter, limit });
8
+ getObjects(opts) {
9
+ return this.restApi.getObjectsByType(this.#type, opts);
14
10
  }
15
11
  getObject(id) {
16
12
  return this.restApi.getObject(id, this.#type);
@@ -3,7 +3,8 @@ import { BASE_URL } from '../index.mjs';
3
3
  // E.g: 'value: 0.6\nconfig:\n<variable>\n<name value="cpu_usage"/>\n<alarm_trigger_level value="0.4"/>\n<alarm_trigger_period value ="60"/>\n</variable>';
4
4
  const ALARM_BODY_REGEX = /^value:\s*(Infinity|NaN|-Infinity|\d+(?:\.\d+)?)\s*config:\s*<variable>\s*<name value="(.*?)"/;
5
5
  const ALARM_NAMES = ['ALARM', 'BOND_STATUS_CHANGED', 'MULTIPATH_PERIODIC_ALERT'];
6
- export const alarmPredicate = CM.parse(`name:|(${ALARM_NAMES.join(' ')})`).createPredicate();
6
+ export const RAW_ALARM_FILTER = `name:|(${ALARM_NAMES.join(' ')})`;
7
+ export const alarmPredicate = CM.parse(RAW_ALARM_FILTER).createPredicate();
7
8
  export class AlarmService {
8
9
  #restApi;
9
10
  constructor(restApi) {
@@ -0,0 +1,284 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
8
+ return function (target, key) { decorator(target, key, paramIndex); }
9
+ };
10
+ import * as CM from 'complex-matcher';
11
+ import { createLogger } from '@xen-orchestra/log';
12
+ import { inject } from 'inversify';
13
+ import { noSuchObject } from 'xo-common/api-errors.js';
14
+ import { Deprecated, Example, Get, Hidden, Middlewares, Path, Query, Request, Response, Route, Security, Tags, } from 'tsoa';
15
+ import { provide } from 'inversify-binding-decorators';
16
+ import { backupLog, backupLogIds, partialBackupLogs } from '../open-api/oa-examples/backup-log.oa-example.mjs';
17
+ import { BackupLogService } from '../backup-logs/backup-log.service.mjs';
18
+ import { notFoundResp, unauthorizedResp } from '../open-api/common/response.common.mjs';
19
+ import { RestApi } from '../rest-api/rest-api.mjs';
20
+ import { limitAndFilterArray } from '../helpers/utils.helper.mjs';
21
+ import { XoController } from '../abstract-classes/xo-controller.mjs';
22
+ import { metadataBackupJob, metadataBackupJobIds, mirrorBackupJob, mirrorBackupJobIds, partialMetadataBackupJobs, partialMirrorBackupJobs, partialVmBackupJobs, vmBackupJob, vmBackupJobIds, } from '../open-api/oa-examples/backup-job.oa-example.mjs';
23
+ import { BASE_URL } from '../index.mjs';
24
+ const log = createLogger('xo:rest-api:backupJob-controller');
25
+ let BackupJobController = class BackupJobController extends XoController {
26
+ async getAllCollectionObjects() {
27
+ const allJobs = await this.restApi.xoApp.getAllJobs();
28
+ const backupJobs = allJobs.filter(job => 'type' in job);
29
+ return backupJobs;
30
+ }
31
+ async getCollectionObject(id) {
32
+ const job = await this.restApi.xoApp.getJob(id);
33
+ if (!('type' in job)) {
34
+ // not a backup job
35
+ throw noSuchObject(id, 'backup-job');
36
+ }
37
+ return job;
38
+ }
39
+ /**
40
+ *
41
+ * @example fields "name,mode,type,id"
42
+ * @example filter "type:backup"
43
+ * @example limit 42
44
+ */
45
+ async getBackupJobs(req, fields, ndjson, filter, limit) {
46
+ const backupJobs = await this.getObjects({ filter, limit });
47
+ return this.sendObjects(Object.values(backupJobs), req, 'backup-jobs');
48
+ }
49
+ /**
50
+ * @example id "d33f3dc1-92b4-469c-ad58-4c2a106a4721"
51
+ */
52
+ getBackupJob(id) {
53
+ return this.getObject(id);
54
+ }
55
+ };
56
+ __decorate([
57
+ Example(vmBackupJobIds),
58
+ Example(partialVmBackupJobs),
59
+ Get(''),
60
+ __param(0, Request()),
61
+ __param(1, Query()),
62
+ __param(2, Query()),
63
+ __param(3, Query()),
64
+ __param(4, Query())
65
+ ], BackupJobController.prototype, "getBackupJobs", null);
66
+ __decorate([
67
+ Example(vmBackupJob),
68
+ Response(notFoundResp.status, notFoundResp.description),
69
+ Get('{id}'),
70
+ __param(0, Path())
71
+ ], BackupJobController.prototype, "getBackupJob", null);
72
+ BackupJobController = __decorate([
73
+ Route('backup-jobs'),
74
+ Security('*'),
75
+ Response(unauthorizedResp.status, unauthorizedResp.description),
76
+ Tags('backup-jobs'),
77
+ provide(BackupJobController)
78
+ ], BackupJobController);
79
+ export { BackupJobController };
80
+ // ----------- DEPRECATED TO BE REMOVED IN ONE YEAR (09-12-2026)--------------------
81
+ let DeprecatedBackupController = class DeprecatedBackupController extends XoController {
82
+ #backupLogService;
83
+ constructor(restApi, backupLogService) {
84
+ super(restApi);
85
+ this.#backupLogService = backupLogService;
86
+ }
87
+ async getAllCollectionObjects() {
88
+ const backupJobs = await this.restApi.xoApp.getAllJobs();
89
+ return backupJobs.filter(job => 'type' in job);
90
+ }
91
+ async getCollectionObject(id) {
92
+ const backupJob = await this.restApi.xoApp.getJob(id);
93
+ if (!('type' in backupJob)) {
94
+ throw noSuchObject(id, 'backup-job');
95
+ }
96
+ return backupJob;
97
+ }
98
+ async getObject(id, type) {
99
+ const backupJob = await super.getObject(id);
100
+ if (backupJob.type !== type) {
101
+ throw noSuchObject(id, type);
102
+ }
103
+ return backupJob;
104
+ }
105
+ /**
106
+ *
107
+ * @example fields "name,mode,id"
108
+ * @example filter "mode:delta"
109
+ * @example limit 42
110
+ */
111
+ async getVmBackupJobs(req, fields, ndjson, filter, limit) {
112
+ const vmBackupJobs = await this.restApi.xoApp.getAllJobs('backup');
113
+ return this.sendObjects(limitAndFilterArray(vmBackupJobs, { filter, limit }), req, 'backup-jobs');
114
+ }
115
+ // For compatibility, redirect /backup/jobs/:id to /backup/jobs/vm/:id
116
+ async redirectToVmBackupJob(req, id) {
117
+ const res = req.res;
118
+ res.redirect(308, BASE_URL + '/backup/jobs/vm/' + id);
119
+ }
120
+ /**
121
+ * @example id "d33f3dc1-92b4-469c-ad58-4c2a106a4721"
122
+ */
123
+ getVmBackupJob(id) {
124
+ return this.getObject(id, 'backup');
125
+ }
126
+ /**
127
+ *
128
+ * @example fields "name,xoMetadata,id"
129
+ * @example filter "xoMetadata?"
130
+ * @example limit 42
131
+ */
132
+ async getMetadataBackupJobs(req, fields, ndjson, filter, limit) {
133
+ const metadataBackupJobs = await this.restApi.xoApp.getAllJobs('metadataBackup');
134
+ return this.sendObjects(limitAndFilterArray(metadataBackupJobs, { filter, limit }), req, 'backup-jobs');
135
+ }
136
+ /**
137
+ * @example id "b50f95fd-f6b7-4027-87b6-6a02c7dcd5f5"
138
+ */
139
+ getMetadataBackupJob(id) {
140
+ return this.getObject(id, 'metadataBackup');
141
+ }
142
+ /**
143
+ *
144
+ * @example fields "name,mode,id"
145
+ * @example filter "mode:delta"
146
+ * @example limit 42
147
+ */
148
+ async getMirrorBackupJobs(req, fields, ndjson, filter, limit) {
149
+ const mirrorBackupJobs = await this.restApi.xoApp.getAllJobs('mirrorBackup');
150
+ return this.sendObjects(limitAndFilterArray(mirrorBackupJobs, { filter, limit }), req, 'backup-jobs');
151
+ }
152
+ /**
153
+ * @example id "e680c14c-ab52-45c8-bb0e-bd4ca12ea8f9"
154
+ */
155
+ getMirrorBackupJob(id) {
156
+ return this.getObject(id, 'mirrorBackup');
157
+ }
158
+ /**
159
+ * @example fields "jobName,status,data"
160
+ * @example filter "status:success"
161
+ * @example limit 42
162
+ */
163
+ async getDeprecatedBackupLogs(req, fields, ndjson, filter, limit) {
164
+ const userFilter = filter === undefined ? () => true : CM.parse(filter).createPredicate();
165
+ const predicate = (log) => {
166
+ if (!this.#backupLogService.isBackupLog(log)) {
167
+ return false;
168
+ }
169
+ return userFilter(log);
170
+ };
171
+ const logs = (await this.restApi.xoApp.getBackupNgLogsSorted({ filter: predicate, limit }));
172
+ return this.sendObjects(logs, req, 'backup-logs');
173
+ }
174
+ /**
175
+ * @example id "1753776067468"
176
+ */
177
+ async getDeprecatedBackupLog(id) {
178
+ const log = await this.restApi.xoApp.getBackupNgLogs(id);
179
+ if (!this.#backupLogService.isBackupLog(log)) {
180
+ throw noSuchObject('backup-log');
181
+ }
182
+ return log;
183
+ }
184
+ };
185
+ __decorate([
186
+ Example(vmBackupJobIds),
187
+ Example(partialVmBackupJobs),
188
+ Deprecated(),
189
+ Get('jobs/vm'),
190
+ Tags('backup-jobs'),
191
+ __param(0, Request()),
192
+ __param(1, Query()),
193
+ __param(2, Query()),
194
+ __param(3, Query()),
195
+ __param(4, Query())
196
+ ], DeprecatedBackupController.prototype, "getVmBackupJobs", null);
197
+ __decorate([
198
+ Hidden(),
199
+ Get('jobs/{id}'),
200
+ Tags('backup-jobs'),
201
+ __param(0, Request()),
202
+ __param(1, Path())
203
+ ], DeprecatedBackupController.prototype, "redirectToVmBackupJob", null);
204
+ __decorate([
205
+ Example(vmBackupJob),
206
+ Deprecated(),
207
+ Response(notFoundResp.status, notFoundResp.description),
208
+ Get('jobs/vm/{id}'),
209
+ Tags('backup-jobs'),
210
+ __param(0, Path())
211
+ ], DeprecatedBackupController.prototype, "getVmBackupJob", null);
212
+ __decorate([
213
+ Example(metadataBackupJobIds),
214
+ Example(partialMetadataBackupJobs),
215
+ Deprecated(),
216
+ Get('jobs/metadata'),
217
+ Tags('backup-jobs'),
218
+ __param(0, Request()),
219
+ __param(1, Query()),
220
+ __param(2, Query()),
221
+ __param(3, Query()),
222
+ __param(4, Query())
223
+ ], DeprecatedBackupController.prototype, "getMetadataBackupJobs", null);
224
+ __decorate([
225
+ Example(metadataBackupJob),
226
+ Deprecated(),
227
+ Response(notFoundResp.status, notFoundResp.description),
228
+ Get('jobs/metadata/{id}'),
229
+ Tags('backup-jobs'),
230
+ __param(0, Path())
231
+ ], DeprecatedBackupController.prototype, "getMetadataBackupJob", null);
232
+ __decorate([
233
+ Example(mirrorBackupJobIds),
234
+ Example(partialMirrorBackupJobs),
235
+ Deprecated(),
236
+ Get('jobs/mirror'),
237
+ Tags('backup-jobs'),
238
+ __param(0, Request()),
239
+ __param(1, Query()),
240
+ __param(2, Query()),
241
+ __param(3, Query()),
242
+ __param(4, Query())
243
+ ], DeprecatedBackupController.prototype, "getMirrorBackupJobs", null);
244
+ __decorate([
245
+ Example(mirrorBackupJob),
246
+ Deprecated(),
247
+ Response(notFoundResp.status, notFoundResp.description),
248
+ Get('jobs/mirror/{id}'),
249
+ Tags('backup-jobs'),
250
+ __param(0, Path())
251
+ ], DeprecatedBackupController.prototype, "getMirrorBackupJob", null);
252
+ __decorate([
253
+ Example(backupLogIds),
254
+ Example(partialBackupLogs),
255
+ Deprecated(),
256
+ Get('logs'),
257
+ Tags('backup-logs'),
258
+ __param(0, Request()),
259
+ __param(1, Query()),
260
+ __param(2, Query()),
261
+ __param(3, Query()),
262
+ __param(4, Query())
263
+ ], DeprecatedBackupController.prototype, "getDeprecatedBackupLogs", null);
264
+ __decorate([
265
+ Example(backupLog),
266
+ Deprecated(),
267
+ Get('logs/{id}'),
268
+ Tags('backup-logs'),
269
+ __param(0, Path())
270
+ ], DeprecatedBackupController.prototype, "getDeprecatedBackupLog", null);
271
+ DeprecatedBackupController = __decorate([
272
+ Route('backup'),
273
+ Security('*'),
274
+ Response(unauthorizedResp.status, unauthorizedResp.description),
275
+ Middlewares((_req, _res, next) => {
276
+ log.warn('You are calling a deprecated route. It will be removed in the futur. Please use `/rest/v0/backup-jobs` or `/rest/v0/backup-logs` instead');
277
+ next();
278
+ }),
279
+ provide(DeprecatedBackupController),
280
+ __param(0, inject(RestApi)),
281
+ __param(1, inject(BackupLogService))
282
+ ], DeprecatedBackupController);
283
+ export { DeprecatedBackupController };
284
+ // ----------- DEPRECATED TO BE REMOVED IN ONE YEAR (09-12-2026)--------------------
@@ -0,0 +1,25 @@
1
+ import { createPredicate } from 'value-matcher';
2
+ import { extractIdsFromSimplePattern } from '@xen-orchestra/backups/extractIdsFromSimplePattern.mjs';
3
+ const NO_BAK_TAG = 'xo:no-bak';
4
+ export class BackupJobService {
5
+ #restApi;
6
+ constructor(restApi) {
7
+ this.#restApi = restApi;
8
+ }
9
+ async isVmInBackupJob(backupJobId, vmId) {
10
+ const backupJob = await this.#restApi.xoApp.getJob(backupJobId);
11
+ const vm = this.#restApi.getObject(vmId, 'VM');
12
+ if (vm.tags.includes(NO_BAK_TAG)) {
13
+ return false;
14
+ }
15
+ try {
16
+ const vmIds = extractIdsFromSimplePattern(backupJob.vms);
17
+ return vmIds.some(id => id === vm.id);
18
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
19
+ }
20
+ catch (_) {
21
+ const predicate = createPredicate(backupJob.vms);
22
+ return predicate(vm);
23
+ }
24
+ }
25
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,75 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
8
+ return function (target, key) { decorator(target, key, paramIndex); }
9
+ };
10
+ import { Example, Get, Path, Query, Request, Response, Route, Security, Tags } from 'tsoa';
11
+ import { inject } from 'inversify';
12
+ import { noSuchObject } from 'xo-common/api-errors.js';
13
+ import { provide } from 'inversify-binding-decorators';
14
+ import { backupLog, backupLogIds, partialBackupLogs } from '../open-api/oa-examples/backup-log.oa-example.mjs';
15
+ import { BackupLogService } from './backup-log.service.mjs';
16
+ import { RestApi } from '../rest-api/rest-api.mjs';
17
+ import { unauthorizedResp } from '../open-api/common/response.common.mjs';
18
+ import { XoController } from '../abstract-classes/xo-controller.mjs';
19
+ let BackupLogController = class BackupLogController extends XoController {
20
+ #backupLogService;
21
+ constructor(restApi, backupLogService) {
22
+ super(restApi);
23
+ this.#backupLogService = backupLogService;
24
+ }
25
+ getAllCollectionObjects() {
26
+ return this.restApi.xoApp.getBackupNgLogsSorted({ filter: this.#backupLogService.isBackupLog });
27
+ }
28
+ async getCollectionObject(id) {
29
+ const log = await this.restApi.xoApp.getBackupNgLogs(id);
30
+ if (!this.#backupLogService.isBackupLog(log)) {
31
+ throw noSuchObject('backup-log');
32
+ }
33
+ return log;
34
+ }
35
+ /**
36
+ * @example fields "jobName,status,data"
37
+ * @example filter "status:success"
38
+ * @example limit 42
39
+ */
40
+ async getBackupLogs(req, fields, ndjson, filter, limit) {
41
+ const backupLogs = await this.getObjects({ filter, limit });
42
+ return this.sendObjects(Object.values(backupLogs), req);
43
+ }
44
+ /**
45
+ * @example id "1753776067468"
46
+ */
47
+ getBackupLog(id) {
48
+ return this.getObject(id);
49
+ }
50
+ };
51
+ __decorate([
52
+ Example(backupLogIds),
53
+ Example(partialBackupLogs),
54
+ Get(''),
55
+ __param(0, Request()),
56
+ __param(1, Query()),
57
+ __param(2, Query()),
58
+ __param(3, Query()),
59
+ __param(4, Query())
60
+ ], BackupLogController.prototype, "getBackupLogs", null);
61
+ __decorate([
62
+ Example(backupLog),
63
+ Get('{id}'),
64
+ __param(0, Path())
65
+ ], BackupLogController.prototype, "getBackupLog", null);
66
+ BackupLogController = __decorate([
67
+ Route('backup-logs'),
68
+ Security('*'),
69
+ Response(unauthorizedResp.status, unauthorizedResp.description),
70
+ Tags('backup-logs'),
71
+ provide(BackupLogController),
72
+ __param(0, inject(RestApi)),
73
+ __param(1, inject(BackupLogService))
74
+ ], BackupLogController);
75
+ export { BackupLogController };
@@ -0,0 +1,5 @@
1
+ export class BackupLogService {
2
+ isBackupLog(log) {
3
+ return log.message === 'backup' || log.message === 'metadata';
4
+ }
5
+ }
@@ -8,13 +8,23 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
8
8
  return function (target, key) { decorator(target, key, paramIndex); }
9
9
  };
10
10
  import { Body, Delete, Example, Get, Middlewares, Patch, Path, Post, Put, Query, Request, Response, Route, Security, SuccessResponse, Tags, } from 'tsoa';
11
+ import { inject } from 'inversify';
11
12
  import { json } from 'express';
12
13
  import { provide } from 'inversify-binding-decorators';
13
14
  import { forbiddenOperation } from 'xo-common/api-errors.js';
14
15
  import { createdResp, forbiddenOperationResp, invalidParameters, noContentResp, notFoundResp, resourceAlreadyExists, unauthorizedResp, } from '../open-api/common/response.common.mjs';
15
16
  import { group, groupId, groupIds, partialGroups } from '../open-api/oa-examples/group.oa-example.mjs';
16
17
  import { XoController } from '../abstract-classes/xo-controller.mjs';
18
+ import { UserService } from '../users/user.service.mjs';
19
+ import { RestApi } from '../rest-api/rest-api.mjs';
20
+ import { limitAndFilterArray } from '../helpers/utils.helper.mjs';
21
+ import { partialUsers, userIds } from '../open-api/oa-examples/user.oa-example.mjs';
17
22
  let GroupController = class GroupController extends XoController {
23
+ #userService;
24
+ constructor(restApi, userService) {
25
+ super(restApi);
26
+ this.#userService = userService;
27
+ }
18
28
  // --- abstract methods
19
29
  getAllCollectionObjects() {
20
30
  return this.restApi.xoApp.getAllGroups();
@@ -85,6 +95,17 @@ let GroupController = class GroupController extends XoController {
85
95
  }
86
96
  await this.restApi.xoApp.addUserToGroup(userId, group.id);
87
97
  }
98
+ /**
99
+ * @example id "6c81b5e1-afc1-43ea-8f8d-939ceb5f3f90"
100
+ * @example fields "permission,name,id"
101
+ * @example filter "permission:none"
102
+ * @example limit 42
103
+ */
104
+ async getGroupUsers(req, id, fields, ndjson, filter, limit) {
105
+ const group = await this.getObject(id);
106
+ const users = await Promise.all(group.users.map(id => this.#userService.getUser(id)));
107
+ return this.sendObjects(limitAndFilterArray(users, { filter, limit }), req, 'users');
108
+ }
88
109
  };
89
110
  __decorate([
90
111
  Example(groupIds),
@@ -143,11 +164,26 @@ __decorate([
143
164
  __param(0, Path()),
144
165
  __param(1, Path())
145
166
  ], GroupController.prototype, "addUserToGroup", null);
167
+ __decorate([
168
+ Example(userIds),
169
+ Example(partialUsers),
170
+ Get('{id}/users'),
171
+ Tags('users'),
172
+ Response(notFoundResp.status, notFoundResp.description),
173
+ __param(0, Request()),
174
+ __param(1, Path()),
175
+ __param(2, Query()),
176
+ __param(3, Query()),
177
+ __param(4, Query()),
178
+ __param(5, Query())
179
+ ], GroupController.prototype, "getGroupUsers", null);
146
180
  GroupController = __decorate([
147
181
  Route('groups'),
148
182
  Security('*'),
149
183
  Response(unauthorizedResp.status, unauthorizedResp.description),
150
184
  Tags('groups'),
151
- provide(GroupController)
185
+ provide(GroupController),
186
+ __param(0, inject(RestApi)),
187
+ __param(1, inject(UserService))
152
188
  ], GroupController);
153
189
  export { GroupController };
package/dist/ioc/ioc.mjs CHANGED
@@ -7,6 +7,11 @@ import { XoaService } from '../xoa/xoa.service.mjs';
7
7
  import { HostService } from '../hosts/host.service.mjs';
8
8
  import { PoolService } from '../pools/pool.service.mjs';
9
9
  import { AlarmService } from '../alarms/alarm.service.mjs';
10
+ import { VdiService } from '../vdis/vdi.service.mjs';
11
+ import { TaskService } from '../tasks/task.service.mjs';
12
+ import { UserService } from '../users/user.service.mjs';
13
+ import { BackupJobService } from '../backup-jobs/backup-job.service.mjs';
14
+ import { BackupLogService } from '../backup-logs/backup-log.service.mjs';
10
15
  const iocContainer = new Container();
11
16
  decorate(injectable(), Controller);
12
17
  iocContainer.load(buildProviderModule());
@@ -53,5 +58,36 @@ export function setupContainer(xoApp) {
53
58
  return new AlarmService(restApi);
54
59
  })
55
60
  .inSingletonScope();
61
+ iocContainer.bind(TaskService).toDynamicValue(ctx => {
62
+ const restApi = ctx.container.get(RestApi);
63
+ return new TaskService(restApi);
64
+ });
65
+ iocContainer
66
+ .bind(VdiService)
67
+ .toDynamicValue(ctx => {
68
+ const restApi = ctx.container.get(RestApi);
69
+ return new VdiService(restApi);
70
+ })
71
+ .inSingletonScope();
72
+ iocContainer
73
+ .bind(UserService)
74
+ .toDynamicValue(ctx => {
75
+ const restApi = ctx.container.get(RestApi);
76
+ return new UserService(restApi);
77
+ })
78
+ .inSingletonScope();
79
+ iocContainer
80
+ .bind(BackupJobService)
81
+ .toDynamicValue(ctx => {
82
+ const restApi = ctx.container.get(RestApi);
83
+ return new BackupJobService(restApi);
84
+ })
85
+ .inSingletonScope();
86
+ iocContainer
87
+ .bind(BackupLogService)
88
+ .toDynamicValue(() => {
89
+ return new BackupLogService();
90
+ })
91
+ .inSingletonScope();
56
92
  }
57
93
  export { iocContainer };
@@ -43,3 +43,7 @@ export const badRequestResp = {
43
43
  status: 400,
44
44
  description: 'Bad request',
45
45
  };
46
+ export const incorrectStateResp = {
47
+ status: 409,
48
+ description: 'Incorrect state',
49
+ };