@spinajs/authz-http-admin 3.0.13 → 3.0.15

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 (188) hide show
  1. package/README.md +9 -8
  2. package/lib/cjs/controllers/AuthzAdminController.d.ts +35 -29
  3. package/lib/cjs/controllers/AuthzAdminController.d.ts.map +1 -1
  4. package/lib/cjs/controllers/AuthzAdminController.js +172 -175
  5. package/lib/cjs/controllers/AuthzAdminController.js.map +1 -1
  6. package/lib/cjs/dto/assignments.d.ts +33 -0
  7. package/lib/cjs/dto/assignments.d.ts.map +1 -0
  8. package/lib/cjs/dto/assignments.js +39 -0
  9. package/lib/cjs/dto/assignments.js.map +1 -0
  10. package/lib/cjs/dto/attributes.d.ts +20 -0
  11. package/lib/cjs/dto/attributes.d.ts.map +1 -0
  12. package/lib/cjs/dto/attributes.js +29 -0
  13. package/lib/cjs/dto/attributes.js.map +1 -0
  14. package/lib/cjs/dto/batch.d.ts +11 -0
  15. package/lib/cjs/dto/batch.d.ts.map +1 -0
  16. package/lib/cjs/dto/batch.js +10 -0
  17. package/lib/cjs/dto/batch.js.map +1 -0
  18. package/lib/cjs/dto/index.d.ts +9 -0
  19. package/lib/cjs/dto/index.d.ts.map +1 -0
  20. package/lib/cjs/dto/index.js +25 -0
  21. package/lib/cjs/dto/index.js.map +1 -0
  22. package/lib/cjs/dto/input.d.ts +8 -0
  23. package/lib/cjs/dto/input.d.ts.map +1 -0
  24. package/lib/cjs/dto/input.js +19 -0
  25. package/lib/cjs/dto/input.js.map +1 -0
  26. package/lib/cjs/dto/links.d.ts +28 -0
  27. package/lib/cjs/dto/links.d.ts.map +1 -0
  28. package/lib/cjs/dto/links.js +40 -0
  29. package/lib/cjs/dto/links.js.map +1 -0
  30. package/lib/cjs/dto/params.d.ts +19 -0
  31. package/lib/cjs/dto/params.d.ts.map +1 -0
  32. package/lib/cjs/dto/params.js +9 -0
  33. package/lib/cjs/dto/params.js.map +1 -0
  34. package/lib/cjs/dto/queries.d.ts +37 -0
  35. package/lib/cjs/dto/queries.d.ts.map +1 -0
  36. package/lib/cjs/dto/queries.js +70 -0
  37. package/lib/cjs/dto/queries.js.map +1 -0
  38. package/lib/cjs/dto/rules.d.ts +18 -0
  39. package/lib/cjs/dto/rules.d.ts.map +1 -0
  40. package/lib/cjs/dto/rules.js +34 -0
  41. package/lib/cjs/dto/rules.js.map +1 -0
  42. package/lib/cjs/index.d.ts +1 -0
  43. package/lib/cjs/index.d.ts.map +1 -1
  44. package/lib/cjs/index.js +1 -0
  45. package/lib/cjs/index.js.map +1 -1
  46. package/lib/cjs/routes/answers.d.ts +22 -0
  47. package/lib/cjs/routes/answers.d.ts.map +1 -0
  48. package/lib/cjs/routes/answers.js +121 -0
  49. package/lib/cjs/routes/answers.js.map +1 -0
  50. package/lib/cjs/routes/args.d.ts +59 -0
  51. package/lib/cjs/routes/args.d.ts.map +1 -0
  52. package/lib/cjs/routes/args.js +167 -0
  53. package/lib/cjs/routes/args.js.map +1 -0
  54. package/lib/cjs/routes/index.d.ts +3 -0
  55. package/lib/cjs/routes/index.d.ts.map +1 -1
  56. package/lib/cjs/routes/index.js +3 -0
  57. package/lib/cjs/routes/index.js.map +1 -1
  58. package/lib/cjs/routes/no-store.d.ts +10 -0
  59. package/lib/cjs/routes/no-store.d.ts.map +1 -0
  60. package/lib/cjs/routes/no-store.js +18 -0
  61. package/lib/cjs/routes/no-store.js.map +1 -0
  62. package/lib/cjs/routes/query.d.ts +6 -7
  63. package/lib/cjs/routes/query.d.ts.map +1 -1
  64. package/lib/cjs/routes/query.js +15 -62
  65. package/lib/cjs/routes/query.js.map +1 -1
  66. package/lib/cjs/schemas/answers.d.ts +7 -0
  67. package/lib/cjs/schemas/answers.d.ts.map +1 -0
  68. package/lib/cjs/schemas/answers.js +14 -0
  69. package/lib/cjs/schemas/answers.js.map +1 -0
  70. package/lib/cjs/schemas/commands.d.ts +4 -0
  71. package/lib/cjs/schemas/commands.d.ts.map +1 -1
  72. package/lib/cjs/schemas/commands.js +20 -12
  73. package/lib/cjs/schemas/commands.js.map +1 -1
  74. package/lib/cjs/schemas/document.d.ts +8 -17
  75. package/lib/cjs/schemas/document.d.ts.map +1 -1
  76. package/lib/cjs/schemas/document.js +53 -64
  77. package/lib/cjs/schemas/document.js.map +1 -1
  78. package/lib/cjs/schemas/index.d.ts +1 -1
  79. package/lib/cjs/schemas/index.d.ts.map +1 -1
  80. package/lib/cjs/schemas/index.js +1 -1
  81. package/lib/cjs/schemas/index.js.map +1 -1
  82. package/lib/cjs/schemas/primitives.d.ts +8 -1
  83. package/lib/cjs/schemas/primitives.d.ts.map +1 -1
  84. package/lib/cjs/schemas/primitives.js +25 -15
  85. package/lib/cjs/schemas/primitives.js.map +1 -1
  86. package/lib/cjs/schemas/provider.d.ts +4 -4
  87. package/lib/cjs/schemas/provider.d.ts.map +1 -1
  88. package/lib/cjs/schemas/provider.js +6 -6
  89. package/lib/cjs/schemas/provider.js.map +1 -1
  90. package/lib/mjs/controllers/AuthzAdminController.d.ts +35 -29
  91. package/lib/mjs/controllers/AuthzAdminController.d.ts.map +1 -1
  92. package/lib/mjs/controllers/AuthzAdminController.js +174 -177
  93. package/lib/mjs/controllers/AuthzAdminController.js.map +1 -1
  94. package/lib/mjs/dto/assignments.d.ts +33 -0
  95. package/lib/mjs/dto/assignments.d.ts.map +1 -0
  96. package/lib/mjs/dto/assignments.js +36 -0
  97. package/lib/mjs/dto/assignments.js.map +1 -0
  98. package/lib/mjs/dto/attributes.d.ts +20 -0
  99. package/lib/mjs/dto/attributes.d.ts.map +1 -0
  100. package/lib/mjs/dto/attributes.js +26 -0
  101. package/lib/mjs/dto/attributes.js.map +1 -0
  102. package/lib/mjs/dto/batch.d.ts +11 -0
  103. package/lib/mjs/dto/batch.d.ts.map +1 -0
  104. package/lib/mjs/dto/batch.js +7 -0
  105. package/lib/mjs/dto/batch.js.map +1 -0
  106. package/lib/mjs/dto/index.d.ts +9 -0
  107. package/lib/mjs/dto/index.d.ts.map +1 -0
  108. package/lib/mjs/dto/index.js +9 -0
  109. package/lib/mjs/dto/index.js.map +1 -0
  110. package/lib/mjs/dto/input.d.ts +8 -0
  111. package/lib/mjs/dto/input.d.ts.map +1 -0
  112. package/lib/mjs/dto/input.js +15 -0
  113. package/lib/mjs/dto/input.js.map +1 -0
  114. package/lib/mjs/dto/links.d.ts +28 -0
  115. package/lib/mjs/dto/links.d.ts.map +1 -0
  116. package/lib/mjs/dto/links.js +37 -0
  117. package/lib/mjs/dto/links.js.map +1 -0
  118. package/lib/mjs/dto/params.d.ts +19 -0
  119. package/lib/mjs/dto/params.d.ts.map +1 -0
  120. package/lib/mjs/dto/params.js +6 -0
  121. package/lib/mjs/dto/params.js.map +1 -0
  122. package/lib/mjs/dto/queries.d.ts +37 -0
  123. package/lib/mjs/dto/queries.d.ts.map +1 -0
  124. package/lib/mjs/dto/queries.js +66 -0
  125. package/lib/mjs/dto/queries.js.map +1 -0
  126. package/lib/mjs/dto/rules.d.ts +18 -0
  127. package/lib/mjs/dto/rules.d.ts.map +1 -0
  128. package/lib/mjs/dto/rules.js +31 -0
  129. package/lib/mjs/dto/rules.js.map +1 -0
  130. package/lib/mjs/index.d.ts +1 -0
  131. package/lib/mjs/index.d.ts.map +1 -1
  132. package/lib/mjs/index.js +1 -0
  133. package/lib/mjs/index.js.map +1 -1
  134. package/lib/mjs/routes/answers.d.ts +22 -0
  135. package/lib/mjs/routes/answers.d.ts.map +1 -0
  136. package/lib/mjs/routes/answers.js +115 -0
  137. package/lib/mjs/routes/answers.js.map +1 -0
  138. package/lib/mjs/routes/args.d.ts +59 -0
  139. package/lib/mjs/routes/args.d.ts.map +1 -0
  140. package/lib/mjs/routes/args.js +160 -0
  141. package/lib/mjs/routes/args.js.map +1 -0
  142. package/lib/mjs/routes/index.d.ts +3 -0
  143. package/lib/mjs/routes/index.d.ts.map +1 -1
  144. package/lib/mjs/routes/index.js +3 -0
  145. package/lib/mjs/routes/index.js.map +1 -1
  146. package/lib/mjs/routes/no-store.d.ts +10 -0
  147. package/lib/mjs/routes/no-store.d.ts.map +1 -0
  148. package/lib/mjs/routes/no-store.js +14 -0
  149. package/lib/mjs/routes/no-store.js.map +1 -0
  150. package/lib/mjs/routes/query.d.ts +6 -7
  151. package/lib/mjs/routes/query.d.ts.map +1 -1
  152. package/lib/mjs/routes/query.js +15 -62
  153. package/lib/mjs/routes/query.js.map +1 -1
  154. package/lib/mjs/schemas/answers.d.ts +7 -0
  155. package/lib/mjs/schemas/answers.d.ts.map +1 -0
  156. package/lib/mjs/schemas/answers.js +11 -0
  157. package/lib/mjs/schemas/answers.js.map +1 -0
  158. package/lib/mjs/schemas/commands.d.ts +4 -0
  159. package/lib/mjs/schemas/commands.d.ts.map +1 -1
  160. package/lib/mjs/schemas/commands.js +19 -12
  161. package/lib/mjs/schemas/commands.js.map +1 -1
  162. package/lib/mjs/schemas/document.d.ts +8 -17
  163. package/lib/mjs/schemas/document.d.ts.map +1 -1
  164. package/lib/mjs/schemas/document.js +53 -63
  165. package/lib/mjs/schemas/document.js.map +1 -1
  166. package/lib/mjs/schemas/index.d.ts +1 -1
  167. package/lib/mjs/schemas/index.d.ts.map +1 -1
  168. package/lib/mjs/schemas/index.js +1 -1
  169. package/lib/mjs/schemas/index.js.map +1 -1
  170. package/lib/mjs/schemas/primitives.d.ts +8 -1
  171. package/lib/mjs/schemas/primitives.d.ts.map +1 -1
  172. package/lib/mjs/schemas/primitives.js +22 -14
  173. package/lib/mjs/schemas/primitives.js.map +1 -1
  174. package/lib/mjs/schemas/provider.d.ts +4 -4
  175. package/lib/mjs/schemas/provider.d.ts.map +1 -1
  176. package/lib/mjs/schemas/provider.js +6 -6
  177. package/lib/mjs/schemas/provider.js.map +1 -1
  178. package/lib/tsconfig.cjs.tsbuildinfo +1 -1
  179. package/lib/tsconfig.mjs.tsbuildinfo +1 -1
  180. package/package.json +13 -12
  181. package/lib/cjs/schemas/bodies.d.ts +0 -17
  182. package/lib/cjs/schemas/bodies.d.ts.map +0 -1
  183. package/lib/cjs/schemas/bodies.js +0 -35
  184. package/lib/cjs/schemas/bodies.js.map +0 -1
  185. package/lib/mjs/schemas/bodies.d.ts +0 -17
  186. package/lib/mjs/schemas/bodies.d.ts.map +0 -1
  187. package/lib/mjs/schemas/bodies.js +0 -32
  188. package/lib/mjs/schemas/bodies.js.map +0 -1
