@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
|
@@ -0,0 +1,384 @@
|
|
|
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 { Body, Delete, Example, Get, Middlewares, Patch, Path, Post, Put, Query, Request, Response, Route, Security, SuccessResponse, Tags, } from 'tsoa';
|
|
11
|
+
import { provide } from 'inversify-binding-decorators';
|
|
12
|
+
import { json } from 'express';
|
|
13
|
+
import { acl, actionsFromBody } from '../middlewares/acl.middleware.mjs';
|
|
14
|
+
import { aclPrivilegeIds, partialAclPrivileges } from '../open-api/oa-examples/acl-privilege.oa-example.mjs';
|
|
15
|
+
import { aclRole, aclRoleIds, partialAclRoles } from '../open-api/oa-examples/acl-role.oa-example.mjs';
|
|
16
|
+
import { asynchronousActionResp, badRequestResp, createdResp, forbiddenOperationResp, invalidParameters, noContentResp, notFoundResp, resourceAlreadyExists, unauthorizedResp, } from '../open-api/common/response.common.mjs';
|
|
17
|
+
import { BASE_URL } from '../index.mjs';
|
|
18
|
+
import { limitAndFilterArray } from '../helpers/utils.helper.mjs';
|
|
19
|
+
import { taskLocation } from '../open-api/oa-examples/task.oa-example.mjs';
|
|
20
|
+
import { XoController } from '../abstract-classes/xo-controller.mjs';
|
|
21
|
+
import { entityId } from '../open-api/oa-examples/common.oa-example.mjs';
|
|
22
|
+
import { inject } from 'inversify';
|
|
23
|
+
import { RestApi } from '../rest-api/rest-api.mjs';
|
|
24
|
+
let AclRoleController = class AclRoleController extends XoController {
|
|
25
|
+
constructor(restApi) {
|
|
26
|
+
super('acl-role', restApi);
|
|
27
|
+
}
|
|
28
|
+
getAllCollectionObjects() {
|
|
29
|
+
return this.restApi.xoApp.getAclV2Roles();
|
|
30
|
+
}
|
|
31
|
+
getCollectionObject(id) {
|
|
32
|
+
return this.restApi.xoApp.getAclV2Role(id);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Returns all ACL roles that match the following privilege:
|
|
36
|
+
* - resource: acl-role, action: read
|
|
37
|
+
*
|
|
38
|
+
* @example fields "id,name,isTemplate"
|
|
39
|
+
* @example filter "name:read only"
|
|
40
|
+
* @example limit 42
|
|
41
|
+
*/
|
|
42
|
+
async getAclV2Roles(req, fields, ndjson, filter, limit) {
|
|
43
|
+
return this.sendObjects(Object.values(await this.getObjects({ filter })), req, {
|
|
44
|
+
limit,
|
|
45
|
+
privilege: { resource: 'acl-role', action: 'read' },
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Required privilege:
|
|
50
|
+
* - resource: acl-role, action: create
|
|
51
|
+
*
|
|
52
|
+
* @example body {
|
|
53
|
+
* "name": "VMs creator",
|
|
54
|
+
* "description": "Allow to create VMs"
|
|
55
|
+
* }
|
|
56
|
+
*/
|
|
57
|
+
async createAclV2Role(body) {
|
|
58
|
+
const newRole = await this.restApi.xoApp.createAclV2Role(body);
|
|
59
|
+
return { id: newRole.id };
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Required privilege:
|
|
63
|
+
* - resource: acl-role, action: read
|
|
64
|
+
*
|
|
65
|
+
* @example id "784bd959-08de-4b26-b575-92ded5aef872"
|
|
66
|
+
*/
|
|
67
|
+
getAclV2Role(id) {
|
|
68
|
+
return this.getObject(id);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Required privilege:
|
|
72
|
+
* - resource: acl-role, action: delete
|
|
73
|
+
*
|
|
74
|
+
* @example id "784bd959-08de-4b26-b575-92ded5aef872"
|
|
75
|
+
*/
|
|
76
|
+
async deleteAclV2Role(id) {
|
|
77
|
+
await this.restApi.xoApp.deleteAclV2Role(id);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Required privileges:
|
|
81
|
+
* - resource: acl-role, action: update (grants all fields)
|
|
82
|
+
* - resource: acl-role, action: update:name (if name is passed)
|
|
83
|
+
* - resource: acl-role, action: update:description (if description is passed)
|
|
84
|
+
*
|
|
85
|
+
* @example id "784bd959-08de-4b26-b575-92ded5aef872"
|
|
86
|
+
* @example body {
|
|
87
|
+
* "name": "VMs creator",
|
|
88
|
+
* "description": "Allow to create VMs"
|
|
89
|
+
* }
|
|
90
|
+
*/
|
|
91
|
+
async updateAclV2Role(id, body) {
|
|
92
|
+
await this.restApi.xoApp.updateAclV2Role(id, body);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Copy a role with all its privileges. Possibility to modify the name and description of the copied role.
|
|
96
|
+
*
|
|
97
|
+
* Required privileges:
|
|
98
|
+
* - resource: acl-role, action: create
|
|
99
|
+
* - resource: acl-privilege, action: create (if copied role has privileges)
|
|
100
|
+
*
|
|
101
|
+
* @example id "784bd959-08de-4b26-b575-92ded5aef872"
|
|
102
|
+
* @example body {"name": "Copied role"}
|
|
103
|
+
*/
|
|
104
|
+
copyAclV2Role(id, body, sync) {
|
|
105
|
+
const roleId = id;
|
|
106
|
+
const action = async () => {
|
|
107
|
+
const id = await this.restApi.xoApp.copyAclV2Role(roleId, body);
|
|
108
|
+
if (sync) {
|
|
109
|
+
this.setHeader('Location', `${BASE_URL}/acl-roles/${id}`);
|
|
110
|
+
}
|
|
111
|
+
return { id };
|
|
112
|
+
};
|
|
113
|
+
return this.createAction(action, {
|
|
114
|
+
sync,
|
|
115
|
+
statusCode: createdResp.status,
|
|
116
|
+
taskProperties: {
|
|
117
|
+
args: body,
|
|
118
|
+
name: 'copy role',
|
|
119
|
+
objectId: roleId,
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Returns all ACL privileges that match the following privilege:
|
|
125
|
+
* - resource: acl-privilege, action: read
|
|
126
|
+
*
|
|
127
|
+
* @example id "426622cc-b2db-4545-a2f0-6ec47b3a6450"
|
|
128
|
+
* @example fields "id,action,resource"
|
|
129
|
+
* @example filter "action:create"
|
|
130
|
+
* @example limit 42
|
|
131
|
+
*/
|
|
132
|
+
async getAclV2RolePrivileges(req, id, fields, ndjson, filter, limit) {
|
|
133
|
+
const privileges = (await this.restApi.xoApp.getAclV2RolePrivileges(id));
|
|
134
|
+
return this.sendObjects(limitAndFilterArray(privileges, { filter }), req, {
|
|
135
|
+
path: 'acl-privileges',
|
|
136
|
+
limit,
|
|
137
|
+
privilege: { resource: 'acl-privilege', action: 'read' },
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Attach an ACL V2 role to a group.
|
|
142
|
+
*
|
|
143
|
+
* Required privilege:
|
|
144
|
+
* - resource: acl-role, action: update:groups
|
|
145
|
+
*
|
|
146
|
+
* @example id "784bd959-08de-4b26-b575-92ded5aef872"
|
|
147
|
+
* @example groupId "ee4965bf-d8af-4ca2-aa0e-5f29d0c5f9e2"
|
|
148
|
+
*/
|
|
149
|
+
async attachAclV2Group(id, groupId) {
|
|
150
|
+
const roleId = id;
|
|
151
|
+
// addAclV2GroupRole does not check if the group exists so we get the group here to make sure it exists.
|
|
152
|
+
const group = await this.restApi.xoApp.getGroup(groupId);
|
|
153
|
+
await this.restApi.xoApp.addAclV2GroupRole(group.id, roleId);
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Detach an ACL V2 role from a group.
|
|
157
|
+
*
|
|
158
|
+
* Required privilege:
|
|
159
|
+
* - resource: acl-role, action: update:groups
|
|
160
|
+
*
|
|
161
|
+
* @example id "784bd959-08de-4b26-b575-92ded5aef872"
|
|
162
|
+
* @example groupId "ee4965bf-d8af-4ca2-aa0e-5f29d0c5f9e2"
|
|
163
|
+
*/
|
|
164
|
+
async detachAclV2Group(id, groupId) {
|
|
165
|
+
const roleId = id;
|
|
166
|
+
// deleteAclV2GroupRole does not check if the group exists so we get the group here to make sure it exists.
|
|
167
|
+
const group = await this.restApi.xoApp.getGroup(groupId);
|
|
168
|
+
await this.restApi.xoApp.deleteAclV2GroupRole(group.id, roleId);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Attach an ACL V2 role to a user.
|
|
172
|
+
*
|
|
173
|
+
* Required privilege:
|
|
174
|
+
* - resource: acl-role, action: update:users
|
|
175
|
+
*
|
|
176
|
+
* @example id "784bd959-08de-4b26-b575-92ded5aef872"
|
|
177
|
+
* @example userId "ee4965bf-d8af-4ca2-aa0e-5f29d0c5f9e2"
|
|
178
|
+
*/
|
|
179
|
+
async attachAclV2User(id, userId) {
|
|
180
|
+
const roleId = id;
|
|
181
|
+
// addAclV2UserRole does not check if the user exists so we get the user here to make sure it exists.
|
|
182
|
+
const user = await this.restApi.xoApp.getUser(userId);
|
|
183
|
+
await this.restApi.xoApp.addAclV2UserRole(user.id, roleId);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Detach an ACL V2 role from a user.
|
|
187
|
+
*
|
|
188
|
+
* Required privilege:
|
|
189
|
+
* - resource: acl-role, action: update:users
|
|
190
|
+
*
|
|
191
|
+
* @example id "784bd959-08de-4b26-b575-92ded5aef872"
|
|
192
|
+
* @example userId "ee4965bf-d8af-4ca2-aa0e-5f29d0c5f9e2"
|
|
193
|
+
*/
|
|
194
|
+
async detachAclV2User(id, userId) {
|
|
195
|
+
const roleId = id;
|
|
196
|
+
// deleteAclV2UserRole does not check if the user exists so we get the user here to make sure it exists.
|
|
197
|
+
const user = await this.restApi.xoApp.getUser(userId);
|
|
198
|
+
await this.restApi.xoApp.deleteAclV2UserRole(user.id, roleId);
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
__decorate([
|
|
202
|
+
Example(aclRoleIds),
|
|
203
|
+
Example(partialAclRoles),
|
|
204
|
+
Get(''),
|
|
205
|
+
Security('*', ['acl']),
|
|
206
|
+
__param(0, Request()),
|
|
207
|
+
__param(1, Query()),
|
|
208
|
+
__param(2, Query()),
|
|
209
|
+
__param(3, Query()),
|
|
210
|
+
__param(4, Query())
|
|
211
|
+
], AclRoleController.prototype, "getAclV2Roles", null);
|
|
212
|
+
__decorate([
|
|
213
|
+
Example(entityId),
|
|
214
|
+
Post(''),
|
|
215
|
+
Middlewares([
|
|
216
|
+
json(),
|
|
217
|
+
acl({
|
|
218
|
+
resource: 'acl-role',
|
|
219
|
+
action: 'create',
|
|
220
|
+
object: ({ req }) => req.body,
|
|
221
|
+
}),
|
|
222
|
+
]),
|
|
223
|
+
SuccessResponse(createdResp.status, createdResp.description),
|
|
224
|
+
Response(forbiddenOperationResp.status, forbiddenOperationResp.description),
|
|
225
|
+
Response(invalidParameters.status, invalidParameters.description),
|
|
226
|
+
__param(0, Body())
|
|
227
|
+
], AclRoleController.prototype, "createAclV2Role", null);
|
|
228
|
+
__decorate([
|
|
229
|
+
Example(aclRole),
|
|
230
|
+
Get('{id}'),
|
|
231
|
+
Middlewares(acl({
|
|
232
|
+
resource: 'acl-role',
|
|
233
|
+
action: 'read',
|
|
234
|
+
objectId: 'params.id',
|
|
235
|
+
getObject: ({ restApi }) => restApi.xoApp.getAclV2Role,
|
|
236
|
+
})),
|
|
237
|
+
Response(forbiddenOperationResp.status, forbiddenOperationResp.description),
|
|
238
|
+
Response(notFoundResp.status, notFoundResp.description),
|
|
239
|
+
__param(0, Path())
|
|
240
|
+
], AclRoleController.prototype, "getAclV2Role", null);
|
|
241
|
+
__decorate([
|
|
242
|
+
Delete('{id}'),
|
|
243
|
+
Middlewares(acl({
|
|
244
|
+
resource: 'acl-role',
|
|
245
|
+
action: 'delete',
|
|
246
|
+
objectId: 'params.id',
|
|
247
|
+
getObject: ({ restApi }) => restApi.xoApp.getAclV2Role,
|
|
248
|
+
})),
|
|
249
|
+
SuccessResponse(noContentResp.status, noContentResp.description),
|
|
250
|
+
Response(forbiddenOperationResp.status, forbiddenOperationResp.description),
|
|
251
|
+
Response(notFoundResp.status, notFoundResp.description),
|
|
252
|
+
__param(0, Path())
|
|
253
|
+
], AclRoleController.prototype, "deleteAclV2Role", null);
|
|
254
|
+
__decorate([
|
|
255
|
+
Patch('{id}'),
|
|
256
|
+
Middlewares([
|
|
257
|
+
json(),
|
|
258
|
+
acl({
|
|
259
|
+
resource: 'acl-role',
|
|
260
|
+
actions: actionsFromBody(['update:name', 'update:description']),
|
|
261
|
+
objectId: 'params.id',
|
|
262
|
+
getObject: ({ restApi }) => restApi.xoApp.getAclV2Role,
|
|
263
|
+
}),
|
|
264
|
+
]),
|
|
265
|
+
SuccessResponse(noContentResp.status, noContentResp.description),
|
|
266
|
+
Response(forbiddenOperationResp.status, forbiddenOperationResp.description),
|
|
267
|
+
Response(notFoundResp.status, notFoundResp.description),
|
|
268
|
+
Response(invalidParameters.status, invalidParameters.description),
|
|
269
|
+
__param(0, Path()),
|
|
270
|
+
__param(1, Body())
|
|
271
|
+
], AclRoleController.prototype, "updateAclV2Role", null);
|
|
272
|
+
__decorate([
|
|
273
|
+
Example(taskLocation),
|
|
274
|
+
Post('{id}/actions/copy'),
|
|
275
|
+
Middlewares([
|
|
276
|
+
json(),
|
|
277
|
+
acl([
|
|
278
|
+
{
|
|
279
|
+
resource: 'acl-role',
|
|
280
|
+
action: 'create',
|
|
281
|
+
object: async ({ req, restApi }) => {
|
|
282
|
+
const model = await restApi.xoApp.getAclV2Role(req.params.id);
|
|
283
|
+
return { name: req.body.name ?? model.name, description: req.body.description ?? model.description };
|
|
284
|
+
},
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
resource: 'acl-privilege',
|
|
288
|
+
action: 'create',
|
|
289
|
+
objects: async ({ req, restApi }) => {
|
|
290
|
+
const privileges = await restApi.xoApp.getAclV2RolePrivileges(req.params.id);
|
|
291
|
+
return privileges.map(({ id, ...rest }) => rest);
|
|
292
|
+
},
|
|
293
|
+
},
|
|
294
|
+
]),
|
|
295
|
+
]),
|
|
296
|
+
SuccessResponse(createdResp.status, createdResp.description),
|
|
297
|
+
Response(forbiddenOperationResp.status, forbiddenOperationResp.description),
|
|
298
|
+
Response(asynchronousActionResp.status, asynchronousActionResp.description),
|
|
299
|
+
Response(notFoundResp.status, notFoundResp.description),
|
|
300
|
+
__param(0, Path()),
|
|
301
|
+
__param(1, Body()),
|
|
302
|
+
__param(2, Query())
|
|
303
|
+
], AclRoleController.prototype, "copyAclV2Role", null);
|
|
304
|
+
__decorate([
|
|
305
|
+
Example(aclPrivilegeIds),
|
|
306
|
+
Example(partialAclPrivileges),
|
|
307
|
+
Get('{id}/privileges'),
|
|
308
|
+
Security('*', ['acl']),
|
|
309
|
+
Response(notFoundResp.status, notFoundResp.description),
|
|
310
|
+
__param(0, Request()),
|
|
311
|
+
__param(1, Path()),
|
|
312
|
+
__param(2, Query()),
|
|
313
|
+
__param(3, Query()),
|
|
314
|
+
__param(4, Query()),
|
|
315
|
+
__param(5, Query())
|
|
316
|
+
], AclRoleController.prototype, "getAclV2RolePrivileges", null);
|
|
317
|
+
__decorate([
|
|
318
|
+
Put('{id}/groups/{groupId}'),
|
|
319
|
+
Middlewares(acl({
|
|
320
|
+
resource: 'acl-role',
|
|
321
|
+
action: 'update:groups',
|
|
322
|
+
objectId: 'params.id',
|
|
323
|
+
getObject: ({ restApi }) => restApi.xoApp.getAclV2Role,
|
|
324
|
+
})),
|
|
325
|
+
SuccessResponse(noContentResp.status, noContentResp.description),
|
|
326
|
+
Response(forbiddenOperationResp.status, forbiddenOperationResp.description),
|
|
327
|
+
Response(notFoundResp.status, notFoundResp.description),
|
|
328
|
+
Response(resourceAlreadyExists.status, resourceAlreadyExists.description),
|
|
329
|
+
__param(0, Path()),
|
|
330
|
+
__param(1, Path())
|
|
331
|
+
], AclRoleController.prototype, "attachAclV2Group", null);
|
|
332
|
+
__decorate([
|
|
333
|
+
Delete('{id}/groups/{groupId}'),
|
|
334
|
+
Middlewares(acl({
|
|
335
|
+
resource: 'acl-role',
|
|
336
|
+
action: 'update:groups',
|
|
337
|
+
objectId: 'params.id',
|
|
338
|
+
getObject: ({ restApi }) => restApi.xoApp.getAclV2Role,
|
|
339
|
+
})),
|
|
340
|
+
SuccessResponse(noContentResp.status, noContentResp.description),
|
|
341
|
+
Response(forbiddenOperationResp.status, forbiddenOperationResp.description),
|
|
342
|
+
Response(notFoundResp.status, notFoundResp.description),
|
|
343
|
+
__param(0, Path()),
|
|
344
|
+
__param(1, Path())
|
|
345
|
+
], AclRoleController.prototype, "detachAclV2Group", null);
|
|
346
|
+
__decorate([
|
|
347
|
+
Put('{id}/users/{userId}'),
|
|
348
|
+
Middlewares(acl({
|
|
349
|
+
resource: 'acl-role',
|
|
350
|
+
action: 'update:users',
|
|
351
|
+
objectId: 'params.id',
|
|
352
|
+
getObject: ({ restApi }) => restApi.xoApp.getAclV2Role,
|
|
353
|
+
})),
|
|
354
|
+
SuccessResponse(noContentResp.status, noContentResp.description),
|
|
355
|
+
Response(forbiddenOperationResp.status, forbiddenOperationResp.description),
|
|
356
|
+
Response(notFoundResp.status, notFoundResp.description),
|
|
357
|
+
Response(resourceAlreadyExists.status, resourceAlreadyExists.description),
|
|
358
|
+
__param(0, Path()),
|
|
359
|
+
__param(1, Path())
|
|
360
|
+
], AclRoleController.prototype, "attachAclV2User", null);
|
|
361
|
+
__decorate([
|
|
362
|
+
Delete('{id}/users/{userId}'),
|
|
363
|
+
Middlewares(acl({
|
|
364
|
+
resource: 'acl-role',
|
|
365
|
+
action: 'update:users',
|
|
366
|
+
objectId: 'params.id',
|
|
367
|
+
getObject: ({ restApi }) => restApi.xoApp.getAclV2Role,
|
|
368
|
+
})),
|
|
369
|
+
SuccessResponse(noContentResp.status, noContentResp.description),
|
|
370
|
+
Response(forbiddenOperationResp.status, forbiddenOperationResp.description),
|
|
371
|
+
Response(notFoundResp.status, notFoundResp.description),
|
|
372
|
+
__param(0, Path()),
|
|
373
|
+
__param(1, Path())
|
|
374
|
+
], AclRoleController.prototype, "detachAclV2User", null);
|
|
375
|
+
AclRoleController = __decorate([
|
|
376
|
+
Route('acl-roles'),
|
|
377
|
+
Security('*'),
|
|
378
|
+
Response(badRequestResp.status, badRequestResp.description),
|
|
379
|
+
Response(unauthorizedResp.status, unauthorizedResp.description),
|
|
380
|
+
Tags('acls'),
|
|
381
|
+
provide(AclRoleController),
|
|
382
|
+
__param(0, inject(RestApi))
|
|
383
|
+
], AclRoleController);
|
|
384
|
+
export { AclRoleController };
|
|
@@ -7,12 +7,12 @@ 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
|
-
import { noSuchObject } from 'xo-common/api-errors.js';
|
|
13
12
|
import { provide } from 'inversify-binding-decorators';
|
|
14
13
|
import { alarm, alarmIds, partialAlarms } from '../open-api/oa-examples/alarm.oa-example.mjs';
|
|
15
|
-
import {
|
|
14
|
+
import { acl, autoBindService } from '../middlewares/acl.middleware.mjs';
|
|
15
|
+
import { badRequestResp, forbiddenOperationResp, notFoundResp, unauthorizedResp, } from '../open-api/common/response.common.mjs';
|
|
16
16
|
import { RestApi } from '../rest-api/rest-api.mjs';
|
|
17
17
|
import { XapiXoController } from '../abstract-classes/xapi-xo-controller.mjs';
|
|
18
18
|
import { AlarmService } from './alarm.service.mjs';
|
|
@@ -32,21 +32,26 @@ let AlarmController = class AlarmController extends XapiXoController {
|
|
|
32
32
|
* Override parent getObject in order to only get `ALARM` message
|
|
33
33
|
*/
|
|
34
34
|
getObject(id) {
|
|
35
|
-
|
|
36
|
-
if (!this.#alarmService.isAlarm(maybeAlarm)) {
|
|
37
|
-
throw noSuchObject(id, 'alarm');
|
|
38
|
-
}
|
|
39
|
-
return this.#alarmService.parseAlarm(maybeAlarm);
|
|
35
|
+
return this.#alarmService.getAlarm(id);
|
|
40
36
|
}
|
|
41
37
|
/**
|
|
38
|
+
* Returns all alarms that match the following privilege:
|
|
39
|
+
* - resource: alarm, action: read
|
|
40
|
+
*
|
|
42
41
|
* @example fields "body,id,object"
|
|
43
42
|
* @example filter "body:name:physical_utilisation"
|
|
44
43
|
* @example limit 42
|
|
45
44
|
*/
|
|
46
|
-
getAlarms(req, fields, ndjson, filter, limit) {
|
|
47
|
-
return this.sendObjects(Object.values(this.getObjects({ filter
|
|
45
|
+
getAlarms(req, fields, ndjson, markdown, filter, limit) {
|
|
46
|
+
return this.sendObjects(Object.values(this.getObjects({ filter })), req, {
|
|
47
|
+
limit,
|
|
48
|
+
privilege: { action: 'read', resource: 'alarm' },
|
|
49
|
+
});
|
|
48
50
|
}
|
|
49
51
|
/**
|
|
52
|
+
* Required privilege:
|
|
53
|
+
* - resource: alarm, action: read
|
|
54
|
+
*
|
|
50
55
|
* @example id "0c98c71c-2f9c-d5c2-b9b6-2c8371730eab"
|
|
51
56
|
*/
|
|
52
57
|
getAlarm(id) {
|
|
@@ -57,15 +62,24 @@ __decorate([
|
|
|
57
62
|
Example(alarmIds),
|
|
58
63
|
Example(partialAlarms),
|
|
59
64
|
Get(''),
|
|
65
|
+
Security('*', ['acl']),
|
|
60
66
|
__param(0, Request()),
|
|
61
67
|
__param(1, Query()),
|
|
62
68
|
__param(2, Query()),
|
|
63
69
|
__param(3, Query()),
|
|
64
|
-
__param(4, Query())
|
|
70
|
+
__param(4, Query()),
|
|
71
|
+
__param(5, Query())
|
|
65
72
|
], AlarmController.prototype, "getAlarms", null);
|
|
66
73
|
__decorate([
|
|
67
74
|
Example(alarm),
|
|
68
75
|
Get('{id}'),
|
|
76
|
+
Middlewares(acl({
|
|
77
|
+
resource: 'alarm',
|
|
78
|
+
action: 'read',
|
|
79
|
+
objectId: 'params.id',
|
|
80
|
+
getObject: autoBindService(AlarmService, 'getAlarm'),
|
|
81
|
+
})),
|
|
82
|
+
Response(forbiddenOperationResp.status, forbiddenOperationResp.description),
|
|
69
83
|
Response(notFoundResp.status, notFoundResp.description),
|
|
70
84
|
__param(0, Path())
|
|
71
85
|
], AlarmController.prototype, "getAlarm", null);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { noSuchObject } from 'xo-common/api-errors.js';
|
|
1
2
|
import { BASE_URL } from '../index.mjs';
|
|
2
3
|
import { safeParseComplexMatcher } from '../helpers/utils.helper.mjs';
|
|
3
4
|
// 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>';
|
|
@@ -65,4 +66,11 @@ export class AlarmService {
|
|
|
65
66
|
}
|
|
66
67
|
return alarms;
|
|
67
68
|
}
|
|
69
|
+
getAlarm(id) {
|
|
70
|
+
const maybeAlarm = this.#restApi.getObject(id, 'message');
|
|
71
|
+
if (!this.isAlarm(maybeAlarm)) {
|
|
72
|
+
throw noSuchObject(id, 'alarm');
|
|
73
|
+
}
|
|
74
|
+
return this.parseAlarm(maybeAlarm);
|
|
75
|
+
}
|
|
68
76
|
}
|
|
@@ -7,19 +7,20 @@ 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
|
-
import { noSuchObject } from 'xo-common/api-errors.js';
|
|
13
12
|
import { provide } from 'inversify-binding-decorators';
|
|
14
|
-
import { badRequestResp, notFoundResp, unauthorizedResp } from '../open-api/common/response.common.mjs';
|
|
13
|
+
import { badRequestResp, forbiddenOperationResp, notFoundResp, unauthorizedResp, } from '../open-api/common/response.common.mjs';
|
|
15
14
|
import { XoController } from '../abstract-classes/xo-controller.mjs';
|
|
16
15
|
import { RestApi } from '../rest-api/rest-api.mjs';
|
|
17
16
|
import { backupArchive, backupArchiveIds, partialBackupArchives, } from '../open-api/oa-examples/backup-archive.oa-example.mjs';
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
import { BackupArchiveService } from './backup-archive.service.mjs';
|
|
18
|
+
import { acl, autoBindService } from '../middlewares/acl.middleware.mjs';
|
|
20
19
|
let BackupArchiveController = class BackupArchiveController extends XoController {
|
|
21
|
-
|
|
20
|
+
#backupArchiveService;
|
|
21
|
+
constructor(restApi, backupArchiveService) {
|
|
22
22
|
super('backup-archive', restApi);
|
|
23
|
+
this.#backupArchiveService = backupArchiveService;
|
|
23
24
|
}
|
|
24
25
|
async getAllCollectionObjects({ backupRepositories = [], } = {}) {
|
|
25
26
|
const backupRepositoryIds = [];
|
|
@@ -40,19 +41,12 @@ let BackupArchiveController = class BackupArchiveController extends XoController
|
|
|
40
41
|
.flat(2);
|
|
41
42
|
return vmBackupArchives;
|
|
42
43
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if (match === null) {
|
|
46
|
-
throw noSuchObject(id, 'backup-archive');
|
|
47
|
-
}
|
|
48
|
-
const [, brId, vmId] = match;
|
|
49
|
-
const backupArchive = (await this.restApi.xoApp.listVmBackupsNg([brId]))[brId]?.[vmId]?.find(ba => ba.id === id);
|
|
50
|
-
if (backupArchive === undefined) {
|
|
51
|
-
throw noSuchObject(id, 'backup-archive');
|
|
52
|
-
}
|
|
53
|
-
return backupArchive;
|
|
44
|
+
getCollectionObject(id) {
|
|
45
|
+
return this.#backupArchiveService.getBackupArchive(id);
|
|
54
46
|
}
|
|
55
47
|
/**
|
|
48
|
+
* Returns all backup archives that match the following privilege:
|
|
49
|
+
* - resource: backup-archive, action: read
|
|
56
50
|
*
|
|
57
51
|
* You can use the alias "*" in "backup-repository" to select all backup repositories.
|
|
58
52
|
*
|
|
@@ -61,12 +55,18 @@ let BackupArchiveController = class BackupArchiveController extends XoController
|
|
|
61
55
|
* @example filter "disks:length:>0"
|
|
62
56
|
* @example limit 42
|
|
63
57
|
*/
|
|
64
|
-
async getBackupArchives(req, backupRepositories, fields, ndjson, filter, limit) {
|
|
65
|
-
const backupArchives = await this.getObjects({ backupRepositories, filter
|
|
66
|
-
return this.sendObjects(Object.values(backupArchives), req
|
|
58
|
+
async getBackupArchives(req, backupRepositories, fields, ndjson, markdown, filter, limit) {
|
|
59
|
+
const backupArchives = await this.getObjects({ backupRepositories, filter });
|
|
60
|
+
return this.sendObjects(Object.values(backupArchives), req, {
|
|
61
|
+
limit,
|
|
62
|
+
privilege: { action: 'read', resource: 'backup-archive' },
|
|
63
|
+
});
|
|
67
64
|
}
|
|
68
65
|
/**
|
|
69
|
-
*
|
|
66
|
+
* Required privilege:
|
|
67
|
+
* - resource: backup-archive, action: read
|
|
68
|
+
*
|
|
69
|
+
* @example id "231264c3-af43-4ec0-a3be-394c5b1fdbfc/xo-vm-backups/6ef7c09e-677b-1e6f-0546-7ab30413c61c/20250801T080832Z.json"
|
|
70
70
|
*/
|
|
71
71
|
async getBackupArchive(id) {
|
|
72
72
|
const backupArchive = await this.getObject(id);
|
|
@@ -77,17 +77,26 @@ __decorate([
|
|
|
77
77
|
Example(backupArchiveIds),
|
|
78
78
|
Example(partialBackupArchives),
|
|
79
79
|
Get(''),
|
|
80
|
+
Security('*', ['acl']),
|
|
80
81
|
Response(notFoundResp.status, notFoundResp.description),
|
|
81
82
|
__param(0, Request()),
|
|
82
83
|
__param(1, Query('backup-repository')),
|
|
83
84
|
__param(2, Query()),
|
|
84
85
|
__param(3, Query()),
|
|
85
86
|
__param(4, Query()),
|
|
86
|
-
__param(5, Query())
|
|
87
|
+
__param(5, Query()),
|
|
88
|
+
__param(6, Query())
|
|
87
89
|
], BackupArchiveController.prototype, "getBackupArchives", null);
|
|
88
90
|
__decorate([
|
|
89
91
|
Example(backupArchive),
|
|
90
92
|
Get('{id}'),
|
|
93
|
+
Middlewares(acl({
|
|
94
|
+
resource: 'backup-archive',
|
|
95
|
+
action: 'read',
|
|
96
|
+
objectId: 'params.id',
|
|
97
|
+
getObject: autoBindService(BackupArchiveService, 'getBackupArchive'),
|
|
98
|
+
})),
|
|
99
|
+
Response(forbiddenOperationResp.status, forbiddenOperationResp.description),
|
|
91
100
|
Response(notFoundResp.status, notFoundResp.description),
|
|
92
101
|
__param(0, Path())
|
|
93
102
|
], BackupArchiveController.prototype, "getBackupArchive", null);
|
|
@@ -98,6 +107,7 @@ BackupArchiveController = __decorate([
|
|
|
98
107
|
Response(unauthorizedResp.status, unauthorizedResp.description),
|
|
99
108
|
Tags('backup-archives'),
|
|
100
109
|
provide(BackupArchiveController),
|
|
101
|
-
__param(0, inject(RestApi))
|
|
110
|
+
__param(0, inject(RestApi)),
|
|
111
|
+
__param(1, inject(BackupArchiveService))
|
|
102
112
|
], BackupArchiveController);
|
|
103
113
|
export { BackupArchiveController };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { noSuchObject } from 'xo-common/api-errors.js';
|
|
2
|
+
// BR uuid/xo-vm-backups/VM uuid/(ISO 8601 compact).json
|
|
3
|
+
const BACKUP_ARCHIVE_ID_REGEX = /^([0-9a-fA-F-]{36})\/+xo-vm-backups\/+([0-9a-fA-F-]{36})\/+(\d{8}T\d{6}Z)\.json$/;
|
|
4
|
+
export class BackupArchiveService {
|
|
5
|
+
#restApi;
|
|
6
|
+
constructor(restApi) {
|
|
7
|
+
this.#restApi = restApi;
|
|
8
|
+
}
|
|
9
|
+
async getBackupArchive(id) {
|
|
10
|
+
const match = id.match(BACKUP_ARCHIVE_ID_REGEX);
|
|
11
|
+
if (match === null) {
|
|
12
|
+
throw noSuchObject(id, 'backup-archive');
|
|
13
|
+
}
|
|
14
|
+
const [, brId, vmId] = match;
|
|
15
|
+
const backupArchive = (await this.#restApi.xoApp.listVmBackupsNg([brId]))[brId]?.[vmId]?.find(ba => ba.id === id);
|
|
16
|
+
if (backupArchive === undefined) {
|
|
17
|
+
throw noSuchObject(id, 'backup-archive');
|
|
18
|
+
}
|
|
19
|
+
return backupArchive;
|
|
20
|
+
}
|
|
21
|
+
}
|