@jwilleke/ngdpbase-types 5.40.0 → 5.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/packages/ngdpbase-types/index.d.ts +1 -1
- package/lib/src/ice/fileHandling.d.ts +6 -1
- package/lib/src/ice/runExport.d.ts +41 -0
- package/lib/src/ice/runImport.d.ts +16 -7
- package/lib/src/ice/shims/csv.d.ts +24 -0
- package/lib/src/ice/shims/export.d.ts +23 -0
- package/lib/src/ice/shims/index.d.ts +3 -1
- package/lib/src/ice/shims/svg.d.ts +27 -0
- package/lib/src/ice/shims/takeout.d.ts +83 -0
- package/lib/src/ice/types.d.ts +251 -5
- package/lib/src/ice/vet.d.ts +19 -0
- package/lib/src/managers/AttachmentManager.d.ts +86 -36
- package/lib/src/managers/AuthManager.d.ts +117 -7
- package/lib/src/managers/AuthManager.js +341 -37
- package/lib/src/managers/ExportManager.d.ts +16 -0
- package/lib/src/managers/ExportManager.js +25 -0
- package/lib/src/managers/FileManager.d.ts +182 -0
- package/lib/src/managers/ImportManager.d.ts +264 -16
- package/lib/src/managers/MediaManager.d.ts +2 -0
- package/lib/src/managers/SharedFolderManager.d.ts +320 -0
- package/lib/src/providers/BaseMediaProvider.d.ts +4 -0
- package/lib/src/providers/FileSystemMediaProvider.d.ts +6 -0
- package/lib/src/security/PolicyDecisionPoint.d.ts +3 -2
- package/lib/src/security/permissions.generated.d.ts +3 -3
- package/lib/src/types/File.d.ts +90 -0
- package/lib/src/types/express.d.ts +3 -1
- package/lib/src/types/linkedom.d.ts +2 -0
- package/lib/src/utils/auditEventNames.generated.d.ts +2 -0
- package/lib/src/utils/auditEventNames.generated.js +2 -0
- package/lib/src/utils/auditEvents.d.ts +3 -0
- package/lib/src/utils/auditEvents.js +3 -0
- package/lib/src/utils/fileMigrationPlan.d.ts +81 -0
- package/lib/src/utils/privateStoreAccess.d.ts +21 -0
- package/lib/src/utils/privateStoreAccess.js +11 -0
- package/lib/src/utils/privateStoreImport.d.ts +0 -10
- package/lib/src/utils/privateStorePath.d.ts +12 -0
- package/lib/src/utils/privateStorePath.js +18 -0
- package/lib/src/utils/recoveryWordsFile.d.ts +54 -0
- package/lib/src/utils/sessionEnd.d.ts +1 -0
- package/lib/src/utils/sessionEnd.js +4 -0
- package/lib/src/utils/sessionIdle.d.ts +4 -0
- package/lib/src/utils/sessionIdle.js +6 -0
- package/package.json +1 -1
|
@@ -38,6 +38,16 @@ export interface VaultDecider {
|
|
|
38
38
|
permit: boolean;
|
|
39
39
|
}>;
|
|
40
40
|
}
|
|
41
|
+
/** The PDP surface {@link holdsInVault} needs. */
|
|
42
|
+
export interface VaultHolder {
|
|
43
|
+
holds(subject: unknown, action: string, on: {
|
|
44
|
+
resource: {
|
|
45
|
+
type: string;
|
|
46
|
+
id: string;
|
|
47
|
+
};
|
|
48
|
+
attributes: Record<string, unknown>;
|
|
49
|
+
}): Promise<boolean>;
|
|
50
|
+
}
|
|
41
51
|
export declare function mayActInPrivateContainer(ctx: ActorContext, owner: string, opts?: {
|
|
42
52
|
vault?: string;
|
|
43
53
|
}): boolean;
|
|
@@ -59,3 +69,14 @@ export declare function permitsInVault(pdp: VaultDecider | null | undefined, ctx
|
|
|
59
69
|
vault: string;
|
|
60
70
|
resource: string;
|
|
61
71
|
}): Promise<boolean>;
|
|
72
|
+
/**
|
|
73
|
+
* Does `ctx` HOLD `action` inside `owner`'s vault (#2120)? {@link permitsInVault}
|
|
74
|
+
* without the step-up rule, for an affordance, and to tell a refusal for a
|
|
75
|
+
* stale sign-in (answered with the step-up prompt) from a plain one. Shared
|
|
76
|
+
* folders are not asked: `permitsInVault` decides them by permission alone.
|
|
77
|
+
*/
|
|
78
|
+
export declare function holdsInVault(pdp: VaultHolder | null | undefined, ctx: ActorContext, action: string, where: {
|
|
79
|
+
owner: string;
|
|
80
|
+
vault: string;
|
|
81
|
+
resource: string;
|
|
82
|
+
}): Promise<boolean>;
|
|
@@ -71,3 +71,14 @@ export async function permitsInVault(pdp, ctx, action, where) {
|
|
|
71
71
|
return false;
|
|
72
72
|
return (await pdp.decide(ctx, { action, resource: { type: 'page', id: where.resource }, attributes: { vault: where.vault } })).permit;
|
|
73
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Does `ctx` HOLD `action` inside `owner`'s vault (#2120)? {@link permitsInVault}
|
|
76
|
+
* without the step-up rule, for an affordance, and to tell a refusal for a
|
|
77
|
+
* stale sign-in (answered with the step-up prompt) from a plain one. Shared
|
|
78
|
+
* folders are not asked: `permitsInVault` decides them by permission alone.
|
|
79
|
+
*/
|
|
80
|
+
export async function holdsInVault(pdp, ctx, action, where) {
|
|
81
|
+
if (isSharedFolderOwner(where.owner) || typeof pdp?.holds !== 'function' || !mayActInPrivateContainer(ctx, where.owner, { vault: where.vault }))
|
|
82
|
+
return false;
|
|
83
|
+
return pdp.holds(ctx, action, { resource: { type: 'page', id: where.resource }, attributes: { vault: where.vault } });
|
|
84
|
+
}
|
|
@@ -46,13 +46,3 @@ export type ParsedTakeout = {
|
|
|
46
46
|
};
|
|
47
47
|
/** What a takeout's entries hold. */
|
|
48
48
|
export declare function readTakeout(entries: readonly ZipEntry[]): ParsedTakeout;
|
|
49
|
-
/** `body` with every `/attachments/{old}` link pointed at its new id. */
|
|
50
|
-
export declare function rewriteAttachmentLinks(body: string, ids: ReadonlyMap<string, string>): string;
|
|
51
|
-
/** Whether `body` links to the file `id`. */
|
|
52
|
-
export declare function linksToAttachment(body: string, id: string): boolean;
|
|
53
|
-
/**
|
|
54
|
-
* The first free title of `title`, `title (imported)`, `title (imported 2)` …
|
|
55
|
-
* (operator, 2026-09-25): a DIFFERENT page already holding the title keeps it,
|
|
56
|
-
* and the import lands beside it.
|
|
57
|
-
*/
|
|
58
|
-
export declare function freeImportTitle(title: string, isTaken: (candidate: string) => Promise<boolean>): Promise<string>;
|
|
@@ -168,6 +168,18 @@ export declare function formatPrivatePageName(owner: string, store: string, titl
|
|
|
168
168
|
* {@link SHARED_FOLDER_OWNER}'s; `vaults/shared-folders/…` is not a name.
|
|
169
169
|
*/
|
|
170
170
|
export declare function parsePrivatePageName(name: unknown): PrivatePageName | null;
|
|
171
|
+
/**
|
|
172
|
+
* A page's name for a log line (#1461, #2118, #2178): a private page's title
|
|
173
|
+
* stays out of logs, so it goes by its uuid, from its `metadata` — with its
|
|
174
|
+
* owner and store when its name holds them, and as "uuid unknown" before it
|
|
175
|
+
* has one. A private page saved under its bare title (#1520) is known only by
|
|
176
|
+
* its `metadata`. A public page goes by its name, and its uuid when known.
|
|
177
|
+
* The audit record is not a log line: it keeps the page's name.
|
|
178
|
+
*/
|
|
179
|
+
export declare function nameForLog(pageName: string, metadata?: {
|
|
180
|
+
private?: unknown;
|
|
181
|
+
uuid?: unknown;
|
|
182
|
+
} | null): string;
|
|
171
183
|
/**
|
|
172
184
|
* The name a page an identifier opened is known by: its title — the
|
|
173
185
|
* identifier may be a uuid or slug, and every downstream index is keyed by
|
|
@@ -252,6 +252,24 @@ export function parsePrivatePageName(name) {
|
|
|
252
252
|
return null;
|
|
253
253
|
return { owner, store, title };
|
|
254
254
|
}
|
|
255
|
+
/**
|
|
256
|
+
* A page's name for a log line (#1461, #2118, #2178): a private page's title
|
|
257
|
+
* stays out of logs, so it goes by its uuid, from its `metadata` — with its
|
|
258
|
+
* owner and store when its name holds them, and as "uuid unknown" before it
|
|
259
|
+
* has one. A private page saved under its bare title (#1520) is known only by
|
|
260
|
+
* its `metadata`. A public page goes by its name, and its uuid when known.
|
|
261
|
+
* The audit record is not a log line: it keeps the page's name.
|
|
262
|
+
*/
|
|
263
|
+
export function nameForLog(pageName, metadata) {
|
|
264
|
+
const uuid = typeof metadata?.uuid === 'string' && metadata.uuid ? metadata.uuid : null;
|
|
265
|
+
const byUuid = `(uuid ${uuid ?? 'unknown'})`;
|
|
266
|
+
const vault = parsePrivatePageName(pageName);
|
|
267
|
+
if (vault)
|
|
268
|
+
return `a page in ${vault.owner}'s store '${vault.store}' ${byUuid}`;
|
|
269
|
+
if (metadata?.private === true)
|
|
270
|
+
return `a private page ${byUuid}`;
|
|
271
|
+
return uuid ? `'${pageName}' ${byUuid}` : `'${pageName}'`;
|
|
272
|
+
}
|
|
255
273
|
/**
|
|
256
274
|
* The name a page an identifier opened is known by: its title — the
|
|
257
275
|
* identifier may be a uuid or slug, and every downstream index is keyed by
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recovery words to keep (#2144): the sheet an admin or a user downloads as a
|
|
3
|
+
* file or prints while their new words still wait to be confirmed, and the
|
|
4
|
+
* audit record of handing them out.
|
|
5
|
+
*
|
|
6
|
+
* One sheet for both sets of words: the shared folders' (SharedFolderManager)
|
|
7
|
+
* and a user's vault key (the store door, `privateStoreDoor.ts`). The words
|
|
8
|
+
* come only from the set still held for confirmation; once confirmed they are
|
|
9
|
+
* gone from the server and cannot be made again, so nothing here stores,
|
|
10
|
+
* caches or logs them. No key material is on the sheet.
|
|
11
|
+
*/
|
|
12
|
+
import { type ActorContext } from '../context/ActorContext.js';
|
|
13
|
+
import { type AuditEventSink } from './auditEvents.js';
|
|
14
|
+
/** Whose words: the organization's shared folders', or a user's vault key. */
|
|
15
|
+
export type RecoveryWordsSet = 'shared-folders' | 'store';
|
|
16
|
+
/** How they left the page: a plain text file, or the print view. */
|
|
17
|
+
export type RecoveryWordsExport = 'download' | 'print';
|
|
18
|
+
/** Everything the sheet shows, for the text file and the print view alike. */
|
|
19
|
+
export interface RecoveryWordsSheet {
|
|
20
|
+
title: string;
|
|
21
|
+
siteName: string;
|
|
22
|
+
siteUrl: string;
|
|
23
|
+
/** When the words were made, in the server's local time with its offset. */
|
|
24
|
+
made: string;
|
|
25
|
+
words: readonly string[];
|
|
26
|
+
purpose: string;
|
|
27
|
+
notStored: string;
|
|
28
|
+
}
|
|
29
|
+
/** `date` in the server's local time: `2026-10-30 05:28 (UTC-04:00)`. */
|
|
30
|
+
export declare function serverLocalTime(date: Date): string;
|
|
31
|
+
/** The sheet for `words` of `set`, made at `madeAt`, on the site named `siteName` at `siteUrl`. */
|
|
32
|
+
export declare function recoveryWordsSheet(args: {
|
|
33
|
+
set: RecoveryWordsSet;
|
|
34
|
+
siteName: string;
|
|
35
|
+
siteUrl: string;
|
|
36
|
+
words: readonly string[];
|
|
37
|
+
madeAt: Date;
|
|
38
|
+
}): RecoveryWordsSheet;
|
|
39
|
+
/** The sheet as a plain text file: the site, when made, the numbered words, what they are for. */
|
|
40
|
+
export declare function recoveryWordsText(sheet: RecoveryWordsSheet): string;
|
|
41
|
+
/** The file name: the site's name and whose words, safe for any file system. */
|
|
42
|
+
export declare function recoveryWordsFilename(siteName: string, set: RecoveryWordsSet): string;
|
|
43
|
+
/**
|
|
44
|
+
* Record that `ctx` downloaded or opened to print the set `wordsId` of `set`
|
|
45
|
+
* (`recovery-words-export`, on-failure refuse): called before the words are
|
|
46
|
+
* sent, so a record that cannot be written sends nothing. Who, which set and
|
|
47
|
+
* how; never the words.
|
|
48
|
+
*/
|
|
49
|
+
export declare function recordRecoveryWordsExport(sink: AuditEventSink | null | undefined, ctx: ActorContext, what: {
|
|
50
|
+
set: RecoveryWordsSet;
|
|
51
|
+
wordsId: string;
|
|
52
|
+
how: RecoveryWordsExport;
|
|
53
|
+
store?: string;
|
|
54
|
+
}): Promise<void>;
|
|
@@ -2,6 +2,7 @@ export type SessionEndReason = 'logout' | 'idle-timeout' | 'max-age' | 'password
|
|
|
2
2
|
export declare function endSession(engine: {
|
|
3
3
|
getManager(name: string): unknown;
|
|
4
4
|
}, session: {
|
|
5
|
+
id?: unknown;
|
|
5
6
|
username?: unknown;
|
|
6
7
|
privateStoreHandle?: unknown;
|
|
7
8
|
pendingConnection?: unknown;
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* - the end is recorded as `authentication-logout`, with who, from where and
|
|
11
11
|
* why (#1670). Until this, only the idle timeout was recorded.
|
|
12
12
|
* - a choice to act for someone (`actingFor`, #1762) ends with it.
|
|
13
|
+
* - so do the form POSTs it kept for a fresh sign-in (#2176), by its `id`.
|
|
13
14
|
*
|
|
14
15
|
* An account deleted or turned off ends its sessions here too (#1937), with
|
|
15
16
|
* the reason `account-deleted` / `account-disabled`: on the session's next
|
|
@@ -30,6 +31,9 @@ export function endSession(engine, session, reason, from) {
|
|
|
30
31
|
// #1762 slice 4: nor does a choice to act for someone.
|
|
31
32
|
if (session)
|
|
32
33
|
delete session.actingFor;
|
|
34
|
+
// #2176: nor do the form POSTs it kept for a fresh sign-in.
|
|
35
|
+
if (typeof session?.id === 'string')
|
|
36
|
+
engine.getManager('AuthManager')?.dropStepUpReplays?.(session.id);
|
|
33
37
|
const username = typeof session?.username === 'string' && session.username ? session.username : null;
|
|
34
38
|
if (!username)
|
|
35
39
|
return; // nobody was signed in: nothing ended
|
|
@@ -39,3 +39,7 @@ export declare function warnBeforeMs(timeoutMs: number): number;
|
|
|
39
39
|
export declare function idleRemainingMs(lastActivity: unknown, now: number, timeoutMs: number): number | null;
|
|
40
40
|
/** The status poll does not count as activity, or the warning would keep the session alive by itself. */
|
|
41
41
|
export declare const IDLE_STATUS_PATH = "/api/session/idle-status";
|
|
42
|
+
/** #2193: nor does a page's poll for its step-up prompt, or a page left waiting would keep its session alive. */
|
|
43
|
+
export declare const STEP_UP_STATUS_PATH = "/auth/reauth/status";
|
|
44
|
+
/** Whether a request to `path` counts as the person's activity: every one but the polls above. */
|
|
45
|
+
export declare function countsAsActivity(path: string): boolean;
|
|
@@ -64,3 +64,9 @@ export function idleRemainingMs(lastActivity, now, timeoutMs) {
|
|
|
64
64
|
}
|
|
65
65
|
/** The status poll does not count as activity, or the warning would keep the session alive by itself. */
|
|
66
66
|
export const IDLE_STATUS_PATH = '/api/session/idle-status';
|
|
67
|
+
/** #2193: nor does a page's poll for its step-up prompt, or a page left waiting would keep its session alive. */
|
|
68
|
+
export const STEP_UP_STATUS_PATH = '/auth/reauth/status';
|
|
69
|
+
/** Whether a request to `path` counts as the person's activity: every one but the polls above. */
|
|
70
|
+
export function countsAsActivity(path) {
|
|
71
|
+
return path !== IDLE_STATUS_PATH && path !== STEP_UP_STATUS_PATH;
|
|
72
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jwilleke/ngdpbase-types",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.41.0",
|
|
4
4
|
"description": "TypeScript types for ngdpbase add-ons, and a test kit of core's own values. A dev dependency, versioned with ngdpbase.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Jim Willeke",
|