@@ -0,0 +1,22 @@
1
+ import { AuthzAdminFailure } from '@spinajs/authz';
2
+ import type { Response } from '@spinajs/http';
3
+ import type { IValidationError } from '@spinajs/validation';
4
+ export declare function respond(status: number, body: unknown): Response;
5
+ /** The answer of an AuthzAdminFailure: its status with `{ error: { code, message, field? } }`. */
6
+ export declare function refused(e: AuthzAdminFailure): Response;
7
+ /**
8
+ * The failure `code` for input that broke its schema, naming the first offending field. `prefix` is
9
+ * the path of the validated value inside the request (a command of a batch), `fallbackField` the
10
+ * name of a scalar input such as a path parameter. Messages never quote the input.
11
+ */
12
+ export declare function inputFailure(code: string, errors: readonly IValidationError[] | null, prefix?: readonly string[], fallbackField?: string): AuthzAdminFailure;
13
+ /**
14
+ * `@OnError` handler of the admin routes for the arguments stage (D2): input that breaks its schema
15
+ * answers the route's `{ error: { code, field } }`, as AuthzAdmin's own refusals do.
16
+ * - ValidationFailed of a body or a path parameter: 400 invalid_request.
17
+ * - InvalidArgument (a body that is not JSON): 400 invalid_request.
18
+ * - AuthzAdminFailure from the query, batch and body args: its code and status.
19
+ * - UnknownAuthzDomain: 403 unknown_domain.
20
+ */
21
+ export declare function adminInputAnswer(err: Error): Response | undefined;
22
+ //# sourceMappingURL=answers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"answers.d.ts","sourceRoot":"","sources":["../../../src/routes/answers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAInD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAI5D,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,QAAQ,CAe/D;AAED,kGAAkG;AAClG,wBAAgB,OAAO,CAAC,CAAC,EAAE,iBAAiB,GAAG,QAAQ,CAEtD;AAuDD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,gBAAgB,EAAE,GAAG,IAAI,EAAE,MAAM,GAAE,SAAS,MAAM,EAAO,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAMhK;AAID;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,KAAK,GAAG,QAAQ,GAAG,SAAS,CAUjE"}
@@ -0,0 +1,115 @@
1
+ import { AuthzAdminFailure } from '@spinajs/authz';
2
+ import { UnknownAuthzDomain } from '@spinajs/authz-http';
3
+ import { InvalidArgument } from '@spinajs/exceptions';
4
+ import { BadRequestResponse, Conflict, ForbiddenResponse, NotFound, Ok, ServerError } from '@spinajs/http';
5
+ import { ValidationFailed } from '@spinajs/validation';
6
+ import { adminErrorStatus } from './status.js';
7
+ export function respond(status, body) {
8
+ switch (status) {
9
+ case 200:
10
+ return new Ok(body);
11
+ case 403:
12
+ return new ForbiddenResponse(body);
13
+ case 404:
14
+ return new NotFound(body);
15
+ case 409:
16
+ return new Conflict(body);
17
+ case 500:
18
+ return new ServerError(body);
19
+ default:
20
+ return new BadRequestResponse(body);
21
+ }
22
+ }
23
+ /** The answer of an AuthzAdminFailure: its status with `{ error: { code, message, field? } }`. */
24
+ export function refused(e) {
25
+ return respond(adminErrorStatus(e.code), { error: { code: e.code, message: e.message, ...(e.field === undefined ? {} : { field: e.field }) } });
26
+ }
27
+ const COMPOSITE = new Set(['anyOf', 'oneOf', 'allOf', 'if', 'not']);
28
+ const inBranch = (e) => /\/(anyOf|oneOf|allOf)\/\d+\//.test(e.schemaPath);
29
+ /** The error that names the input best: an unknown key, else an error outside the branches of anyOf/oneOf, else the composite itself. */
30
+ function primary(errors) {
31
+ const own = errors.filter((e) => !inBranch(e));
32
+ return own.find((e) => e.keyword === 'additionalProperties') ?? own.find((e) => !COMPOSITE.has(e.keyword)) ?? own[0] ?? errors[0];
33
+ }
34
+ /** `/commands/0/expiresAt` as `commands.0.expiresAt`; the key a `required` or `additionalProperties` error names is appended. */
35
+ function pathOf(e) {
36
+ const params = e.params;
37
+ // http's required-parameter check names the argument, not a JSON pointer.
38
+ if (params.missingParameter !== undefined)
39
+ return [];
40
+ const path = e.instancePath === '' ? [] : e.instancePath.slice(1).split('/').map((s) => s.replace(/~1/g, '/').replace(/~0/g, '~'));
41
+ if (e.keyword === 'required' && params.missingProperty !== undefined)
42
+ path.push(params.missingProperty);
43
+ if (e.keyword === 'additionalProperties' && params.additionalProperty !== undefined)
44
+ path.push(params.additionalProperty);
45
+ return path;
46
+ }
47
+ const LIMIT_WORDS = {
48
+ maxLength: 'exceeds the limit of',
49
+ maxItems: 'exceeds the limit of',
50
+ maximum: 'exceeds the limit of',
51
+ minLength: 'is below the minimum of',
52
+ minItems: 'is below the minimum of',
53
+ minimum: 'is below the minimum of',
54
+ };
55
+ function describe(e, field, errors) {
56
+ const what = field ?? 'the input';
57
+ const params = e.params;
58
+ if (Object.hasOwn(LIMIT_WORDS, e.keyword))
59
+ return `${what} ${LIMIT_WORDS[e.keyword]} ${String(params.limit)}`;
60
+ switch (e.keyword) {
61
+ case 'additionalProperties':
62
+ return `${what} is not a field of this request`;
63
+ case 'required':
64
+ return `${what} is required`;
65
+ case 'type':
66
+ return `${what} must be of type ${String(params.type)}`;
67
+ case 'anyOf': {
68
+ const keys = errors.filter((x) => x.keyword === 'required' && inBranch(x)).map((x) => x.params.missingProperty);
69
+ return keys.length > 0 ? `${what} needs one of ${keys.join(', ')}` : `${what} matches none of the allowed shapes`;
70
+ }
71
+ case 'oneOf':
72
+ return `${what} matches none of the allowed shapes`;
73
+ case 'format':
74
+ return `${what} must be a ${String(params.format)}`;
75
+ default:
76
+ return `${what} is invalid (${e.keyword})`;
77
+ }
78
+ }
79
+ /**
80
+ * The failure `code` for input that broke its schema, naming the first offending field. `prefix` is
81
+ * the path of the validated value inside the request (a command of a batch), `fallbackField` the
82
+ * name of a scalar input such as a path parameter. Messages never quote the input.
83
+ */
84
+ export function inputFailure(code, errors, prefix = [], fallbackField) {
85
+ const e = primary(errors ?? []);
86
+ if (!e)
87
+ return new AuthzAdminFailure(code, 'the input is invalid', fallbackField);
88
+ const path = [...prefix, ...pathOf(e)];
89
+ const field = path.length > 0 ? path.join('.') : fallbackField;
90
+ return new AuthzAdminFailure(code, describe(e, field, errors ?? []), field);
91
+ }
92
+ const PARAM_ID = 'authz.admin.param.';
93
+ /**
94
+ * `@OnError` handler of the admin routes for the arguments stage (D2): input that breaks its schema
95
+ * answers the route's `{ error: { code, field } }`, as AuthzAdmin's own refusals do.
96
+ * - ValidationFailed of a body or a path parameter: 400 invalid_request.
97
+ * - InvalidArgument (a body that is not JSON): 400 invalid_request.
98
+ * - AuthzAdminFailure from the query, batch and body args: its code and status.
99
+ * - UnknownAuthzDomain: 403 unknown_domain.
100
+ */
101
+ export function adminInputAnswer(err) {
102
+ if (err instanceof AuthzAdminFailure)
103
+ return refused(err);
104
+ if (err instanceof UnknownAuthzDomain)
105
+ return respond(403, { error: { code: 'unknown_domain', message: err.message } });
106
+ if (err instanceof ValidationFailed) {
107
+ const id = err.schema?.$id;
108
+ const param = typeof id === 'string' && id.startsWith(PARAM_ID) ? id.slice(PARAM_ID.length) : undefined;
109
+ return refused(inputFailure('invalid_request', err.parameter, [], param));
110
+ }
111
+ if (err instanceof InvalidArgument)
112
+ return refused(new AuthzAdminFailure('invalid_request', 'the body must be a JSON object'));
113
+ return undefined;
114
+ }
115
+ //# sourceMappingURL=answers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"answers.js","sourceRoot":"","sources":["../../../src/routes/answers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ import { RouteArgs } from '@spinajs/http';
2
+ import type { IRoute, IRouteCall, IRouteParameter, Req } from '@spinajs/http';
3
+ import type * as express from 'express';
4
+ import type { AuthzAdminCommandBatch } from '../dto/batch.js';
5
+ import { AuthzCommandSchemaRegistry } from '../schemas/registry.js';
6
+ type Decorator = ReturnType<typeof Req>;
7
+ /** Route arg of `@AdminQuery()`: the whole query string as the parameter's DTO class, validated against its `@Schema`; a failure is 400 invalid_query. */
8
+ export declare class AuthzAdminQueryArg extends RouteArgs {
9
+ get SupportedType(): string;
10
+ extract(callData: IRouteCall, _args: unknown[], param: IRouteParameter, req: express.Request): Promise<{
11
+ CallData: IRouteCall;
12
+ Args: object;
13
+ }>;
14
+ }
15
+ /** Route arg of `@AdminBody()`: the whole body as the parameter's DTO class. Unlike `@Body()`, a body key named as the parameter is not taken for the body. */
16
+ export declare class AuthzAdminBodyArg extends RouteArgs {
17
+ get SupportedType(): string;
18
+ extract(callData: IRouteCall, _args: unknown[], param: IRouteParameter, req: express.Request, _res: express.Response, route: IRoute): Promise<{
19
+ CallData: IRouteCall;
20
+ Args: any;
21
+ }>;
22
+ }
23
+ /**
24
+ * Route arg of `@AdminBatch()`: the body of POST /authz/commands. The envelope is checked against
25
+ * BATCH_ENVELOPE_SCHEMA and each command against the schema AuthzCommandSchemaRegistry holds for its
26
+ * kind, read on each request so that a late AuthzCommandSchemaSource counts; a kind no source
27
+ * describes is refused. A failure is 400 invalid_request (not an object) or invalid_batch.
28
+ */
29
+ export declare class AuthzAdminBatchArg extends RouteArgs {
30
+ protected Registry: AuthzCommandSchemaRegistry;
31
+ private strictCopies;
32
+ get SupportedType(): string;
33
+ extract(callData: IRouteCall, _args: unknown[], _param: IRouteParameter, req: express.Request): Promise<{
34
+ CallData: IRouteCall;
35
+ Args: AuthzAdminCommandBatch;
36
+ }>;
37
+ /** The command schema under an `authz.` id, which the validation package checks without coercion. */
38
+ private strict;
39
+ }
40
+ /** Route arg of `@AdminDomain()`: the authz domain of the request as the AuthzDomainResolver names it, `authz.http.admin.domain` being its fallback. */
41
+ export declare class AuthzAdminDomainArg extends RouteArgs {
42
+ Priority: number;
43
+ protected FallbackDomain: string;
44
+ get SupportedType(): string;
45
+ extract(callData: IRouteCall, _args: unknown[], _param: IRouteParameter, req: express.Request): Promise<{
46
+ CallData: IRouteCall;
47
+ Args: string;
48
+ }>;
49
+ }
50
+ /** The whole query string as the parameter's `@Schema` DTO class; 400 invalid_query when it breaks the schema. */
51
+ export declare function AdminQuery(): Decorator;
52
+ /** The whole body as the parameter's `@Schema` DTO class; 400 invalid_request when it breaks the schema. */
53
+ export declare function AdminBody(): Decorator;
54
+ /** The body of POST /authz/commands as AuthzAdminCommandBatch. */
55
+ export declare function AdminBatch(): Decorator;
56
+ /** The authz domain the admin routes run in for this request. */
57
+ export declare function AdminDomain(): Decorator;
58
+ export {};
59
+ //# sourceMappingURL=args.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../../src/routes/args.ts"],"names":[],"mappings":"AAIA,OAAO,EAAoB,SAAS,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,eAAe,EAAE,GAAG,EAAW,MAAM,eAAe,CAAC;AAEvF,OAAO,KAAK,KAAK,OAAO,MAAM,SAAS,CAAC;AAGxC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AAIpE,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,GAAG,CAAC,CAAC;AAiBxC,0JAA0J;AAC1J,qBACa,kBAAmB,SAAQ,SAAS;IAC/C,IAAW,aAAa,IAAI,MAAM,CAEjC;IAEY,OAAO,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE,GAAG,EAAE,OAAO,CAAC,OAAO;;;OAOxG;CACF;AAED,+JAA+J;AAC/J,qBACa,iBAAkB,SAAQ,SAAS;IAC9C,IAAW,aAAa,IAAI,MAAM,CAEjC;IAEY,OAAO,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM;;;OAE/I;CACF;AAED;;;;;GAKG;AACH,qBACa,kBAAmB,SAAQ,SAAS;IAE/C,SAAS,CAAC,QAAQ,EAAE,0BAA0B,CAAC;IAG/C,OAAO,CAAC,YAAY,CAA6B;IAEjD,IAAW,aAAa,IAAI,MAAM,CAEjC;IAEY,OAAO,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE,GAAG,EAAE,OAAO,CAAC,OAAO;;;OAkBzG;IAED,qGAAqG;IACrG,OAAO,CAAC,MAAM;CAMf;AAED,wJAAwJ;AACxJ,qBACa,mBAAoB,SAAQ,SAAS;IAEzC,QAAQ,SAAM;IAGrB,SAAS,CAAC,cAAc,EAAE,MAAM,CAAC;IAEjC,IAAW,aAAa,IAAI,MAAM,CAEjC;IAEY,OAAO,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE,GAAG,EAAE,OAAO,CAAC,OAAO;;;OAEzG;CACF;AAED,kHAAkH;AAClH,wBAAgB,UAAU,IAAI,SAAS,CAEtC;AAED,4GAA4G;AAC5G,wBAAgB,SAAS,IAAI,SAAS,CAErC;AAED,kEAAkE;AAClE,wBAAgB,UAAU,IAAI,SAAS,CAEtC;AAED,iEAAiE;AACjE,wBAAgB,WAAW,IAAI,SAAS,CAEvC"}
@@ -0,0 +1,160 @@
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
+ import { AuthzAdminFailure } from '@spinajs/authz';
11
+ import { resolveAuthzDomain } from '@spinajs/authz-http';
12
+ import { Config } from '@spinajs/configuration';
13
+ import { Autoinject, Injectable } from '@spinajs/di';
14
+ import { Parameter, Route, RouteArgs } from '@spinajs/http';
15
+ import { isPlainObject } from '@spinajs/util';
16
+ import { BATCH_ENVELOPE_SCHEMA } from '../dto/batch.js';
17
+ import { AuthzCommandSchemaRegistry } from '../schemas/registry.js';
18
+ import { inputFailure } from './answers.js';
19
+ import { decodeCommands } from './decode.js';
20
+ const q = (v) => JSON.stringify(v);
21
+ /** A query string value as the type its schema property names: the query string itself has none, and the admin schemas are validated without coercion. */
22
+ function typedQuery(schema, query) {
23
+ const out = {};
24
+ for (const [key, value] of Object.entries(query)) {
25
+ const type = schema?.properties?.[key]?.type;
26
+ if (type === 'integer' && typeof value === 'string' && /^\d{1,15}$/.test(value))
27
+ out[key] = Number(value);
28
+ else if (type === 'boolean' && (value === 'true' || value === 'false'))
29
+ out[key] = value === 'true';
30
+ else
31
+ out[key] = value;
32
+ }
33
+ return out;
34
+ }
35
+ /** Route arg of `@AdminQuery()`: the whole query string as the parameter's DTO class, validated against its `@Schema`; a failure is 400 invalid_query. */
36
+ let AuthzAdminQueryArg = class AuthzAdminQueryArg extends RouteArgs {
37
+ get SupportedType() {
38
+ return 'AuthzAdminQueryArg';
39
+ }
40
+ async extract(callData, _args, param, req) {
41
+ const Dto = param.RuntimeType;
42
+ const schema = this.Validator.extractSchema(Dto);
43
+ const input = typedQuery(schema, req.query ?? {});
44
+ const [valid, errors] = this.Validator.tryValidate(schema, input);
45
+ if (!valid)
46
+ throw inputFailure('invalid_query', errors);
47
+ return { CallData: callData, Args: new Dto(input) };
48
+ }
49
+ };
50
+ AuthzAdminQueryArg = __decorate([
51
+ Injectable()
52
+ ], AuthzAdminQueryArg);
53
+ export { AuthzAdminQueryArg };
54
+ /** Route arg of `@AdminBody()`: the whole body as the parameter's DTO class. Unlike `@Body()`, a body key named as the parameter is not taken for the body. */
55
+ let AuthzAdminBodyArg = class AuthzAdminBodyArg extends RouteArgs {
56
+ get SupportedType() {
57
+ return 'AuthzAdminBodyArg';
58
+ }
59
+ async extract(callData, _args, param, req, _res, route) {
60
+ return { CallData: callData, Args: await this.tryHydrateParam(req.body ?? null, param, route) };
61
+ }
62
+ };
63
+ AuthzAdminBodyArg = __decorate([
64
+ Injectable()
65
+ ], AuthzAdminBodyArg);
66
+ export { AuthzAdminBodyArg };
67
+ /**
68
+ * Route arg of `@AdminBatch()`: the body of POST /authz/commands. The envelope is checked against
69
+ * BATCH_ENVELOPE_SCHEMA and each command against the schema AuthzCommandSchemaRegistry holds for its
70
+ * kind, read on each request so that a late AuthzCommandSchemaSource counts; a kind no source
71
+ * describes is refused. A failure is 400 invalid_request (not an object) or invalid_batch.
72
+ */
73
+ let AuthzAdminBatchArg = class AuthzAdminBatchArg extends RouteArgs {
74
+ constructor() {
75
+ super(...arguments);
76
+ // Ajv caches every schema object it compiled for good, so the copies are keyed by content: sources may build fresh objects per call.
77
+ this.strictCopies = new Map();
78
+ }
79
+ get SupportedType() {
80
+ return 'AuthzAdminBatchArg';
81
+ }
82
+ async extract(callData, _args, _param, req) {
83
+ const body = req.body;
84
+ if (!isPlainObject(body))
85
+ throw new AuthzAdminFailure('invalid_request', 'the body must be an object { commands, reason?, idempotencyKey?, dryRun? }');
86
+ const [valid, errors] = this.Validator.tryValidate(BATCH_ENVELOPE_SCHEMA, body);
87
+ if (!valid)
88
+ throw inputFailure('invalid_batch', errors);
89
+ const schemas = this.Registry.commands();
90
+ const commands = body.commands;
91
+ commands.forEach((command, i) => {
92
+ if (!Object.hasOwn(schemas, command.kind))
93
+ throw new AuthzAdminFailure('invalid_batch', `command ${i} has kind ${q(command.kind)}, which no AuthzCommandSchemaSource describes`, `commands.${i}.kind`);
94
+ const [ok, failures] = this.Validator.tryValidate(this.strict(command.kind, schemas[command.kind]), command);
95
+ if (!ok)
96
+ throw inputFailure('invalid_batch', failures, ['commands', String(i)]);
97
+ });
98
+ const options = {};
99
+ for (const key of ['reason', 'idempotencyKey', 'dryRun'])
100
+ if (key in body)
101
+ options[key] = body[key];
102
+ const batch = { commands: decodeCommands(commands), options };
103
+ return { CallData: callData, Args: batch };
104
+ }
105
+ /** The command schema under an `authz.` id, which the validation package checks without coercion. */
106
+ strict(kind, schema) {
107
+ const key = `${kind}\n${JSON.stringify(schema)}`;
108
+ let copy = this.strictCopies.get(key);
109
+ if (!copy)
110
+ this.strictCopies.set(key, (copy = { ...schema, $id: `authz.admin.command.${kind}` }));
111
+ return copy;
112
+ }
113
+ };
114
+ __decorate([
115
+ Autoinject(AuthzCommandSchemaRegistry),
116
+ __metadata("design:type", AuthzCommandSchemaRegistry)
117
+ ], AuthzAdminBatchArg.prototype, "Registry", void 0);
118
+ AuthzAdminBatchArg = __decorate([
119
+ Injectable()
120
+ ], AuthzAdminBatchArg);
121
+ export { AuthzAdminBatchArg };
122
+ /** Route arg of `@AdminDomain()`: the authz domain of the request as the AuthzDomainResolver names it, `authz.http.admin.domain` being its fallback. */
123
+ let AuthzAdminDomainArg = class AuthzAdminDomainArg extends RouteArgs {
124
+ constructor() {
125
+ super(...arguments);
126
+ // Before the inputs, so that an unknown domain is refused before the input is checked.
127
+ this.Priority = 10;
128
+ }
129
+ get SupportedType() {
130
+ return 'AuthzAdminDomainArg';
131
+ }
132
+ async extract(callData, _args, _param, req) {
133
+ return { CallData: callData, Args: await resolveAuthzDomain(req, this.FallbackDomain) };
134
+ }
135
+ };
136
+ __decorate([
137
+ Config('authz.http.admin.domain'),
138
+ __metadata("design:type", String)
139
+ ], AuthzAdminDomainArg.prototype, "FallbackDomain", void 0);
140
+ AuthzAdminDomainArg = __decorate([
141
+ Injectable()
142
+ ], AuthzAdminDomainArg);
143
+ export { AuthzAdminDomainArg };
144
+ /** The whole query string as the parameter's `@Schema` DTO class; 400 invalid_query when it breaks the schema. */
145
+ export function AdminQuery() {
146
+ return Route(Parameter('AuthzAdminQueryArg', null));
147
+ }
148
+ /** The whole body as the parameter's `@Schema` DTO class; 400 invalid_request when it breaks the schema. */
149
+ export function AdminBody() {
150
+ return Route(Parameter('AuthzAdminBodyArg', null, { required: true }));
151
+ }
152
+ /** The body of POST /authz/commands as AuthzAdminCommandBatch. */
153
+ export function AdminBatch() {
154
+ return Route(Parameter('AuthzAdminBatchArg', null));
155
+ }
156
+ /** The authz domain the admin routes run in for this request. */
157
+ export function AdminDomain() {
158
+ return Route(Parameter('AuthzAdminDomainArg', null));
159
+ }
160
+ //# sourceMappingURL=args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.js","sourceRoot":"","sources":["../../../src/routes/args.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,7 @@
1
+ export * from './answers.js';
2
+ export * from './args.js';
1
3
  export * from './decode.js';
