@jwilleke/ngdpbase-types 5.43.0 → 5.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/lib/src/context/ApiContext.d.ts +10 -3
  2. package/lib/src/context/ApiContext.js +36 -3
  3. package/lib/src/ice/runExport.d.ts +8 -3
  4. package/lib/src/ice/searchExportSource.d.ts +44 -0
  5. package/lib/src/ice/types.d.ts +6 -0
  6. package/lib/src/managers/AttachmentManager.d.ts +11 -0
  7. package/lib/src/managers/AuditManager.d.ts +0 -1
  8. package/lib/src/managers/AuthManager.d.ts +38 -0
  9. package/lib/src/managers/AuthManager.js +84 -12
  10. package/lib/src/managers/BackupManager.d.ts +9 -2
  11. package/lib/src/managers/BackupManager.js +42 -19
  12. package/lib/src/managers/BaseManager.d.ts +17 -3
  13. package/lib/src/managers/BaseManager.js +12 -8
  14. package/lib/src/managers/ConfigurationManager.d.ts +13 -0
  15. package/lib/src/managers/ConsentManager.d.ts +1 -1
  16. package/lib/src/managers/DatabaseManager.js +17 -8
  17. package/lib/src/managers/EmailManager.d.ts +1 -1
  18. package/lib/src/managers/ExportManager.d.ts +1 -44
  19. package/lib/src/managers/ExportManager.js +3 -115
  20. package/lib/src/managers/ImportManager.d.ts +7 -0
  21. package/lib/src/managers/PageManager.d.ts +9 -0
  22. package/lib/src/managers/PolicyEvaluator.d.ts +113 -30
  23. package/lib/src/managers/ThemeManager.d.ts +20 -1
  24. package/lib/src/providers/FileLoggingProvider.d.ts +12 -1
  25. package/lib/src/providers/FileLoggingProvider.js +37 -4
  26. package/lib/src/security/PolicyDecisionPoint.d.ts +50 -3
  27. package/lib/src/security/PolicyInformationPoint.d.ts +27 -1
  28. package/lib/src/security/ownedRecords.d.ts +69 -0
  29. package/lib/src/security/signedOutWrites.d.ts +69 -0
  30. package/lib/src/security/signedOutWrites.js +146 -0
  31. package/lib/src/types/Policy.d.ts +26 -30
  32. package/lib/src/utils/addonConfigLayer.d.ts +6 -3
  33. package/lib/src/utils/addonConfigLayer.js +61 -3
  34. package/lib/src/utils/addonHost.d.ts +25 -0
  35. package/lib/src/utils/addonHost.js +29 -1
  36. package/lib/src/utils/availability.d.ts +15 -0
  37. package/lib/src/utils/availability.js +88 -0
  38. package/lib/src/utils/pageTitleConflict.d.ts +32 -0
  39. package/lib/src/utils/pageWritePolicies.d.ts +48 -29
  40. package/lib/src/utils/plainAttention.d.ts +19 -0
  41. package/lib/src/utils/plainAttention.js +18 -0
  42. package/lib/src/utils/policyAttributes.d.ts +113 -22
  43. package/lib/src/utils/policyAttributes.js +228 -43
  44. package/lib/src/utils/roleGrants.d.ts +1 -1
  45. package/package.json +7 -7
