@spinajs/authz-http-admin 0.0.0-stage → 3.0.1

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 (110) hide show
  1. package/README.md +52 -2
  2. package/lib/cjs/config/authz-http-admin.d.ts +9 -0
  3. package/lib/cjs/config/authz-http-admin.d.ts.map +1 -0
  4. package/lib/cjs/config/authz-http-admin.js +16 -0
  5. package/lib/cjs/config/authz-http-admin.js.map +1 -0
  6. package/lib/cjs/controllers/AuthzAdminController.d.ts +249 -0
  7. package/lib/cjs/controllers/AuthzAdminController.d.ts.map +1 -0
  8. package/lib/cjs/controllers/AuthzAdminController.js +549 -0
  9. package/lib/cjs/controllers/AuthzAdminController.js.map +1 -0
  10. package/lib/cjs/index.d.ts +4 -0
  11. package/lib/cjs/index.d.ts.map +1 -0
  12. package/lib/cjs/index.js +20 -0
  13. package/lib/cjs/index.js.map +1 -0
  14. package/lib/cjs/package.json +1 -0
  15. package/lib/cjs/routes/decode.d.ts +11 -0
  16. package/lib/cjs/routes/decode.d.ts.map +1 -0
  17. package/lib/cjs/routes/decode.js +53 -0
  18. package/lib/cjs/routes/decode.js.map +1 -0
  19. package/lib/cjs/routes/index.d.ts +4 -0
  20. package/lib/cjs/routes/index.d.ts.map +1 -0
  21. package/lib/cjs/routes/index.js +20 -0
  22. package/lib/cjs/routes/index.js.map +1 -0
  23. package/lib/cjs/routes/query.d.ts +16 -0
  24. package/lib/cjs/routes/query.d.ts.map +1 -0
  25. package/lib/cjs/routes/query.js +128 -0
  26. package/lib/cjs/routes/query.js.map +1 -0
  27. package/lib/cjs/routes/status.d.ts +6 -0
  28. package/lib/cjs/routes/status.d.ts.map +1 -0
  29. package/lib/cjs/routes/status.js +21 -0
  30. package/lib/cjs/routes/status.js.map +1 -0
  31. package/lib/cjs/schemas/bodies.d.ts +16 -0
  32. package/lib/cjs/schemas/bodies.d.ts.map +1 -0
  33. package/lib/cjs/schemas/bodies.js +39 -0
  34. package/lib/cjs/schemas/bodies.js.map +1 -0
  35. package/lib/cjs/schemas/commands.d.ts +9 -0
  36. package/lib/cjs/schemas/commands.d.ts.map +1 -0
  37. package/lib/cjs/schemas/commands.js +64 -0
  38. package/lib/cjs/schemas/commands.js.map +1 -0
  39. package/lib/cjs/schemas/document.d.ts +19 -0
  40. package/lib/cjs/schemas/document.d.ts.map +1 -0
  41. package/lib/cjs/schemas/document.js +76 -0
  42. package/lib/cjs/schemas/document.js.map +1 -0
  43. package/lib/cjs/schemas/index.d.ts +6 -0
  44. package/lib/cjs/schemas/index.d.ts.map +1 -0
  45. package/lib/cjs/schemas/index.js +21 -0
  46. package/lib/cjs/schemas/index.js.map +1 -0
  47. package/lib/cjs/schemas/primitives.d.ts +13 -0
  48. package/lib/cjs/schemas/primitives.d.ts.map +1 -0
  49. package/lib/cjs/schemas/primitives.js +29 -0
  50. package/lib/cjs/schemas/primitives.js.map +1 -0
  51. package/lib/cjs/schemas/provider.d.ts +13 -0
  52. package/lib/cjs/schemas/provider.d.ts.map +1 -0
  53. package/lib/cjs/schemas/provider.js +62 -0
  54. package/lib/cjs/schemas/provider.js.map +1 -0
  55. package/lib/mjs/config/authz-http-admin.d.ts +9 -0
  56. package/lib/mjs/config/authz-http-admin.d.ts.map +1 -0
  57. package/lib/mjs/config/authz-http-admin.js +14 -0
  58. package/lib/mjs/config/authz-http-admin.js.map +1 -0
  59. package/lib/mjs/controllers/AuthzAdminController.d.ts +249 -0
  60. package/lib/mjs/controllers/AuthzAdminController.d.ts.map +1 -0
  61. package/lib/mjs/controllers/AuthzAdminController.js +546 -0
  62. package/lib/mjs/controllers/AuthzAdminController.js.map +1 -0
  63. package/lib/mjs/index.d.ts +4 -0
  64. package/lib/mjs/index.d.ts.map +1 -0
  65. package/lib/mjs/index.js +4 -0
  66. package/lib/mjs/index.js.map +1 -0
  67. package/lib/mjs/package.json +1 -0
  68. package/lib/mjs/routes/decode.d.ts +11 -0
  69. package/lib/mjs/routes/decode.d.ts.map +1 -0
  70. package/lib/mjs/routes/decode.js +48 -0
  71. package/lib/mjs/routes/decode.js.map +1 -0
  72. package/lib/mjs/routes/index.d.ts +4 -0
  73. package/lib/mjs/routes/index.d.ts.map +1 -0
  74. package/lib/mjs/routes/index.js +4 -0
  75. package/lib/mjs/routes/index.js.map +1 -0
  76. package/lib/mjs/routes/query.d.ts +16 -0
  77. package/lib/mjs/routes/query.d.ts.map +1 -0
  78. package/lib/mjs/routes/query.js +120 -0
  79. package/lib/mjs/routes/query.js.map +1 -0
  80. package/lib/mjs/routes/status.d.ts +6 -0
  81. package/lib/mjs/routes/status.d.ts.map +1 -0
  82. package/lib/mjs/routes/status.js +17 -0
  83. package/lib/mjs/routes/status.js.map +1 -0
  84. package/lib/mjs/schemas/bodies.d.ts +16 -0
  85. package/lib/mjs/schemas/bodies.d.ts.map +1 -0
  86. package/lib/mjs/schemas/bodies.js +36 -0
  87. package/lib/mjs/schemas/bodies.js.map +1 -0
  88. package/lib/mjs/schemas/commands.d.ts +9 -0
  89. package/lib/mjs/schemas/commands.d.ts.map +1 -0
  90. package/lib/mjs/schemas/commands.js +61 -0
  91. package/lib/mjs/schemas/commands.js.map +1 -0
  92. package/lib/mjs/schemas/document.d.ts +19 -0
  93. package/lib/mjs/schemas/document.d.ts.map +1 -0
  94. package/lib/mjs/schemas/document.js +72 -0
  95. package/lib/mjs/schemas/document.js.map +1 -0
  96. package/lib/mjs/schemas/index.d.ts +6 -0
  97. package/lib/mjs/schemas/index.d.ts.map +1 -0
  98. package/lib/mjs/schemas/index.js +5 -0
  99. package/lib/mjs/schemas/index.js.map +1 -0
  100. package/lib/mjs/schemas/primitives.d.ts +13 -0
  101. package/lib/mjs/schemas/primitives.d.ts.map +1 -0
  102. package/lib/mjs/schemas/primitives.js +24 -0
  103. package/lib/mjs/schemas/primitives.js.map +1 -0
  104. package/lib/mjs/schemas/provider.d.ts +13 -0
  105. package/lib/mjs/schemas/provider.d.ts.map +1 -0
  106. package/lib/mjs/schemas/provider.js +26 -0
  107. package/lib/mjs/schemas/provider.js.map +1 -0
  108. package/lib/tsconfig.cjs.tsbuildinfo +1 -0
  109. package/lib/tsconfig.mjs.tsbuildinfo +1 -0
  110. package/package.json +67 -4