4
+ export * from './no-store.js';
2
5
  export * from './query.js';
3
6
  export * from './status.js';
4
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/routes/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/routes/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC"}
@@ -1,4 +1,7 @@
1
+ export * from './answers.js';
2
+ export * from './args.js';
1
3
  export * from './decode.js';
4
+ export * from './no-store.js';
2
5
  export * from './query.js';
3
6
  export * from './status.js';
4
7
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/routes/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/routes/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { RouteMiddleware } from '@spinajs/http';
2
+ import type * as express from 'express';
3
+ /** For routes whose answer may hold a link token: no proxy or browser cache may keep one. Set before the route runs, so it goes out with any answer it gives. */
4
+ export declare class NoStore extends RouteMiddleware {
5
+ isEnabled(): boolean;
6
+ onBefore(_req: express.Request, res: express.Response): Promise<void>;
7
+ onAfter(): Promise<void>;
8
+ onResponse(): Promise<void>;
9
+ }
10
+ //# sourceMappingURL=no-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-store.d.ts","sourceRoot":"","sources":["../../../src/routes/no-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,KAAK,OAAO,MAAM,SAAS,CAAC;AAExC,iKAAiK;AACjK,qBAAa,OAAQ,SAAQ,eAAe;IACnC,SAAS,IAAI,OAAO,CAE1B;IAEY,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAGjF;IAEY,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAG;IAE3B,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAG;CAC5C"}
@@ -0,0 +1,14 @@
1
+ import { RouteMiddleware } from '@spinajs/http';
2
+ /** For routes whose answer may hold a link token: no proxy or browser cache may keep one. Set before the route runs, so it goes out with any answer it gives. */
3
+ export class NoStore extends RouteMiddleware {
4
+ isEnabled() {
5
+ return true;
6
+ }
7
+ async onBefore(_req, res) {
8
+ res.setHeader('Cache-Control', 'no-store');
9
+ res.setHeader('Pragma', 'no-cache');
10
+ }
11
+ async onAfter() { }
12
+ async onResponse() { }
13
+ }
14
+ //# sourceMappingURL=no-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-store.js","sourceRoot":"","sources":["../../../src/routes/no-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGhD,iKAAiK;AACjK,MAAM,OAAO,OAAQ,SAAQ,eAAe;IACnC,SAAS;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,KAAK,CAAC,QAAQ,CAAC,IAAqB,EAAE,GAAqB;QAChE,GAAG,CAAC,SAAS,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;QAC3C,GAAG,CAAC,SAAS,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IACtC,CAAC;IAEM,KAAK,CAAC,OAAO,KAAmB,CAAC;IAEjC,KAAK,CAAC,UAAU,KAAmB,CAAC;CAC5C"}
@@ -1,6 +1,5 @@
1
1
  import type { AuthzAdminOptions, AuthzAdminQuery, PrincipalRef, ResourceRef } from '@spinajs/authz';