@@ -1,39 +1,34 @@
1
+ import type { Policy } from '../types/Policy.js';
1
2
  /**
2
- * The page-write policies after #2255, and the migration of a site's stored
3
- * copies of the old ones.
4
- *
5
- * Until #2255 the shipped role policies granted `page-edit`, `page-delete` and
6
- * `page-rename` on every page (`page: *`), and an `access: { edit: [admin] }`
7
- * stamp on each shipped page was the only thing keeping editors out of the
8
- * system and documentation pages. Those grants now sit on the
9
- * `system-category` resource type, one policy per group of categories, and the
10
- * stamp is gone.
11
- *
12
- * A site that ever saved `ngdpbase.access.policies` (the configuration editor,
13
- * the Shared folders screen) holds a full copy of the old role policies, and a
14
- * stored entry replaces the shipped one with the same id whole
15
- * (`src/utils/configFiles.ts`). Its `page-edit` on `page: *` would reopen every
16
- * pushed page to editors. So, before the merge, in memory:
17
- *
18
- * - a stored entry with a shipped id below loses the page writes it held on
19
- * `page: *`; any it held that the shipped category policies do not give that
20
- * role is kept, on the general category only, as a new policy
21
- * `<id>-page-write`;
22
- * - every other policy that grants a page write on a `page` resource to a role
23
- * other than admin, and every deny policy (a deny now overrides an allow
24
- * whatever its priority), is reported and left as it is: it is the site's
25
- * own choice.
26
- *
27
- * Pure: the caller logs and reports. The site's file is not rewritten; saving
28
- * the policy list from the configuration editor writes the migrated list.
3
+ * Where the denies an administrator marked as checked are kept (#2355): rule id to the fingerprint of
4
+ * the rule as it was then. A mark hides the dashboard item and is read by nothing that decides access.
29
5
  */
30
- import type { Policy } from '../types/Policy.js';
6
+ export declare const CHECKED_DENIES_KEY = "ngdpbase.access.checked-denies";
7
+ /** Where the "Mark as checked" button on the dashboard item posts (#2355). */
8
+ export declare const DENY_CHECKED_ACTION = "/admin/access-policies/deny-checked";
9
+ /** A stable hash of a whole rule, its id included, so a changed rule (or the same content under another name) is a different one (#2355). */
10
+ export declare function policyFingerprint(policy: Policy): string;
31
11
  /** What the migration did and found, one sentence each. */
32
12
  export interface PageWritePolicyReport {
33
13
  /** Stored shipped policies rewritten in memory. */
34
14
  rewritten: string[];
35
15
  /** Policies left alone that now decide differently, or reopen pushed pages. */
36
16
  review: string[];
17
+ /** Each `rewritten` line, in plain words, for the needs-attention entry (no permission ids, issue numbers or setting names). */
18
+ shown: Record<string, string>;
19
+ }
20
+ /** One finding for the start-up log (`log`, in full) and for the needs-attention entry (`plain`, in plain words). */
21
+ export interface PolicyFinding {
22
+ log: string;
23
+ plain: string;
24
+ /** Set when the finding is an allow rule the upgrade notice already lists (`openWriteRules`); the needs-attention item leaves it out. */
25
+ coveredByUpgradeNotice?: boolean;
26
+ /** Set on a deny (#2355): the rule, its fingerprint now, and whether an administrator marked exactly this content as checked. */
27
+ deny?: {
28
+ id: string;
29
+ fingerprint: string;
30
+ checked: boolean;
31
+ };
37
32
  }
38
33
  /**
39
34
  * Rewrite the stored copies of the moved shipped policies, in `policies` (the
@@ -50,6 +45,30 @@ export declare function migrateStoredPageWritePolicies(policies: unknown): {
50
45
  * allow that grants a page write on a `page` resource to a role other than
51
46
  * admin (it reaches pushed pages), an allow that grants anything but
52
47
  * page-read to `anyone` or `authenticated` (#2261, #2283), and every deny (a deny now overrides any
53
- * allow, whatever the priorities).
48
+ * allow; one an administrator marked as checked is still reported, with `deny.checked` set, #2355). Each is a log line in full and the same finding in plain words.
54
49
  */
50
+ export declare function pageWritePolicyFindings(policies: readonly Policy[], checked?: Readonly<Record<string, string>>): PolicyFinding[];
51
+ /** The log lines of {@link pageWritePolicyFindings}. */
55
52
  export declare function pageWritePoliciesToReview(policies: readonly Policy[]): string[];