@@ -0,0 +1,546 @@
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 __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
+ return function (target, key) { decorator(target, key, paramIndex); }
12
+ };
13
+ import { AuthzAdminFailure, AuthzDomains } from '@spinajs/authz';
14
+ import { Config } from '@spinajs/configuration';
15
+ import { Autoinject } from '@spinajs/di';
16
+ import { BadRequestResponse, BaseController, BasePath, Conflict, Del, ForbiddenResponse, Get, NotFound, Ok, Patch, Policy, Post, Put, Req } from '@spinajs/http';
17
+ import { IsAuthenticated } from '@spinajs/authz-http';
18
+ import { isPlainObject } from '@spinajs/util';
19
+ import '../schemas/provider.js';
20
+ import { decodeCommand, decodeCommands } from '../routes/decode.js';
21
+ import { readAssignmentsQuery, readHoldersQuery, readPageQuery, readWriteOptions } from '../routes/query.js';
22
+ import { adminErrorStatus, resultsStatus } from '../routes/status.js';
23
+ const PATCH_KEYS = ['tags', 'addTags', 'removeTags', 'expiresAt'];
24
+ const PATCH_KINDS = { tags: 'assignment.setTags', addTags: 'assignment.addTags', removeTags: 'assignment.removeTags' };
25
+ function respond(status, body) {
26
+ switch (status) {
27
+ case 200:
28
+ return new Ok(body);
29
+ case 403:
30
+ return new ForbiddenResponse(body);
31
+ case 404:
32
+ return new NotFound(body);
33
+ case 409:
34
+ return new Conflict(body);
35
+ default:
36
+ return new BadRequestResponse(body);
37
+ }
38
+ }
39
+ function refused(e) {
40
+ return respond(adminErrorStatus(e.code), { error: { code: e.code, message: e.message, ...(e.field === undefined ? {} : { field: e.field }) } });
41
+ }
42
+ function badRequest(message, field) {
43
+ throw new AuthzAdminFailure('invalid_request', message, field);
44
+ }
45
+ function objectBody(body, what) {
46
+ if (!isPlainObject(body))
47
+ badRequest(`the body must be ${what}`);
48
+ return body;
49
+ }
50
+ /** The body of PUT /authz/rules/:id or /authz/policies/:id with the path id; an id in the body must equal it. */
51
+ function withPathId(body, id, what) {
52
+ const o = objectBody(body, what);
53
+ if (o.id !== undefined && o.id !== id)
54
+ badRequest(`the body id ${JSON.stringify(o.id)} is not the path id ${JSON.stringify(id)}`, 'id');
55
+ return { ...o, id };
56
+ }
57
+ const LINK_PATCH_KEYS = ['expiresAt', 'attributes', 'role', 'tags'];
58
+ /** PATCH /authz/links/:id as one link.update; like the assignment patch, a key it does not serve is refused, not ignored. */
59
+ function linkUpdate(body, id) {
60
+ const patch = withPathId(body, id, 'an object { expiresAt?, attributes?, role?, tags? }');
61
+ const unknown = Object.keys(patch).find((k) => k !== 'id' && !LINK_PATCH_KEYS.includes(k));
62
+ if (unknown !== undefined)
63
+ badRequest(`a link patch takes ${LINK_PATCH_KEYS.join(', ')}, not ${JSON.stringify(unknown)}`, unknown);
64
+ if (!LINK_PATCH_KEYS.some((k) => k in patch))
65
+ badRequest(`a link patch needs one of ${LINK_PATCH_KEYS.join(', ')}`);
66
+ return decodeCommand({ ...patch, kind: 'link.update' });
67
+ }
68
+ /** For answers that may hold a link token: no proxy or browser cache may keep one. Set first, so it goes out with any answer the route gives. */
69
+ function noStore(req) {
70
+ req.res?.setHeader('Cache-Control', 'no-store');
71
+ req.res?.setHeader('Pragma', 'no-cache');
72
+ }
73
+ const query = (req) => (req.query ?? {});
74
+ const param = (req, name) => req.params[name];
75
+ const actorOf = (req) => req.storage.Principal;
76
+ const scopeOf = (req) => ({ type: param(req, 'type'), id: param(req, 'id') });
77
+ /**
78
+ * Admin routes over the management API of the configured domain (`authz.http.admin.domain`).
79
+ *
80
+ * The routes check authentication only: the actor is always the request principal, and every
81
+ * permission, validation and guard check runs in AuthzAdmin, as for an in-process caller (design
82
+ * §6.6.5). A refused request answers `{ error: { code, message, field? } }`; a write answers
83
+ * `{ results }`, one entry per command.
84
+ *
85
+ * @tags Authz admin
86
+ */
87
+ let AuthzAdminController = class AuthzAdminController extends BaseController {
88
+ /** Runs a route on the domain's AuthzAdmin; an AuthzAdminFailure becomes its status with `{ error }`, anything else propagates. */
89
+ async guarded(fn) {
90
+ const admin = (await this.Domains.service(this.AdminDomain)).admin();
91
+ try {
92
+ return await fn(admin);
93
+ }
94
+ catch (e) {
95
+ if (e instanceof AuthzAdminFailure)
96
+ return refused(e);
97
+ throw e;
98
+ }
99
+ }
100
+ /** One batch built from the route, with the options of the query string. */
101
+ single(req, build) {
102
+ return this.guarded(async (admin) => {
103
+ const opts = readWriteOptions(query(req));
104
+ return results(await admin.execute(actorOf(req), build(), opts));
105
+ });
106
+ }
107
+ list(req, build) {
108
+ return this.guarded(async (admin) => respond(200, await admin.list(actorOf(req), build())));
109
+ }
110
+ /**
111
+ * Run a batch of commands
112
+ * Runs the commands in order in one transaction on the configured domain; the first failure rolls the batch back and its status is the answer.
113
+ * Body: { commands, reason?, idempotencyKey?, dryRun? } (schema AuthzAdminBatch); `commands` lists the command kinds of AuthzCommand, with dates as ISO 8601 strings. The options go in the body, not the query string.
114
+ * The result of a link.create carries the link token, shown once: every answer the route sends carries `Cache-Control: no-store` (the 401 of the authentication check comes before the route and holds no token), and a retried or dry-run batch answers without the token.
115
+ * @response 200 {AuthzAdminResults} Every command succeeded
116
+ * @response 400 {AuthzAdminError} invalid_request, invalid_batch or a validation code of the command
117
+ * @response 401 Unauthorized: a valid session or token is required
118
+ * @response 403 {AuthzAdminError} forbidden, escalation, last_holder, self_lockout or protected_role
119
+ * @response 404 {AuthzAdminError} not_found: a row the command names does not exist
120
+ * @response 409 {AuthzAdminError} conflict: the row changed or exists already
121
+ */
122
+ async commands(req) {
123
+ noStore(req);
124
+ return this.guarded(async (admin) => {
125
+ const body = objectBody(req.body, 'an object { commands, reason?, idempotencyKey?, dryRun? }');
126
+ const opts = {};
127
+ for (const key of ['reason', 'idempotencyKey', 'dryRun'])
128
+ if (key in body)
129
+ opts[key] = body[key];
130
+ return results(await admin.execute(actorOf(req), decodeCommands(body.commands), opts));
131
+ });
132
+ }
133
+ /**
134
+ * List assignments
135
+ * Lists assignments, filtered by the query.
136
+ * Query: `scope` (`<type>` or `<type>:<id>`), `subject` (`<type>:<id>` or `set:<role>@<type>:<id>`), `role`, `includeExpired` (`true` or `false`), `limit`, `offset`.
137
+ * @response 200 {AuthzAdminPage} One page of rows
138
+ * @response 400 {AuthzAdminError} invalid_query: a malformed query parameter
139
+ * @response 401 Unauthorized: a valid session or token is required
140
+ * @response 403 {AuthzAdminError} forbidden: the caller lacks the read permission at the scope
141
+ */
142
+ async listAssignments(req) {
143
+ return this.list(req, () => readAssignmentsQuery(query(req)));
144
+ }
145
+ /**
146
+ * List holders
147
+ * Who holds a permission on a resource through role assignments on it, its ancestors or $global; each principal is verified by a fresh check.
148
+ * Query: `scope` (`<type>:<id>`), `permission`, `expandSets` (`true` or `false`), `limit`, `offset`.
149
+ * @response 200 {AuthzAdminPage} One page of holders
150
+ * @response 400 {AuthzAdminError} invalid_query: a malformed or missing query parameter
151
+ * @response 401 Unauthorized: a valid session or token is required
152
+ * @response 403 {AuthzAdminError} forbidden: the caller lacks authz:holders.read at the resource, or the resource is unknown
153
+ */
154
+ async listHolders(req) {
155
+ return this.list(req, () => readHoldersQuery(query(req)));
156
+ }
157
+ /**
158
+ * Grant a role
159
+ * Grants a role to a subject at a scope (assignment.grant).
160
+ * Body: the fields of assignment.grant without `kind` (schema AuthzAssignmentGrant).
161
+ * Query: `reason` (audit text), `idempotencyKey`, `dryRun` (`true` validates and guards, then rolls back).
162
+ * @response 200 {AuthzAdminResults} Every command succeeded
163
+ * @response 400 {AuthzAdminError} invalid_request, invalid_query (an option of the query string), invalid_batch or a validation code of the command
164
+ * @response 401 Unauthorized: a valid session or token is required
165
+ * @response 403 {AuthzAdminError} forbidden, escalation, last_holder, self_lockout or protected_role
166
+ * @response 404 {AuthzAdminError} not_found: a row the command names does not exist
167
+ * @response 409 {AuthzAdminError} conflict: the row changed or exists already
168
+ */
169
+ async grant(req) {
170
+ return this.single(req, () => [decodeCommand({ ...objectBody(req.body, 'the fields of assignment.grant'), kind: 'assignment.grant' })]);
171
+ }
172
+ /**
173
+ * Change an assignment
174
+ * Changes the tags or the expiry of an assignment.
175
+ * Body: { tags?, addTags?, removeTags?, expiresAt? } with at least one key (schema AuthzAssignmentPatch); the keys run as one batch.
176
+ * Query: `reason` (audit text), `idempotencyKey`, `dryRun` (`true` validates and guards, then rolls back).
177
+ * @response 200 {AuthzAdminResults} Every command succeeded
178
+ * @response 400 {AuthzAdminError} invalid_request, invalid_query (an option of the query string), invalid_batch or a validation code of the command
179
+ * @response 401 Unauthorized: a valid session or token is required
180
+ * @response 403 {AuthzAdminError} forbidden, escalation, last_holder, self_lockout or protected_role
181
+ * @response 404 {AuthzAdminError} not_found: a row the command names does not exist
182
+ * @response 409 {AuthzAdminError} conflict: the row changed or exists already
183
+ */
184
+ async patchAssignment(req) {
185
+ return this.single(req, () => {
186
+ const body = objectBody(req.body, 'an object { tags?, addTags?, removeTags?, expiresAt? }');
187
+ const unknown = Object.keys(body).find((k) => !PATCH_KEYS.includes(k));
188
+ if (unknown !== undefined)
189
+ badRequest(`an assignment patch takes ${PATCH_KEYS.join(', ')}, not ${JSON.stringify(unknown)}`, unknown);
190
+ const id = param(req, 'id');
191
+ const commands = [];
192
+ for (const key of ['tags', 'addTags', 'removeTags'])
193
+ if (key in body)
194
+ commands.push({ kind: PATCH_KINDS[key], id, tags: body[key] });
195
+ if ('expiresAt' in body)
196
+ commands.push(decodeCommand({ kind: 'assignment.setExpiry', id, expiresAt: body.expiresAt }));
197
+ if (commands.length === 0)
198
+ badRequest(`an assignment patch needs one of ${PATCH_KEYS.join(', ')}`);
199
+ return commands;
200
+ });
201
+ }
202
+ /**
203
+ * Revoke an assignment
204
+ * Revokes the assignment with the path id.
205
+ * Query: `reason` (audit text), `idempotencyKey`, `dryRun` (`true` validates and guards, then rolls back).
206
+ * @response 200 {AuthzAdminResults} Every command succeeded
207
+ * @response 400 {AuthzAdminError} invalid_request, invalid_query (an option of the query string), invalid_batch or a validation code of the command
208
+ * @response 401 Unauthorized: a valid session or token is required
209
+ * @response 403 {AuthzAdminError} forbidden, escalation, last_holder, self_lockout or protected_role
210
+ * @response 404 {AuthzAdminError} not_found: a row the command names does not exist
211
+ * @response 409 {AuthzAdminError} conflict: the row changed or exists already
212
+ */
213
+ async revoke(req) {
214
+ return this.single(req, () => [{ kind: 'assignment.revoke', id: param(req, 'id') }]);
215
+ }
216
+ /**
217
+ * List share links
218
+ * Lists the share links, filtered by the query. A listing never carries a token or its hash: the token is shown once, when the link is created.
219
+ * Query: `scope` (`<type>` or `<type>:<id>`), `limit`, `offset`.
220
+ * @response 200 {AuthzAdminPage} One page of rows
221
+ * @response 400 {AuthzAdminError} invalid_query: a malformed query parameter
222
+ * @response 401 Unauthorized: a valid session or token is required
223
+ * @response 403 {AuthzAdminError} forbidden: the caller lacks the read permission at the scope
224
+ */
225
+ async listLinks(req) {
226
+ return this.list(req, () => readPageQuery('links', query(req)));
227
+ }
228
+ /**
229
+ * Create a share link
230
+ * Creates a share link that grants a role at a scope (link.create). The result carries the link id and its token: the token is shown once, here, and every answer the route sends carries `Cache-Control: no-store` (the 401 of the authentication check comes before the route and holds no token). A dry run or a retried request (same idempotency key) answers without the token.
231
+ * Body: the fields of link.create without `kind` (schema AuthzLinkCreate).
232
+ * Query: `reason` (audit text), `idempotencyKey`, `dryRun` (`true` validates and guards, then rolls back).
233
+ * @response 200 {AuthzAdminResults} The link was created; results[0] holds its id and token
234
+ * @response 400 {AuthzAdminError} invalid_request, invalid_query (an option of the query string), invalid_batch or a validation code of the command
235
+ * @response 401 Unauthorized: a valid session or token is required
236
+ * @response 403 {AuthzAdminError} forbidden, escalation, last_holder, self_lockout or protected_role
237
+ * @response 404 {AuthzAdminError} not_found: a row the command names does not exist
238
+ * @response 409 {AuthzAdminError} conflict: the row changed or exists already
239
+ */
240
+ async createLink(req) {
241
+ noStore(req);
242
+ return this.single(req, () => [decodeCommand({ ...objectBody(req.body, 'the fields of link.create'), kind: 'link.create' })]);
243
+ }
244
+ /**
245
+ * Change a share link
246
+ * Changes the expiry, attributes, role or tags of the link with the path id (link.update). The answer never carries the token.
247
+ * Body: { expiresAt?, attributes?, role?, tags? } with at least one key (schema AuthzLinkPatch); an `id` in the body must equal the path id.
248
+ * Query: `reason` (audit text), `idempotencyKey`, `dryRun` (`true` validates and guards, then rolls back).
249
+ * @response 200 {AuthzAdminResults} Every command succeeded
250
+ * @response 400 {AuthzAdminError} invalid_request, invalid_query (an option of the query string), invalid_batch or a validation code of the command
251
+ * @response 401 Unauthorized: a valid session or token is required
252
+ * @response 403 {AuthzAdminError} forbidden, escalation, last_holder, self_lockout or protected_role
253
+ * @response 404 {AuthzAdminError} not_found: a row the command names does not exist
254
+ * @response 409 {AuthzAdminError} conflict: the row changed or exists already
255
+ */
256
+ async patchLink(req) {
257
+ return this.single(req, () => [linkUpdate(req.body, param(req, 'id'))]);
258
+ }
259
+ /**
260
+ * Revoke a share link
261
+ * Revokes the link with the path id and the role it grants (link.revoke); its token opens nothing from then on.
262
+ * Query: `reason` (audit text), `idempotencyKey`, `dryRun` (`true` validates and guards, then rolls back).
263
+ * @response 200 {AuthzAdminResults} Every command succeeded
264
+ * @response 400 {AuthzAdminError} invalid_request, invalid_query (an option of the query string), invalid_batch or a validation code of the command
265
+ * @response 401 Unauthorized: a valid session or token is required
266
+ * @response 403 {AuthzAdminError} forbidden, escalation, last_holder, self_lockout or protected_role
267
+ * @response 404 {AuthzAdminError} not_found: a row the command names does not exist
268
+ * @response 409 {AuthzAdminError} conflict: the row changed or exists already
269
+ */
270
+ async revokeLink(req) {
271
+ return this.single(req, () => [{ kind: 'link.revoke', id: param(req, 'id') }]);
272
+ }
273
+ /**
274
+ * List rules
275
+ * Lists the RBAC rules held as rows.
276
+ * Query: `scope` (`<type>` or `<type>:<id>`), `limit`, `offset`.
277
+ * @response 200 {AuthzAdminPage} One page of rows
278
+ * @response 400 {AuthzAdminError} invalid_query: a malformed query parameter
279
+ * @response 401 Unauthorized: a valid session or token is required
280
+ * @response 403 {AuthzAdminError} forbidden: the caller lacks the read permission at the scope
281
+ */
282
+ async listRules(req) {
283
+ return this.list(req, () => readPageQuery('rules', query(req)));
284
+ }
285
+ /**
286
+ * Put a rule
287
+ * Inserts or replaces the RBAC rule with the path id.
288
+ * Body: a rule (schema AuthzRuleBody); an `id` in the body must equal the path id.
289
+ * Query: `reason` (audit text), `idempotencyKey`, `dryRun` (`true` validates and guards, then rolls back).
290
+ * @response 200 {AuthzAdminResults} Every command succeeded
291
+ * @response 400 {AuthzAdminError} invalid_request, invalid_query (an option of the query string), invalid_batch or a validation code of the command
292
+ * @response 401 Unauthorized: a valid session or token is required
293
+ * @response 403 {AuthzAdminError} forbidden, escalation, last_holder, self_lockout or protected_role
294
+ * @response 404 {AuthzAdminError} not_found: a row the command names does not exist
295
+ * @response 409 {AuthzAdminError} conflict: the row changed or exists already
296
+ */
297
+ async putRule(req) {
298
+ return this.single(req, () => [decodeCommand({ kind: 'rule.put', rule: withPathId(req.body, param(req, 'id'), 'a rule') })]);
299
+ }
300
+ /**
301
+ * Delete a rule
302
+ * Deletes the RBAC rule with the path id.
303
+ * Query: `reason` (audit text), `idempotencyKey`, `dryRun` (`true` validates and guards, then rolls back).
304
+ * @response 200 {AuthzAdminResults} Every command succeeded
305
+ * @response 400 {AuthzAdminError} invalid_request, invalid_query (an option of the query string), invalid_batch or a validation code of the command
306
+ * @response 401 Unauthorized: a valid session or token is required
307
+ * @response 403 {AuthzAdminError} forbidden, escalation, last_holder, self_lockout or protected_role
308
+ * @response 404 {AuthzAdminError} not_found: a row the command names does not exist
309
+ * @response 409 {AuthzAdminError} conflict: the row changed or exists already
310
+ */
311
+ async deleteRule(req) {
312
+ return this.single(req, () => [{ kind: 'rule.delete', id: param(req, 'id') }]);
313
+ }
314
+ /**
315
+ * List policies
316
+ * Lists the ABAC policies held as rows.
317
+ * Query: `scope` (`<type>` or `<type>:<id>`), `limit`, `offset`.
318
+ * @response 200 {AuthzAdminPage} One page of rows
319
+ * @response 400 {AuthzAdminError} invalid_query: a malformed query parameter
320
+ * @response 401 Unauthorized: a valid session or token is required
321
+ * @response 403 {AuthzAdminError} forbidden: the caller lacks the read permission at the scope
322
+ */
323
+ async listPolicies(req) {
324
+ return this.list(req, () => readPageQuery('policies', query(req)));
325
+ }
326
+ /**
327
+ * Put a policy
328
+ * Inserts or replaces the ABAC policy with the path id.
329
+ * Body: a policy (schema AuthzPolicyBody); an `id` in the body must equal the path id.
330
+ * Query: `reason` (audit text), `idempotencyKey`, `dryRun` (`true` validates and guards, then rolls back).
331
+ * @response 200 {AuthzAdminResults} Every command succeeded
332
+ * @response 400 {AuthzAdminError} invalid_request, invalid_query (an option of the query string), invalid_batch or a validation code of the command
333
+ * @response 401 Unauthorized: a valid session or token is required
334
+ * @response 403 {AuthzAdminError} forbidden, escalation, last_holder, self_lockout or protected_role
335
+ * @response 404 {AuthzAdminError} not_found: a row the command names does not exist
336
+ * @response 409 {AuthzAdminError} conflict: the row changed or exists already
337
+ */
338
+ async putPolicy(req) {
339
+ return this.single(req, () => [decodeCommand({ kind: 'policy.put', policy: withPathId(req.body, param(req, 'id'), 'a policy') })]);
340
+ }
341
+ /**
342
+ * Delete a policy
343
+ * Deletes the ABAC policy with the path id.
344
+ * Query: `reason` (audit text), `idempotencyKey`, `dryRun` (`true` validates and guards, then rolls back).
345
+ * @response 200 {AuthzAdminResults} Every command succeeded
346
+ * @response 400 {AuthzAdminError} invalid_request, invalid_query (an option of the query string), invalid_batch or a validation code of the command
347
+ * @response 401 Unauthorized: a valid session or token is required
348
+ * @response 403 {AuthzAdminError} forbidden, escalation, last_holder, self_lockout or protected_role
349
+ * @response 404 {AuthzAdminError} not_found: a row the command names does not exist
350
+ * @response 409 {AuthzAdminError} conflict: the row changed or exists already
351
+ */
352
+ async deletePolicy(req) {
353
+ return this.single(req, () => [{ kind: 'policy.delete', id: param(req, 'id') }]);
354
+ }
355
+ /**
356
+ * Read scope attributes
357
+ * Returns the attributes of the scope node `<type>:<id>`.
358
+ * @response 200 {AuthzAdminPage} items holds one entry, the attributes object of the scope; total is 1
359
+ * @response 400 {AuthzAdminError} invalid_query: a malformed query parameter
360
+ * @response 401 Unauthorized: a valid session or token is required
361
+ * @response 403 {AuthzAdminError} forbidden: the caller lacks the read permission at the scope
362
+ */
363
+ async attributes(req) {
364
+ return this.list(req, () => ({ kind: 'attributes', scope: scopeOf(req) }));
365
+ }
366
+ /**
367
+ * Merge scope attributes
368
+ * Deep-merges the body into the attributes of the scope node; null deletes a path.
369
+ * Body: an object (schema AuthzAttributesPatch).
370
+ * Query: `reason` (audit text), `idempotencyKey`, `dryRun` (`true` validates and guards, then rolls back).
371
+ * @response 200 {AuthzAdminResults} Every command succeeded
372
+ * @response 400 {AuthzAdminError} invalid_request, invalid_query (an option of the query string), invalid_batch or a validation code of the command
373
+ * @response 401 Unauthorized: a valid session or token is required
374
+ * @response 403 {AuthzAdminError} forbidden, escalation, last_holder, self_lockout or protected_role
375
+ * @response 404 {AuthzAdminError} not_found: a row the command names does not exist
376
+ * @response 409 {AuthzAdminError} conflict: the row changed or exists already
377
+ */
378
+ async patchAttributes(req) {
379
+ return this.single(req, () => [{ kind: 'scope.setAttributes', scope: scopeOf(req), patch: req.body }]);
380
+ }
381
+ /**
382
+ * Replace scope attributes
383
+ * Replaces all attributes of the scope node with the body.
384
+ * Body: an object (schema AuthzAttributesBody).
385
+ * Query: `reason` (audit text), `idempotencyKey`, `dryRun` (`true` validates and guards, then rolls back).
386
+ * @response 200 {AuthzAdminResults} Every command succeeded
387
+ * @response 400 {AuthzAdminError} invalid_request, invalid_query (an option of the query string), invalid_batch or a validation code of the command
388
+ * @response 401 Unauthorized: a valid session or token is required
389
+ * @response 403 {AuthzAdminError} forbidden, escalation, last_holder, self_lockout or protected_role
390
+ * @response 404 {AuthzAdminError} not_found: a row the command names does not exist
391
+ * @response 409 {AuthzAdminError} conflict: the row changed or exists already
392
+ */
393
+ async replaceAttributes(req) {
394
+ return this.single(req, () => [{ kind: 'scope.replaceAttributes', scope: scopeOf(req), attributes: req.body }]);
395
+ }
396
+ };
397
+ __decorate([
398
+ Config('authz.http.admin.domain'),
399
+ __metadata("design:type", String)
400
+ ], AuthzAdminController.prototype, "AdminDomain", void 0);
401
+ __decorate([
402
+ Autoinject(AuthzDomains),
403
+ __metadata("design:type", AuthzDomains)
404
+ ], AuthzAdminController.prototype, "Domains", void 0);
405
+ __decorate([
406
+ Post('commands'),
407
+ __param(0, Req()),
408
+ __metadata("design:type", Function),
409
+ __metadata("design:paramtypes", [Object]),
410
+ __metadata("design:returntype", Promise)
411
+ ], AuthzAdminController.prototype, "commands", null);
412
+ __decorate([
413
+ Get('assignments'),
414
+ __param(0, Req()),
415
+ __metadata("design:type", Function),
416
+ __metadata("design:paramtypes", [Object]),
417
+ __metadata("design:returntype", Promise)
418
+ ], AuthzAdminController.prototype, "listAssignments", null);
419
+ __decorate([
420
+ Get('holders'),
421
+ __param(0, Req()),
422
+ __metadata("design:type", Function),
423
+ __metadata("design:paramtypes", [Object]),
424
+ __metadata("design:returntype", Promise)
425
+ ], AuthzAdminController.prototype, "listHolders", null);
426
+ __decorate([
427
+ Post('assignments'),
428
+ __param(0, Req()),
429
+ __metadata("design:type", Function),
430
+ __metadata("design:paramtypes", [Object]),
431
+ __metadata("design:returntype", Promise)
432
+ ], AuthzAdminController.prototype, "grant", null);
433
+ __decorate([
434
+ Patch('assignments/:id'),
435
+ __param(0, Req()),
436
+ __metadata("design:type", Function),
437
+ __metadata("design:paramtypes", [Object]),
438
+ __metadata("design:returntype", Promise)
439
+ ], AuthzAdminController.prototype, "patchAssignment", null);
440
+ __decorate([
441
+ Del('assignments/:id'),
442
+ __param(0, Req()),
443
+ __metadata("design:type", Function),
444
+ __metadata("design:paramtypes", [Object]),
445
+ __metadata("design:returntype", Promise)
446
+ ], AuthzAdminController.prototype, "revoke", null);
447
+ __decorate([
448
+ Get('links'),
449
+ __param(0, Req()),
450
+ __metadata("design:type", Function),
451
+ __metadata("design:paramtypes", [Object]),
452
+ __metadata("design:returntype", Promise)
453
+ ], AuthzAdminController.prototype, "listLinks", null);
454
+ __decorate([
455
+ Post('links'),
456
+ __param(0, Req()),
457
+ __metadata("design:type", Function),
458
+ __metadata("design:paramtypes", [Object]),
459
+ __metadata("design:returntype", Promise)
460
+ ], AuthzAdminController.prototype, "createLink", null);
461
+ __decorate([
462
+ Patch('links/:id'),
463
+ __param(0, Req()),
464
+ __metadata("design:type", Function),
465
+ __metadata("design:paramtypes", [Object]),
466
+ __metadata("design:returntype", Promise)
467
+ ], AuthzAdminController.prototype, "patchLink", null);
468
+ __decorate([
469
+ Del('links/:id'),
470
+ __param(0, Req()),
471
+ __metadata("design:type", Function),
472
+ __metadata("design:paramtypes", [Object]),
473
+ __metadata("design:returntype", Promise)
474
+ ], AuthzAdminController.prototype, "revokeLink", null);
475
+ __decorate([
476
+ Get('rules'),
477
+ __param(0, Req()),
478
+ __metadata("design:type", Function),
479
+ __metadata("design:paramtypes", [Object]),
480
+ __metadata("design:returntype", Promise)
481
+ ], AuthzAdminController.prototype, "listRules", null);
482
+ __decorate([
483
+ Put('rules/:id'),
484
+ __param(0, Req()),
485
+ __metadata("design:type", Function),
486
+ __metadata("design:paramtypes", [Object]),
487
+ __metadata("design:returntype", Promise)
488
+ ], AuthzAdminController.prototype, "putRule", null);
489
+ __decorate([
490
+ Del('rules/:id'),
491
+ __param(0, Req()),
492
+ __metadata("design:type", Function),
493
+ __metadata("design:paramtypes", [Object]),
494
+ __metadata("design:returntype", Promise)
495
+ ], AuthzAdminController.prototype, "deleteRule", null);
496
+ __decorate([
497
+ Get('policies'),
498
+ __param(0, Req()),
499
+ __metadata("design:type", Function),
500
+ __metadata("design:paramtypes", [Object]),
501
+ __metadata("design:returntype", Promise)
502
+ ], AuthzAdminController.prototype, "listPolicies", null);
503
+ __decorate([
504
+ Put('policies/:id'),
505
+ __param(0, Req()),
506
+ __metadata("design:type", Function),
507
+ __metadata("design:paramtypes", [Object]),
508
+ __metadata("design:returntype", Promise)
509
+ ], AuthzAdminController.prototype, "putPolicy", null);
510
+ __decorate([
511
+ Del('policies/:id'),
512
+ __param(0, Req()),
513
+ __metadata("design:type", Function),
514
+ __metadata("design:paramtypes", [Object]),
515
+ __metadata("design:returntype", Promise)
516
+ ], AuthzAdminController.prototype, "deletePolicy", null);
517
+ __decorate([
518
+ Get('scopes/:type/:id/attributes'),
519
+ __param(0, Req()),
520
+ __metadata("design:type", Function),
521
+ __metadata("design:paramtypes", [Object]),
522
+ __metadata("design:returntype", Promise)
523
+ ], AuthzAdminController.prototype, "attributes", null);
524
+ __decorate([
525
+ Patch('scopes/:type/:id/attributes'),
526
+ __param(0, Req()),
527
+ __metadata("design:type", Function),
528
+ __metadata("design:paramtypes", [Object]),
529
+ __metadata("design:returntype", Promise)
530
+ ], AuthzAdminController.prototype, "patchAttributes", null);
531
+ __decorate([
532
+ Put('scopes/:type/:id/attributes'),
533
+ __param(0, Req()),
534
+ __metadata("design:type", Function),
535
+ __metadata("design:paramtypes", [Object]),
536
+ __metadata("design:returntype", Promise)
537
+ ], AuthzAdminController.prototype, "replaceAttributes", null);
538
+ AuthzAdminController = __decorate([
539
+ Policy(IsAuthenticated),
540
+ BasePath('authz')
541
+ ], AuthzAdminController);
542
+ export { AuthzAdminController };
543
+ function results(r) {
544
+ return respond(resultsStatus(r), { results: r });
545
+ }
546
+ //# sourceMappingURL=AuthzAdminController.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthzAdminController.js","sourceRoot":"","sources":["../../../src/controllers/AuthzAdminController.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export * from './controllers/AuthzAdminController.js';
2
+ export * from './routes/index.js';
3
+ export * from './schemas/index.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,uCAAuC,CAAC;AACtD,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export * from './controllers/AuthzAdminController.js';
2
+ export * from './routes/index.js';
3
+ export * from './schemas/index.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,uCAAuC,CAAC;AACtD,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC"}
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -0,0 +1,11 @@
1
+ /** Date, time (seconds and fraction optional) and `Z` or an offset: the only strings read as a Date. */
2
+ export declare const ISO_DATE_TIME: RegExp;
3
+ /**
4
+ * A command as JSON carries its expiry dates as strings; this copy holds Dates at the known expiry
5
+ * paths. Anything else, including a string that is not an ISO date-time, stays as it came, so
6
+ * AuthzAdmin refuses it as it would refuse it in-process.
7
+ */
8
+ export declare function decodeCommand(command: unknown): unknown;
9
+ /** decodeCommand for each entry of a list; anything else goes through for AuthzAdmin to refuse. */
10
+ export declare function decodeCommands(commands: unknown): unknown;
11
+ //# sourceMappingURL=decode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decode.d.ts","sourceRoot":"","sources":["../../../src/routes/decode.ts"],"names":[],"mappings":"AAEA,wGAAwG;AACxG,eAAO,MAAM,aAAa,QAAkG,CAAC;AA+B7H;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAMvD;AAED,mGAAmG;AACnG,wBAAgB,cAAc,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CAEzD"}
@@ -0,0 +1,48 @@
1
+ import { isPlainObject } from '@spinajs/util';
2
+ /** Date, time (seconds and fraction optional) and `Z` or an offset: the only strings read as a Date. */
3
+ export const ISO_DATE_TIME = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2})(?:\.\d{1,9})?)?(?:Z|[+-](\d{2}):(\d{2}))$/;
4
+ // Date rolls 2027-02-30 over to 2 March instead of refusing it.
5
+ function realFields(m) {
6
+ const [y, mo, d, h, mi, s, oh, om] = m.slice(1).map((x) => Number(x ?? 0));
7
+ const day = new Date(Date.UTC(y, mo - 1, d));
8
+ return day.getUTCFullYear() === y && day.getUTCMonth() === mo - 1 && day.getUTCDate() === d && h < 24 && mi < 60 && s < 60 && oh < 24 && om < 60;
9
+ }
10
+ /** Command kinds whose top-level `expiresAt`, or `expiresAt` inside one nested object, is a Date. */
11
+ const DATE_PATHS = {
12
+ 'assignment.grant': null,
13
+ 'assignment.setExpiry': null,
14
+ 'set.addMember': null,
15
+ 'link.create': null,
16
+ 'link.update': null,
17
+ 'rule.put': 'rule',
18
+ 'policy.put': 'policy',
19
+ };
20
+ function toDate(v) {
21
+ const m = typeof v === 'string' ? ISO_DATE_TIME.exec(v) : null;
22
+ if (!m || !realFields(m))
23
+ return v;
24
+ const at = new Date(v);
25
+ return Number.isNaN(at.getTime()) ? v : at;
26
+ }
27
+ function withDate(o) {
28
+ return 'expiresAt' in o ? { ...o, expiresAt: toDate(o.expiresAt) } : o;
29
+ }
30
+ /**
31
+ * A command as JSON carries its expiry dates as strings; this copy holds Dates at the known expiry
32
+ * paths. Anything else, including a string that is not an ISO date-time, stays as it came, so
33
+ * AuthzAdmin refuses it as it would refuse it in-process.
34
+ */
35
+ export function decodeCommand(command) {
36
+ if (!isPlainObject(command) || typeof command.kind !== 'string' || !Object.hasOwn(DATE_PATHS, command.kind))
37
+ return command;
38
+ const nested = DATE_PATHS[command.kind];
39
+ if (nested === null)
40
+ return withDate(command);
41
+ const inner = command[nested];
42
+ return isPlainObject(inner) ? { ...command, [nested]: withDate(inner) } : command;
43
+ }
44
+ /** decodeCommand for each entry of a list; anything else goes through for AuthzAdmin to refuse. */
45
+ export function decodeCommands(commands) {
46
+ return Array.isArray(commands) ? commands.map(decodeCommand) : commands;
47
+ }
48
+ //# sourceMappingURL=decode.js.map