2
- /** A parsed query string (express: string, string[] or a nested object per key). */
3
- export type QueryInput = Readonly<Record<string, unknown>>;
2
+ import type { AuthzAdminPageQuery, AuthzAssignmentsQuery, AuthzHoldersQuery, AuthzWriteOptionsQuery } from '../dto/queries.js';
4
3
  /** authz-rbac's AssignmentSubject; the list queries belong to models this package does not import. */
5
4
  type AssignmentSubject = PrincipalRef | {
6
5
  readonly set: {
@@ -13,12 +12,12 @@ export declare function parseResourceRef(value: string, field: string): Resource
13
12
  /** `<type>:<id>` (a principal) or `set:<role>@<type>:<id>` (a subject set). */
14
13
  export declare function parseAssignmentSubject(value: string, field?: string): AssignmentSubject;
15
14
  /** GET /authz/assignments: `scope`, `subject`, `role`, `includeExpired`, `limit`, `offset` or `after`. */
16
- export declare function readAssignmentsQuery(q: QueryInput): AuthzAdminQuery;
15
+ export declare function readAssignmentsQuery(q: AuthzAssignmentsQuery): AuthzAdminQuery;
17
16
  /** GET /authz/holders: `scope` and `permission` (both required), `expandSets`, `limit`, `offset` or `after`. */
18
- export declare function readHoldersQuery(q: QueryInput): AuthzAdminQuery;
19
- /** GET /authz/links and /authz/rules: `scope`, `limit`, `offset` or `after`; GET /authz/policies has no `after`. */
20
- export declare function readPageQuery(kind: 'links' | 'rules' | 'policies', q: QueryInput): AuthzAdminQuery;
17
+ export declare function readHoldersQuery(q: AuthzHoldersQuery): AuthzAdminQuery;
18
+ /** GET /authz/links, /authz/rules and /authz/policies: `scope`, `limit`, `offset` or `after` (policies have no `after`, which their query DTO refuses). */
19
+ export declare function readPageQuery(kind: 'links' | 'rules' | 'policies', q: AuthzAdminPageQuery): AuthzAdminQuery;
21
20
  /** The AuthzAdminOptions of a single-command route: `reason`, `idempotencyKey`, `dryRun`. */
22
- export declare function readWriteOptions(q: QueryInput): AuthzAdminOptions;
21
+ export declare function readWriteOptions(q: AuthzWriteOptionsQuery): AuthzAdminOptions;
23
22
  export {};
24
23
  //# sourceMappingURL=query.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../../src/routes/query.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAEpG,oFAAoF;AACpF,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAI3D,sGAAsG;AACtG,KAAK,iBAAiB,GAAG,YAAY,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAA;KAAE,CAAA;CAAE,CAAC;AAajH,kGAAkG;AAClG,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,CAS1E;AAED,+EAA+E;AAC/E,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,SAAY,GAAG,iBAAiB,CAa1F;AAsCD,0GAA0G;AAC1G,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,UAAU,GAAG,eAAe,CAYnE;AAED,gHAAgH;AAChH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,UAAU,GAAG,eAAe,CAa/D;AAED,oHAAoH;AACpH,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,UAAU,EAAE,CAAC,EAAE,UAAU,GAAG,eAAe,CAGlG;AAED,6FAA6F;AAC7F,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,UAAU,GAAG,iBAAiB,CASjE"}
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../../src/routes/query.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAEpG,OAAO,KAAK,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAI/H,sGAAsG;AACtG,KAAK,iBAAiB,GAAG,YAAY,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAA;KAAE,CAAA;CAAE,CAAC;AAMjH,kGAAkG;AAClG,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,CAS1E;AAED,+EAA+E;AAC/E,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,SAAY,GAAG,iBAAiB,CAa1F;AAcD,0GAA0G;AAC1G,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,qBAAqB,GAAG,eAAe,CAS9E;AAED,gHAAgH;AAChH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,iBAAiB,GAAG,eAAe,CAStE;AAED,2JAA2J;AAC3J,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,UAAU,EAAE,CAAC,EAAE,mBAAmB,GAAG,eAAe,CAE3G;AAED,6FAA6F;AAC7F,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,sBAAsB,GAAG,iBAAiB,CAM7E"}
@@ -2,14 +2,6 @@ import { AuthzAdminFailure, GLOBAL } from '@spinajs/authz';
2
2
  function invalid(field, message) {
3
3
  throw new AuthzAdminFailure('invalid_query', message, field);
4
4
  }
5
- function text(q, field) {
6
- const v = q[field];
7
- if (v === undefined)
8
- return undefined;
9
- if (typeof v !== 'string')
10
- invalid(field, `${field} must be given once, as text`);
11
- return v;
12
- }
13
5
  /** `<type>` or `<type>:<id>`, split at the first `:` (ids may hold more); `$global` is GLOBAL. */
14
6
  export function parseResourceRef(value, field) {
15
7
  if (value === GLOBAL.type)
@@ -43,90 +35,51 @@ export function parseAssignmentSubject(value, field = 'subject') {
43
35
  return bad();
44
36
  return { type: value.slice(0, at), id: value.slice(at + 1) };
45
37
  }
46
- function flag(q, field) {
47
- const v = text(q, field);
48
- if (v === undefined)
49
- return undefined;
50
- if (v !== 'true' && v !== 'false')
51
- invalid(field, `${field} must be true or false`);
52
- return v === 'true';
53
- }
54
- function count(q, field) {
55
- const v = text(q, field);
56
- if (v === undefined)
57
- return undefined;
58
- if (!/^\d+$/.test(v))
59
- invalid(field, `${field} must be a non-negative integer`);
60
- return Number(v);
61
- }
62
- /** `after`, the `next` of the previous page; it replaces `offset`. */
63
- function cursor(q, offset) {
64
- const after = text(q, 'after');
65
- if (after === '')
66
- invalid('after', 'after must not be empty');
38
+ /** `limit`, `offset` and `after` as AuthzAdmin's page, only the ones given; AuthzAdmin defaults the rest. `after` replaces `offset`. */
39
+ function page(q) {
40
+ const { limit, offset, after } = q;
67
41
  if (after !== undefined && offset !== undefined)
68
42
  invalid('after', 'after replaces offset: give one of them');
69
- return after;
70
- }
71
- /** `limit`, `offset` and `after` as AuthzAdmin's page, only the ones given; AuthzAdmin defaults the rest. */
72
- function page(q) {
73
- const limit = count(q, 'limit');
74
- const offset = count(q, 'offset');
75
- const after = cursor(q, offset);
76
43
  if (limit === undefined && offset === undefined && after === undefined)
77
44
  return {};
78
45
  return { page: { ...(limit === undefined ? {} : { limit }), ...(offset === undefined ? {} : { offset }), ...(after === undefined ? {} : { after }) } };
79
46
  }
80
47
  function scope(q) {
81
- const v = text(q, 'scope');
82
- return v === undefined ? {} : { scope: parseResourceRef(v, 'scope') };
48
+ return q.scope === undefined ? {} : { scope: parseResourceRef(q.scope, 'scope') };
83
49
  }
84
50
  /** GET /authz/assignments: `scope`, `subject`, `role`, `includeExpired`, `limit`, `offset` or `after`. */
85
51
  export function readAssignmentsQuery(q) {
86
- const subject = text(q, 'subject');
87
- const role = text(q, 'role');
88
- const includeExpired = flag(q, 'includeExpired');
89
52
  return {
90
53
  kind: 'assignments',
91
54
  ...scope(q),
92
- ...(subject === undefined ? {} : { subject: parseAssignmentSubject(subject) }),
93
- ...(role === undefined ? {} : { role }),
94
- ...(includeExpired === undefined ? {} : { includeExpired }),
55
+ ...(q.subject === undefined ? {} : { subject: parseAssignmentSubject(q.subject) }),
56
+ ...(q.role === undefined ? {} : { role: q.role }),
57
+ ...(q.includeExpired === undefined ? {} : { includeExpired: q.includeExpired }),
95
58
  ...page(q),
96
59
  };
97
60
  }
98
61
  /** GET /authz/holders: `scope` and `permission` (both required), `expandSets`, `limit`, `offset` or `after`. */
99
62
  export function readHoldersQuery(q) {
100
- const scope = text(q, 'scope');
101
- const permission = text(q, 'permission');
102
- if (scope === undefined)
63
+ if (q.scope === undefined)
103
64
  invalid('scope', 'scope is required');
104
- if (permission === undefined || permission === '')
105
- invalid('permission', 'permission is required');
106
- const expandSets = flag(q, 'expandSets');
107
65
  return {
108
66
  kind: 'holders',
109
- scope: parseResourceRef(scope, 'scope'),
110
- permission,
111
- ...(expandSets === undefined ? {} : { expandSets }),
67
+ scope: parseResourceRef(q.scope, 'scope'),
68
+ permission: q.permission,
69
+ ...(q.expandSets === undefined ? {} : { expandSets: q.expandSets }),
112
70
  ...page(q),
113
71
  };
114
72
  }
115
- /** GET /authz/links and /authz/rules: `scope`, `limit`, `offset` or `after`; GET /authz/policies has no `after`. */
73
+ /** GET /authz/links, /authz/rules and /authz/policies: `scope`, `limit`, `offset` or `after` (policies have no `after`, which their query DTO refuses). */
116
74
  export function readPageQuery(kind, q) {
117
- if (kind === 'policies' && text(q, 'after') !== undefined)
118
- invalid('after', 'policies are paged by offset: after is not supported');
119
75
  return { kind, ...scope(q), ...page(q) };
120
76
  }
121
77
  /** The AuthzAdminOptions of a single-command route: `reason`, `idempotencyKey`, `dryRun`. */
122
78
  export function readWriteOptions(q) {
123
- const reason = text(q, 'reason');
124
- const idempotencyKey = text(q, 'idempotencyKey');
125
- const dryRun = flag(q, 'dryRun');
126
79
  return {
127
- ...(reason === undefined ? {} : { reason }),
128
- ...(idempotencyKey === undefined ? {} : { idempotencyKey }),
129
- ...(dryRun === undefined ? {} : { dryRun }),
80
+ ...(q.reason === undefined ? {} : { reason: q.reason }),
81
+ ...(q.idempotencyKey === undefined ? {} : { idempotencyKey: q.idempotencyKey }),
82
+ ...(q.dryRun === undefined ? {} : { dryRun: q.dryRun }),
130
83
  };
131
84
  }
132
85
  //# sourceMappingURL=query.js.map