53
+ /** An allow rule in force that lets more people write than the shipped rules do (#2355 handles denies, not this). */
54
+ export interface OpenWriteRule {
55
+ id: string;
56
+ /** Who: everyone including signed-out visitors, every signed-in user, or the named roles other than admin. */
57
+ who: {
58
+ kind: 'anyone';
59
+ } | {
60
+ kind: 'authenticated';
61
+ } | {
62
+ kind: 'roles';
63
+ roles: string[];
64
+ };
65
+ /** The actions it grants; for `anyone` and `authenticated`, without page-read. `*` means everything. */
66
+ actions: string[];
67
+ resources: NonNullable<Policy['resources']>;
68
+ }
69
+ /**
70
+ * The allow rules in force that let `anyone` (signed-out visitors) or `authenticated` (every signed-in user)
71
+ * do more than page-read, or give page writes to a role other than admin. Deny rules are left out.
72
+ * Computed from the policies it is given, so what it returns follows the current policies.
73
+ */
74
+ export declare function openWriteRules(policies: readonly Policy[]): OpenWriteRule[];
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Plain wording for dashboard items that more than one manager raises (#2354).
3
+ *
4
+ * The dashboard's "needs attention" and "not working" items are read by home
5
+ * users. Each says what is wrong and one thing to do, with no issue numbers,
6
+ * setting names, environment variable names, file paths or "see the log". The
7
+ * developer detail goes to the log, beside the call that marks the item.
8
+ */
9
+ /** Where a staged restore is looked at and cancelled: the Backup page. */
10
+ export declare const STAGED_RESTORE_FIX: {
11
+ fixUrl: string;
12
+ fixLabel: string;
13
+ };
14
+ /** A staged restore that was set aside at start-up instead of put back (#1876, #1985). */
15
+ export declare function stagedRestoreNotApplied(what: string): string;
16
+ /** Said where the fix is a setting only the server can change: the app refuses to save it. */
17
+ export declare const IN_SERVER_SETTINGS = "This is set in the server's settings, outside this page.";
18
+ /** A configured folder on a drive that is not connected (`preflightConfiguredPath`). */
19
+ export declare const UNUSABLE_FOLDER_REASON = "The drive or folder this feature keeps its files on is not connected, so it is switched off. Connect the drive again, or choose another folder, then restart the site.";
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Plain wording for dashboard items that more than one manager raises (#2354).
3
+ *
4
+ * The dashboard's "needs attention" and "not working" items are read by home
5
+ * users. Each says what is wrong and one thing to do, with no issue numbers,
6
+ * setting names, environment variable names, file paths or "see the log". The
7
+ * developer detail goes to the log, beside the call that marks the item.
8
+ */
9
+ /** Where a staged restore is looked at and cancelled: the Backup page. */
10
+ export const STAGED_RESTORE_FIX = { fixUrl: '/admin/backup', fixLabel: 'Open Admin → Backup' };
11
+ /** A staged restore that was set aside at start-up instead of put back (#1876, #1985). */
12
+ export function stagedRestoreNotApplied(what) {
13
+ return `A saved copy of ${what} was not put back when the site started, so what was there before is still in use. Open the Backup page to see what to do next.`;
14
+ }
15
+ /** Said where the fix is a setting only the server can change: the app refuses to save it. */
16
+ export const IN_SERVER_SETTINGS = "This is set in the server's settings, outside this page.";
17
+ /** A configured folder on a drive that is not connected (`preflightConfiguredPath`). */
18
+ export const UNUSABLE_FOLDER_REASON = 'The drive or folder this feature keeps its files on is not connected, so it is switched off. Connect the drive again, or choose another folder, then restart the site.';
@@ -1,38 +1,72 @@
1
1
  /**
2
- * The vocabulary of a policy `condition` (#2261): attribute types, the
3
- * operator table, the nesting limit, and how one comparison is decided.
2
+ * The vocabulary of a policy `condition` (#2261, #2330): attribute types, the
3
+ * function table, the nesting limit, and how one comparison is decided.
4
4
  * Pure: no I/O, no manager. The evaluator and the validator both import it,
5
- * so the set of operators lives here and nowhere else.
5
+ * so the set of functions lives here and nowhere else.
6
+ *
7
+ * A condition follows XACML 3.0 in lowercase (#2330). A function is a key
8
+ * named for its XACML function, `string-equal`, whose value is the array of its
9
+ * arguments. An argument is an attribute, `{ "attributeid": "subject:id",
10
+ * "datatype": "string" }`, or a literal, `{ "value": "sales", "datatype":
11
+ * "string" }`. `datatype` is required on both.
6
12
  */
13
+ import type { PolicyFinding } from './pageWritePolicies.js';
7
14
  /** The types an attribute can be declared with. */
8
15
  export declare const ATTRIBUTE_TYPES: readonly ["string", "integer", "boolean", "identity", "list"];
9
16
  export type AttributeType = (typeof ATTRIBUTE_TYPES)[number];
10
17
  /**
11
- * How deep a condition may nest. Every node counts, leaves included, so
12
- * `any-of` > `all-of` > `not` > leaf is 4 and one more level is refused.
18
+ * The datatypes a condition may name: the XACML 3.0 JSON profile's short
19
+ * names. Only `string`, `integer` and `boolean` have a function today, so a
20
+ * condition naming any other is refused as a datatype its function does not take.
21
+ */
22
+ export declare const DATATYPES: readonly ["string", "integer", "boolean", "double", "date", "time", "dateTime", "anyURI"];
23
+ /** The datatypes some function takes. */
24
+ export type FunctionType = 'string' | 'integer' | 'boolean';
25
+ /**
26
+ * How deep a condition may nest. Every function node counts, arguments that
27
+ * are attributes or values do not, so `or` > `and` > `not` > `string-equal` is 4
28
+ * and one more level is refused.
13
29
  */
14
30
  export declare const MAX_CONDITION_DEPTH = 4;
15
31
  /**
16
32
  * How wide a condition may be (#2261). Depth alone leaves the tree as wide as
17
33
  * a config file can make it, and the evaluator walks it for every page a
18
- * listing or search asks about. A literal `in` list, the children of one
19
- * `any-of` or `all-of`, and the nodes of the whole condition are each capped.
34
+ * listing or search asks about. A literal `value` list in an `is-in`, the
35
+ * arguments of one `and` or `or`, and the function nodes of the whole condition
36
+ * are each capped.
20
37
  */
21
38
  export declare const MAX_IN_ITEMS = 256;
22
39
  export declare const MAX_GROUP_CHILDREN = 256;
23
40
  export declare const MAX_CONDITION_NODES = 512;
24
- /** What a comparison against an attribute accepts, by operator. */
25
- interface LeafOperator {
26
- /** Types the attribute on the left may have. */
27
- left: readonly AttributeType[];
41
+ /** What a comparison does once both arguments are read. */
42
+ export type ComparisonKind = 'equal' | 'is-in' | 'greater-than' | 'greater-than-or-equal' | 'less-than' | 'less-than-or-equal';
43
+ /** One function that compares two arguments: the datatype it takes and what it does. */
44
+ export interface ConditionFunction {
45
+ type: FunctionType;
46
+ kind: ComparisonKind;
28
47
  }
29
- /** The operators that compare one attribute with a value. */
30
- export declare const LEAF_OPERATORS: Readonly<Record<string, LeafOperator>>;
31
- /** The operators that combine conditions. `not` takes one condition, these take a list. */
32
- export declare const GROUP_OPERATORS: readonly ["any-of", "all-of"];
33
- export declare const NOT_OPERATOR = "not";
34
- /** Every operator, in the order the validator lists them. */
35
- export declare const CONDITION_OPERATORS: readonly string[];
48
+ /**
49
+ * The functions that compare two arguments, by XACML 3.0 name (core spec,
50
+ * appendix A.3), in lowercase. `X-is-in` takes a value, then a bag: an attribute
51
+ * that is a list, or a literal whose `value` is an array.
52
+ */
53
+ export declare const COMPARISON_FUNCTIONS: Readonly<Record<string, ConditionFunction>>;
54
+ /** The functions that combine conditions: XACML's logical functions. `not` takes one condition, these take a list. */
55
+ export declare const GROUP_FUNCTIONS: readonly ["and", "or"];
56
+ export declare const NOT_FUNCTION = "not";
57
+ /** Every function, in the order the validator lists them. */
58
+ export declare const CONDITION_FUNCTIONS: readonly string[];
59
+ /** The keys of an argument: an attribute or a literal, and its datatype. */
60
+ export declare const OPERAND_KEYS: readonly ["attributeid", "value", "datatype"];
61
+ /**
62
+ * The shape before #2330, key by key, and what replaces it, so the validator
63
+ * can say what to write. Not read by the evaluator: an old condition never holds.
64
+ */
65
+ export declare const LEGACY_CONDITION_KEYS: Readonly<Record<string, string>>;
66
+ /** The one example the validator shows for the old shape. */
67
+ export declare const CONDITION_EXAMPLE = "{ \"string-equal\": [ { \"attributeid\": \"subject:department-id\", \"datatype\": \"string\" }, { \"value\": \"sales\", \"datatype\": \"string\" } ] }";
68
+ /** The datatype an attribute of a declared type is referenced with: an identity is a string. A list has the datatype of its entries. */
69
+ export declare function datatypeOf(attributeType: string): string | null;
36
70
  /** The type a literal value has, or `null` when it is not a usable literal. */
37
71
  export declare function literalType(value: unknown): 'string' | 'integer' | 'boolean' | null;
38
72
  /** Can a literal be compared with an attribute of this type? An identity is a string. */
@@ -47,13 +81,21 @@ export declare function literalFits(attributeType: string, value: unknown): bool
47
81
  export declare function valueFits(attributeType: string, value: unknown): boolean;
48
82
  /**
49
83
  * Decides one comparison once both sides are read. `undefined` is unknown: a
50
- * side that is missing, or not of a type the operator can compare. Both sides
84
+ * side that is missing, or not of a type the function can compare. Both sides
51
85
  * must be the same kind of value (a string, a boolean or a whole number), so
52
- * "5" never equals 5 and NaN never compares. `in` takes an array, or a Set the
86
+ * "5" never equals 5 and NaN never compares. `is-in` takes an array, or a Set the
53
87
  * evaluator built from a literal list; every entry of an array must be the
54
88
  * kind of value on the left. An empty string is a value, not a missing one.
55
89
  */
56
- export declare function compareLeaf(operator: string, left: unknown, right: unknown): boolean | undefined;
90
+ export declare function compareLeaf(kind: ComparisonKind, left: unknown, right: unknown): boolean | undefined;
91
+ /** The key that names how rules are combined (#2330). */
92
+ export declare const RULE_COMBINING_ALGORITHM_KEY = "ngdpbase.access.rule-combining-algorithm";
93
+ /** The only algorithm the evaluator implements; XACML's name for it. */
94
+ export declare const SUPPORTED_COMBINING_ALGORITHMS: readonly string[];
95
+ /** What Admin → Configuration says about the algorithm. */
96
+ export declare const DENY_OVERRIDES_EXPLANATION = "Any matching deny wins. Order and priority don't matter.";
97
+ /** What is wrong with the value of `ngdpbase.access.rule-combining-algorithm`, or `null`. Used on save, on load and at boot. */
98
+ export declare function combiningAlgorithmProblem(value: unknown): string | null;
57
99
  /** The assurance level a sign-in reached: NIST SP 800-63B, 1 to 3. */
58
100
  export type SubjectAal = 1 | 2 | 3;
59
101
  /** `value` as an assurance level, or `undefined` when it is not 1, 2 or 3. Never coerces. */
@@ -131,6 +173,8 @@ export declare function declaredSubjectAttributes(raw: unknown): Record<string,
131
173
  * declaration `subjectDeclarationProblem` refuses. Used on save, on load and at boot.
132
174
  */
133
175
  export declare function subjectAttributesProblems(raw: unknown, sensitive: readonly string[]): string[];
176
+ /** {@link subjectAttributesProblems}, each also in plain words for the needs-attention entry. */
177
+ export declare function subjectAttributesFindings(raw: unknown, sensitive: readonly string[]): PolicyFinding[];
134
178
  /**
135
179
  * What is wrong with a subject attribute's declaration, or `null`: a `type`
136
180
  * that is not known, a `from` that is not a subject source, or an account field
@@ -138,4 +182,51 @@ export declare function subjectAttributesProblems(raw: unknown, sensitive: reado
138
182
  * like). Said so a condition naming it is refused rather than silently unknown.
139
183
  */
140
184
  export declare function subjectDeclarationProblem(name: string, decl: DeclaredSubjectAttribute | undefined, sensitive: readonly string[]): string | null;
141
- export {};
185
+ /**
186
+ * A declaration map as written, every `$NAME` left unresolved, or `null` when
187
+ * it cannot be read. Declarations are read this way so a `$NAME` in one is
188
+ * judged and reported as written and an environment variable's value never
189
+ * reaches a message or a log line; a throwing read (an unset variable) is
190
+ * `null`, not an exception.
191
+ */
192
+ export declare function readDeclaredAsWritten(config: {
193
+ getUnresolvedProperty?: (key: string, def?: unknown) => unknown;
194
+ getProperty: (key: string, def?: unknown) => unknown;
195
+ } | null | undefined, key: string): unknown;
196
+ /** Where an environment attribute may be read from: `schedule:<name>` or `config:<key>` (#2261 slice 4). */
197
+ export declare const ENVIRONMENT_SOURCES: readonly ["schedule:", "config:"];
198
+ /** One declared environment attribute, as `ngdpbase.access.environment-attributes` holds it. */
199
+ export interface DeclaredEnvironmentAttribute {
200
+ type?: string;
201
+ from?: string;
202
+ }
203
+ /** The environment attributes a site declares. Anything not an object is ignored. */
204
+ export declare function declaredEnvironmentAttributes(raw: unknown): Record<string, DeclaredEnvironmentAttribute>;
205
+ /**
206
+ * What is wrong with an environment attribute's declaration, or `null`: a
207
+ * `type` that is not `boolean` (both sources yield a boolean and nothing
208
+ * else), a `from` that is not `schedule:<name>` or `config:<key>`, or one with
209
+ * no name or key after the prefix. Any configuration key may be read, secrets
210
+ * included (#2261): a condition can only compare the value, and the value is
211
+ * never written to a log, an audit record or a message.
212
+ */
213
+ export declare function environmentDeclarationProblem(name: string, decl: DeclaredEnvironmentAttribute | undefined): string | null;
214
+ /**
215
+ * What is wrong with the value of `ngdpbase.access.environment-attributes`
216
+ * itself, one message each: not an object, or a declaration
217
+ * {@link environmentDeclarationProblem} refuses. Used on save, on load and at boot.
218
+ */
219
+ export declare function environmentAttributesProblems(raw: unknown): string[];
220
+ /** {@link environmentAttributesProblems}, each also in plain words for the needs-attention entry. */
221
+ export declare function environmentAttributesFindings(raw: unknown): PolicyFinding[];
222
+ /**
223
+ * The words an administrator sees (the needs-attention entry and the save message) when a policy carries
224
+ * the old plural `conditions` array, or null when none does (#2334). Plain words: no issue number, no JSON.
225
+ */
226
+ export declare function unenforcedConditionsNotice(policies: unknown): string | null;
227
+ /**
228
+ * The start-up log line for the same policies, in full: the condition to write, the attribute
229
+ * declaration it needs, and the entry types with no equivalent (#2334). Null when none has one.
230
+ * Nothing in the decision path reads that array, so a rule written there limits no access.
231
+ */
232
+ export declare function unenforcedConditionsLine(policies: unknown): string | null;