@jwilleke/ngdpbase-types 0.0.0 → 5.18.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/LICENSE +201 -0
- package/README.md +16 -2
- package/lib/packages/ngdpbase-types/index.d.ts +32 -0
- package/lib/packages/ngdpbase-types/testing.d.ts +43 -0
- package/lib/packages/ngdpbase-types/testing.js +53 -0
- package/lib/src/cache/CacheDependencies.d.ts +50 -0
- package/lib/src/cache/CacheDependencies.js +50 -0
- package/lib/src/cache/ICacheAdapter.d.ts +86 -0
- package/lib/src/cache/RegionCache.d.ts +171 -0
- package/lib/src/context/ActorContext.d.ts +48 -0
- package/lib/src/context/ActorContext.js +33 -0
- package/lib/src/context/ApiContext.d.ts +194 -0
- package/lib/src/context/ApiContext.js +273 -0
- package/lib/src/context/BaseContext.d.ts +110 -0
- package/lib/src/context/BaseContext.js +143 -0
- package/lib/src/context/JobContext.d.ts +153 -0
- package/lib/src/context/JobContext.js +144 -0
- package/lib/src/context/WikiContext.d.ts +404 -0
- package/lib/src/context/bootActions.d.ts +64 -0
- package/lib/src/context/bootActions.js +111 -0
- package/lib/src/converters/HtmlConverter.d.ts +70 -0
- package/lib/src/converters/IContentConverter.d.ts +94 -0
- package/lib/src/converters/JSPWikiConverter.d.ts +117 -0
- package/lib/src/converters/conversionWarning.d.ts +15 -0
- package/lib/src/converters/ncm/bridge.d.ts +22 -0
- package/lib/src/converters/ncm/existing.d.ts +23 -0
- package/lib/src/converters/ncm/fix/blocks.d.ts +89 -0
- package/lib/src/converters/ncm/fix/bulletMarkers.d.ts +21 -0
- package/lib/src/converters/ncm/fix/index.d.ts +36 -0
- package/lib/src/converters/ncm/fix/jspwikiBullets.d.ts +20 -0
- package/lib/src/converters/ncm/fix/jspwikiCodeMarkers.d.ts +38 -0
- package/lib/src/converters/ncm/fix/jspwikiHeadings.d.ts +25 -0
- package/lib/src/converters/ncm/fix/jspwikiIndent.d.ts +24 -0
- package/lib/src/converters/ncm/fix/jspwikiInsert.d.ts +21 -0
- package/lib/src/converters/ncm/fix/jspwikiItalic.d.ts +29 -0
- package/lib/src/converters/ncm/fix/jspwikiLinkLeftovers.d.ts +27 -0
- package/lib/src/converters/ncm/fix/moreInformationFooter.d.ts +25 -0
- package/lib/src/converters/ncm/fix/styleClosers.d.ts +25 -0
- package/lib/src/converters/ncm/fix/tightenLists.d.ts +30 -0
- package/lib/src/converters/ncm/fix/types.d.ts +33 -0
- package/lib/src/converters/ncm/footnotes.d.ts +39 -0
- package/lib/src/converters/ncm/images.d.ts +49 -0
- package/lib/src/converters/ncm/index.d.ts +20 -0
- package/lib/src/converters/ncm/links.d.ts +21 -0
- package/lib/src/converters/ncm/normalize.d.ts +39 -0
- package/lib/src/converters/ncm/placeholder.d.ts +25 -0
- package/lib/src/converters/ncm/tables.d.ts +36 -0
- package/lib/src/converters/ncm/types.d.ts +42 -0
- package/lib/src/http/egressPolicy.d.ts +52 -0
- package/lib/src/http/guardedFetch.d.ts +89 -0
- package/lib/src/http/guardedFetch.js +113 -0
- package/lib/src/http/guardedLookup.d.ts +48 -0
- package/lib/src/http/guardedLookup.js +73 -0
- package/lib/src/http/ssrf.d.ts +83 -0
- package/lib/src/http/ssrf.js +311 -0
- package/lib/src/mail/MailProvider.d.ts +36 -0
- package/lib/src/mail/NodemailerMailProvider.d.ts +26 -0
- package/lib/src/managers/AddonsManager.d.ts +691 -0
- package/lib/src/managers/AgentTokenManager.d.ts +269 -0
- package/lib/src/managers/AssetManager.d.ts +116 -0
- package/lib/src/managers/AttachmentManager.d.ts +1032 -0
- package/lib/src/managers/AuthManager.d.ts +1257 -0
- package/lib/src/managers/BackgroundJobManager.d.ts +434 -0
- package/lib/src/managers/BaseManager.d.ts +391 -0
- package/lib/src/managers/BaseManager.js +415 -0
- package/lib/src/managers/CacheManager.d.ts +159 -0
- package/lib/src/managers/CatalogManager.d.ts +235 -0
- package/lib/src/managers/CommentManager.d.ts +75 -0
- package/lib/src/managers/ConfigurationManager.d.ts +747 -0
- package/lib/src/managers/DatabaseManager.d.ts +89 -0
- package/lib/src/managers/DatabaseManager.js +236 -0
- package/lib/src/managers/EmailManager.d.ts +47 -0
- package/lib/src/managers/ExportManager.d.ts +129 -0
- package/lib/src/managers/ExportManager.js +420 -0
- package/lib/src/managers/FootnoteManager.d.ts +118 -0
- package/lib/src/managers/MediaManager.d.ts +279 -0
- package/lib/src/managers/MetricsManager.d.ts +89 -0
- package/lib/src/managers/NotificationManager.d.ts +165 -0
- package/lib/src/managers/OidcManager.d.ts +210 -0
- package/lib/src/managers/OrganizationManager.d.ts +107 -0
- package/lib/src/managers/PageManager.d.ts +1645 -0
- package/lib/src/managers/PersonManager.d.ts +48 -0
- package/lib/src/managers/PluginManager.d.ts +179 -0
- package/lib/src/managers/PluginManager.js +393 -0
- package/lib/src/managers/PolicyEvaluator.d.ts +213 -0
- package/lib/src/managers/RenderingManager.d.ts +358 -0
- package/lib/src/managers/RoleManager.d.ts +134 -0
- package/lib/src/managers/SearchManager.d.ts +402 -0
- package/lib/src/managers/ShareManager.d.ts +251 -0
- package/lib/src/managers/TemplateManager.d.ts +176 -0
- package/lib/src/managers/ThemeManager.d.ts +56 -0
- package/lib/src/managers/UserManager.d.ts +480 -0
- package/lib/src/managers/ValidationManager.d.ts +426 -0
- package/lib/src/managers/VariableManager.d.ts +145 -0
- package/lib/src/middleware/csrf.d.ts +3 -0
- package/lib/src/parsers/LinkParser.d.ts +457 -0
- package/lib/src/parsers/MarkupParser.d.ts +769 -0
- package/lib/src/parsers/context/ParseContext.d.ts +314 -0
- package/lib/src/parsers/data/emoji-map.d.ts +18 -0
- package/lib/src/parsers/dom/DOMBuilder.d.ts +210 -0
- package/lib/src/parsers/dom/DOMParser.d.ts +252 -0
- package/lib/src/parsers/dom/Tokenizer.d.ts +358 -0
- package/lib/src/parsers/dom/WikiDocument.d.ts +272 -0
- package/lib/src/parsers/dom/handlers/DOMLinkHandler.d.ts +260 -0
- package/lib/src/parsers/dom/handlers/DOMPluginHandler.d.ts +212 -0
- package/lib/src/parsers/dom/handlers/DOMVariableHandler.d.ts +171 -0
- package/lib/src/parsers/filters/BaseFilter.d.ts +269 -0
- package/lib/src/parsers/filters/FilterChain.d.ts +320 -0
- package/lib/src/parsers/handlers/BaseSyntaxHandler.d.ts +331 -0
- package/lib/src/parsers/handlers/HandlerRegistry.d.ts +225 -0
- package/lib/src/parsers/handlers/JSPWikiPreprocessor.d.ts +89 -0
- package/lib/src/parsers/handlers/LinkParserHandler.d.ts +80 -0
- package/lib/src/parsers/handlers/PluginSyntaxHandler.d.ts +78 -0
- package/lib/src/parsers/handlers/WikiFormHandler.d.ts +149 -0
- package/lib/src/parsers/handlers/WikiTagHandler.d.ts +125 -0
- package/lib/src/parsers/jspwikiTableRow.d.ts +39 -0
- package/lib/src/parsers/styleBlockSyntax.d.ts +14 -0
- package/lib/src/plugins/types.d.ts +79 -0
- package/lib/src/providers/AgentTokenAuthProvider.d.ts +40 -0
- package/lib/src/providers/AuthentikBearerAuthProvider.d.ts +75 -0
- package/lib/src/providers/BaseAttachmentProvider.d.ts +197 -0
- package/lib/src/providers/BaseAuthProvider.d.ts +220 -0
- package/lib/src/providers/BaseCacheProvider.d.ts +140 -0
- package/lib/src/providers/BaseCredentialsProvider.d.ts +84 -0
- package/lib/src/providers/BaseDatabaseProvider.d.ts +22 -0
- package/lib/src/providers/BaseDatabaseProvider.js +12 -0
- package/lib/src/providers/BaseLoggingProvider.d.ts +68 -0
- package/lib/src/providers/BaseLoggingProvider.js +37 -0
- package/lib/src/providers/BaseMediaProvider.d.ts +308 -0
- package/lib/src/providers/BasePageProvider.d.ts +337 -0
- package/lib/src/providers/BaseProvider.d.ts +98 -0
- package/lib/src/providers/BaseProvider.js +74 -0
- package/lib/src/providers/BaseSearchProvider.d.ts +362 -0
- package/lib/src/providers/BasicAttachmentProvider.d.ts +599 -0
- package/lib/src/providers/CloudflareAccessAuthProvider.d.ts +72 -0
- package/lib/src/providers/FileCredentialsProvider.d.ts +33 -0
- package/lib/src/providers/FileJobStateProvider.d.ts +58 -0
- package/lib/src/providers/FileLoggingProvider.d.ts +43 -0
- package/lib/src/providers/FileLoggingProvider.js +120 -0
- package/lib/src/providers/FileOidcAdapter.d.ts +25 -0
- package/lib/src/providers/FileSystemMediaProvider.d.ts +403 -0
- package/lib/src/providers/LunrSearchProvider.d.ts +280 -0
- package/lib/src/providers/MagicLinkAuthProvider.d.ts +125 -0
- package/lib/src/providers/NullCacheProvider.d.ts +72 -0
- package/lib/src/providers/OidcAuthProvider.d.ts +180 -0
- package/lib/src/providers/OidcBearerAuthProvider.d.ts +30 -0
- package/lib/src/providers/PasskeyAuthProvider.d.ts +58 -0
- package/lib/src/providers/PasswordAuthProvider.d.ts +20 -0
- package/lib/src/providers/SqliteDatabaseProvider.d.ts +55 -0
- package/lib/src/providers/SqliteDatabaseProvider.js +90 -0
- package/lib/src/providers/SqliteJobStateProvider.d.ts +41 -0
- package/lib/src/providers/databaseMigrations.d.ts +8 -0
- package/lib/src/providers/databaseMigrations.js +47 -0
- package/lib/src/providers/jobState.d.ts +99 -0
- package/lib/src/providers/lunrQueryToMiniSearch.d.ts +32 -0
- package/lib/src/providers/mediaFilenameDate.d.ts +22 -0
- package/lib/src/providers/sqliteLocation.d.ts +17 -0
- package/lib/src/providers/sqliteLocation.js +55 -0
- package/lib/src/providers/sqliteMigrations.d.ts +48 -0
- package/lib/src/providers/sqliteMigrations.js +72 -0
- package/lib/src/rendering/githubAlerts.d.ts +22 -0
- package/lib/src/rendering/htmlPolicy.d.ts +76 -0
- package/lib/src/rendering/markdownConverter.d.ts +73 -0
- package/lib/src/security/PolicyDecisionPoint.d.ts +245 -0
- package/lib/src/security/PolicyInformationPoint.d.ts +448 -0
- package/lib/src/security/pageActions.d.ts +40 -0
- package/lib/src/security/permissions.generated.d.ts +78 -0
- package/lib/src/types/Asset.d.ts +414 -0
- package/lib/src/types/Catalog.d.ts +61 -0
- package/lib/src/types/Comment.d.ts +11 -0
- package/lib/src/types/Config.d.ts +388 -0
- package/lib/src/types/Organization.d.ts +78 -0
- package/lib/src/types/OrganizationProvider.d.ts +38 -0
- package/lib/src/types/Page.d.ts +220 -0
- package/lib/src/types/Person.d.ts +56 -0
- package/lib/src/types/PersonProvider.d.ts +25 -0
- package/lib/src/types/Policy.d.ts +139 -0
- package/lib/src/types/Policy.js +17 -0
- package/lib/src/types/Provider.d.ts +810 -0
- package/lib/src/types/Role.d.ts +84 -0
- package/lib/src/types/RoleProvider.d.ts +35 -0
- package/lib/src/types/Schema.d.ts +425 -0
- package/lib/src/types/Share.d.ts +172 -0
- package/lib/src/types/Share.js +81 -0
- package/lib/src/types/User.d.ts +304 -0
- package/lib/src/types/Version.d.ts +189 -0
- package/lib/src/types/WikiEngine.d.ts +128 -0
- package/lib/src/types/express.d.ts +120 -0
- package/lib/src/types/express.js +1 -0
- package/lib/src/types/guards.d.ts +78 -0
- package/lib/src/types/heic-decode.d.ts +16 -0
- package/lib/src/types/index.d.ts +19 -0
- package/lib/src/types/linkedom.d.ts +77 -0
- package/lib/src/types/markdown-it-plugins.d.ts +21 -0
- package/lib/src/utils/DeltaStorage.d.ts +118 -0
- package/lib/src/utils/LocaleUtils.d.ts +105 -0
- package/lib/src/utils/LocaleUtils.js +294 -0
- package/lib/src/utils/PageNameMatcher.d.ts +98 -0
- package/lib/src/utils/PathPreflight.d.ts +38 -0
- package/lib/src/utils/PathPreflight.js +50 -0
- package/lib/src/utils/SectionUtils.d.ts +40 -0
- package/lib/src/utils/addonConfigLayer.d.ts +144 -0
- package/lib/src/utils/addonConfigLayer.js +382 -0
- package/lib/src/utils/addonDatabaseRules.d.ts +25 -0
- package/lib/src/utils/addonDatabaseRules.js +57 -0
- package/lib/src/utils/addonHost.d.ts +51 -0
- package/lib/src/utils/addonHost.js +72 -0
- package/lib/src/utils/addonInstaller.d.ts +109 -0
- package/lib/src/utils/addonLock.d.ts +37 -0
- package/lib/src/utils/addonLock.js +48 -0
- package/lib/src/utils/addonPageSync.d.ts +45 -0
- package/lib/src/utils/addonProvenance.d.ts +48 -0
- package/lib/src/utils/addonTarball.d.ts +41 -0
- package/lib/src/utils/addonsPathResolver.d.ts +76 -0
- package/lib/src/utils/addonsPathResolver.js +129 -0
- package/lib/src/utils/assetMetadataTags.d.ts +66 -0
- package/lib/src/utils/atomicWrite.d.ts +28 -0
- package/lib/src/utils/auditConfigChange.d.ts +57 -0
- package/lib/src/utils/auditEventNames.d.ts +50 -0
- package/lib/src/utils/auditEventNames.generated.d.ts +163 -0
- package/lib/src/utils/auditEventNames.generated.js +168 -0
- package/lib/src/utils/auditEventNames.js +49 -0
- package/lib/src/utils/auditEvents.d.ts +265 -0
- package/lib/src/utils/auditEvents.js +309 -0
- package/lib/src/utils/auditRegistry.d.ts +102 -0
- package/lib/src/utils/auditRegistry.js +168 -0
- package/lib/src/utils/bip39English.d.ts +2 -0
- package/lib/src/utils/configEnvKeys.d.ts +68 -0
- package/lib/src/utils/configFiles.d.ts +74 -0
- package/lib/src/utils/configFiles.js +150 -0
- package/lib/src/utils/delegation.d.ts +48 -0
- package/lib/src/utils/deriveUsername.d.ts +21 -0
- package/lib/src/utils/explainMediaPath.d.ts +123 -0
- package/lib/src/utils/formerTitles.d.ts +69 -0
- package/lib/src/utils/frontmatterAccess.d.ts +54 -0
- package/lib/src/utils/headlessAdminPassword.d.ts +55 -0
- package/lib/src/utils/imageTransform.d.ts +52 -0
- package/lib/src/utils/instanceEnvSecret.d.ts +51 -0
- package/lib/src/utils/jobSlots.d.ts +43 -0
- package/lib/src/utils/keywordNormalizer.d.ts +127 -0
- package/lib/src/utils/logger.d.ts +70 -0
- package/lib/src/utils/logger.js +106 -0
- package/lib/src/utils/magicLinkDeviceState.d.ts +95 -0
- package/lib/src/utils/managerUtils.d.ts +40 -0
- package/lib/src/utils/migrateLegacyPrivateAttachments.d.ts +15 -0
- package/lib/src/utils/orgFilename.d.ts +22 -0
- package/lib/src/utils/pageFeature.d.ts +27 -0
- package/lib/src/utils/pageFrontmatter.d.ts +21 -0
- package/lib/src/utils/pageNotes.d.ts +150 -0
- package/lib/src/utils/pageTitleRule.d.ts +37 -0
- package/lib/src/utils/pageToArticle.d.ts +59 -0
- package/lib/src/utils/pageUrl.d.ts +18 -0
- package/lib/src/utils/passwordChange.d.ts +12 -0
- package/lib/src/utils/passwordHash.d.ts +60 -0
- package/lib/src/utils/permissionCatalog.d.ts +52 -0
- package/lib/src/utils/pluginFormatters.d.ts +452 -0
- package/lib/src/utils/pluginFormatters.js +714 -0
- package/lib/src/utils/privateLinkRewrite.d.ts +42 -0
- package/lib/src/utils/privateStoreAccess.d.ts +57 -0
- package/lib/src/utils/privateStoreAccess.js +65 -0
- package/lib/src/utils/privateStoreCatalogs.d.ts +40 -0
- package/lib/src/utils/privateStoreCrypto.d.ts +127 -0
- package/lib/src/utils/privateStoreDoor.d.ts +181 -0
- package/lib/src/utils/privateStoreExport.d.ts +72 -0
- package/lib/src/utils/privateStoreFiles.d.ts +120 -0
- package/lib/src/utils/privateStoreMeta.d.ts +64 -0
- package/lib/src/utils/privateStoreMigrations.d.ts +37 -0
- package/lib/src/utils/privateStorePath.d.ts +259 -0
- package/lib/src/utils/privateStorePath.js +436 -0
- package/lib/src/utils/privateStoreTakeout.d.ts +76 -0
- package/lib/src/utils/privateStoreUnlock.d.ts +175 -0
- package/lib/src/utils/proxyClaim.d.ts +59 -0
- package/lib/src/utils/proxyClaim.js +30 -0
- package/lib/src/utils/redactPrivateNames.d.ts +21 -0
- package/lib/src/utils/redactPrivateNames.js +89 -0
- package/lib/src/utils/redactSecrets.d.ts +58 -0
- package/lib/src/utils/redactSecrets.js +171 -0
- package/lib/src/utils/renameLinkRewrite.d.ts +112 -0
- package/lib/src/utils/roleGrants.d.ts +35 -0
- package/lib/src/utils/safeRedirect.d.ts +32 -0
- package/lib/src/utils/schedule.d.ts +54 -0
- package/lib/src/utils/secretFileMode.d.ts +17 -0
- package/lib/src/utils/seededShippedPages.d.ts +45 -0
- package/lib/src/utils/sensitiveValues.d.ts +59 -0
- package/lib/src/utils/sensitiveValues.js +106 -0
- package/lib/src/utils/sessionEnd.d.ts +12 -0
- package/lib/src/utils/sessionGeneration.d.ts +24 -0
- package/lib/src/utils/sessionIdle.d.ts +41 -0
- package/lib/src/utils/sessionLimits.d.ts +68 -0
- package/lib/src/utils/shareLockbox.d.ts +64 -0
- package/lib/src/utils/sigstoreTrustedRoot.d.ts +33 -0
- package/lib/src/utils/sniffMime.d.ts +21 -0
- package/lib/src/utils/storeSearchIndex.d.ts +75 -0
- package/lib/src/utils/subjectMayDo.d.ts +21 -0
- package/lib/src/utils/systemCategoryRules.d.ts +30 -0
- package/lib/src/utils/systemCategoryRules.js +41 -0
- package/lib/src/utils/userCreateError.d.ts +62 -0
- package/lib/src/utils/username.d.ts +53 -0
- package/lib/src/utils/vaultUrlRewrite.d.ts +27 -0
- package/lib/src/utils/version.d.ts +84 -0
- package/lib/src/utils/videoFrame.d.ts +21 -0
- package/package.json +54 -3
|
@@ -0,0 +1,599 @@
|
|
|
1
|
+
import BaseAttachmentProvider, { FileInfo, User, AttachmentResult } from './BaseAttachmentProvider.js';
|
|
2
|
+
import type { ProviderInfo, StoreFileEntry, StoreFileLocation } from '../types/Provider.js';
|
|
3
|
+
import { AttachmentMetadata } from '../types/index.js';
|
|
4
|
+
import type { AssetProvider, AssetRecord, AssetQuery, AssetPage, AssetInput, AssetMetadata, AssetMetadataPatch } from '../types/Asset.js';
|
|
5
|
+
import type { CreativeWork } from '../types/Schema.js';
|
|
6
|
+
import type { ActorContext } from '../context/ActorContext.js';
|
|
7
|
+
import type { WikiEngine } from '../types/WikiEngine.js';
|
|
8
|
+
/**
|
|
9
|
+
* Schema.org Person metadata
|
|
10
|
+
*/
|
|
11
|
+
interface SchemaPerson {
|
|
12
|
+
'@type': 'Person';
|
|
13
|
+
name: string;
|
|
14
|
+
email?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Schema.org mention reference
|
|
18
|
+
*/
|
|
19
|
+
interface SchemaMention {
|
|
20
|
+
'@type'?: 'Thing';
|
|
21
|
+
name?: string;
|
|
22
|
+
url?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Schema.org CreativeWork metadata for attachments
|
|
26
|
+
*/
|
|
27
|
+
interface SchemaCreativeWork {
|
|
28
|
+
'@context': 'https://schema.org';
|
|
29
|
+
'@type': 'CreativeWork';
|
|
30
|
+
identifier: string;
|
|
31
|
+
name: string;
|
|
32
|
+
description?: string;
|
|
33
|
+
author?: SchemaPerson;
|
|
34
|
+
editor?: SchemaPerson;
|
|
35
|
+
dateCreated: string;
|
|
36
|
+
dateModified: string;
|
|
37
|
+
encodingFormat: string;
|
|
38
|
+
contentSize: number;
|
|
39
|
+
url: string;
|
|
40
|
+
storageLocation: string;
|
|
41
|
+
isFamilyFriendly?: boolean;
|
|
42
|
+
isBasedOn?: string;
|
|
43
|
+
mentions: SchemaMention[];
|
|
44
|
+
/** Whether this attachment belongs to a private page */
|
|
45
|
+
isPrivate?: boolean;
|
|
46
|
+
/** Username of the page creator; set when isPrivate is true */
|
|
47
|
+
creator?: string;
|
|
48
|
+
/** Private-store id when the file lives in the page store (#1386) */
|
|
49
|
+
store?: string;
|
|
50
|
+
/** Structured metadata extracted at upload time (EXIF via sharp) — Phase 5 #405 */
|
|
51
|
+
assetMetadata?: AssetMetadata;
|
|
52
|
+
/** Title embedded in the document (PDF /Info Title; docx core.xml dc:title). Distinct from the uploaded filename. */
|
|
53
|
+
documentTitle?: string;
|
|
54
|
+
/** Author embedded in the document (PDF /Info Author; docx dc:creator). Distinct from the uploader's user. */
|
|
55
|
+
documentAuthor?: string;
|
|
56
|
+
/** Subject / abstract embedded in the document (PDF /Info Subject; docx dc:description). */
|
|
57
|
+
documentSubject?: string;
|
|
58
|
+
/** Keywords / tags embedded in the document (PDF /Info Keywords; docx dc:subject). String array, deduplicated. */
|
|
59
|
+
documentKeywords?: string[];
|
|
60
|
+
/** Document's own CreationDate (when the file was first authored). Distinct from upload time. */
|
|
61
|
+
documentDateCreated?: string;
|
|
62
|
+
/** Document's own ModDate (last edit before upload). Distinct from upload time. */
|
|
63
|
+
documentDateModified?: string;
|
|
64
|
+
/** BCP-47 language tag from the document (PDF /Lang; docx core.xml dc:language). */
|
|
65
|
+
inLanguage?: string;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Backup data structure
|
|
69
|
+
*/
|
|
70
|
+
interface BackupData extends Record<string, unknown> {
|
|
71
|
+
providerName: string;
|
|
72
|
+
timestamp: string;
|
|
73
|
+
metadataFile: string;
|
|
74
|
+
storageDirectory: string;
|
|
75
|
+
attachments: Array<[string, SchemaCreativeWork]>;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* The extension to store a file under, given what the uploader called it and
|
|
79
|
+
* what they said it was.
|
|
80
|
+
*
|
|
81
|
+
* A stored file is named `{generated-id}{ext}`. The id is ours; the extension
|
|
82
|
+
* used to be whatever `path.extname()` returned for the uploaded name — and
|
|
83
|
+
* that function does not promise an extension, it promises everything after
|
|
84
|
+
* the last dot in the basename. For `photo.jpg` that is `.jpg`. For a name
|
|
85
|
+
* written by hand in the request, such as `x.\..\..\etc\passwd`, it is
|
|
86
|
+
* `.\etc\passwd`, and we pasted it onto the id without ever asking whether it
|
|
87
|
+
* looked like an extension. Harmless on Linux, where `\` is an ordinary
|
|
88
|
+
* character — but it is untrusted text in a filename we construct, which it
|
|
89
|
+
* should never have been.
|
|
90
|
+
*
|
|
91
|
+
* So an extension is now defined rather than inherited: a short run of letters
|
|
92
|
+
* and digits, and nothing else. It comes from
|
|
93
|
+
*
|
|
94
|
+
* 1. the uploaded name, when that already matches the definition — which is
|
|
95
|
+
* every real file, and keeps `.docx`, `.heic` and the rest that no table
|
|
96
|
+
* here lists; or
|
|
97
|
+
* 2. the declared MIME type through the table above, a closed set we own; or
|
|
98
|
+
* 3. nowhere, and the file is stored as the bare id, exactly as an
|
|
99
|
+
* extensionless upload has always been.
|
|
100
|
+
*
|
|
101
|
+
* Nothing downstream depends on this: a download's Content-Type comes from the
|
|
102
|
+
* recorded `encodingFormat`, and the only reader of the stored extension is the
|
|
103
|
+
* orphan-recovery scan, which maps it back through this same table.
|
|
104
|
+
*/
|
|
105
|
+
export declare function safeStoredExtension(originalName: string, mimeType?: string): string;
|
|
106
|
+
/**
|
|
107
|
+
* BasicAttachmentProvider - Filesystem-based attachment storage
|
|
108
|
+
*
|
|
109
|
+
* Implements attachment storage using filesystem with Schema.org CreativeWork metadata.
|
|
110
|
+
* Attachments are stored in a shared directory structure, not tied to individual pages.
|
|
111
|
+
* Page references are tracked via the "mentions" array in metadata.
|
|
112
|
+
*
|
|
113
|
+
* Based on JSPWiki's BasicAttachmentProvider:
|
|
114
|
+
* https://github.com/apache/jspwiki/blob/master/jspwiki-main/src/main/java/org/apache/wiki/providers/BasicAttachmentProvider.java
|
|
115
|
+
*
|
|
116
|
+
* Features:
|
|
117
|
+
* - Filesystem storage with SHA-256 content hashing
|
|
118
|
+
* - Schema.org CreativeWork metadata format
|
|
119
|
+
* - Shared storage model with page mentions tracking
|
|
120
|
+
* - Automatic metadata persistence
|
|
121
|
+
* - Backup/restore support
|
|
122
|
+
*/
|
|
123
|
+
declare class BasicAttachmentProvider extends BaseAttachmentProvider implements AssetProvider {
|
|
124
|
+
private storageDirectory;
|
|
125
|
+
/** Pre-#1386 attachments/{legacyprivateroot}/{user}/ — migrate-FROM and read fallback only. */
|
|
126
|
+
private legacyPrivateDir;
|
|
127
|
+
private pagesDirectory;
|
|
128
|
+
private privateStoreLayout;
|
|
129
|
+
private thumbDir;
|
|
130
|
+
private metadataFile;
|
|
131
|
+
private attachmentMetadata;
|
|
132
|
+
private maxFileSize;
|
|
133
|
+
private allowedMimeTypes;
|
|
134
|
+
private hashMethod;
|
|
135
|
+
/**
|
|
136
|
+
* Lazily-instantiated ExifTool worker (Slice 5 of #755 / #759).
|
|
137
|
+
* Used to extract embedded document metadata from PDFs / docx at upload
|
|
138
|
+
* time. Created on first use to avoid spawning a perl process when the
|
|
139
|
+
* provider initialises but never sees a PDF or docx upload.
|
|
140
|
+
*/
|
|
141
|
+
private _exiftool;
|
|
142
|
+
private exiftool;
|
|
143
|
+
/**
|
|
144
|
+
* MIME types that carry extractable document metadata.
|
|
145
|
+
* exiftool reads both via its PDF / OOXML modules.
|
|
146
|
+
*/
|
|
147
|
+
private static readonly DOC_METADATA_MIME_TYPES;
|
|
148
|
+
constructor(engine: WikiEngine);
|
|
149
|
+
/**
|
|
150
|
+
* Initialize the provider
|
|
151
|
+
* All configuration access via ConfigurationManager
|
|
152
|
+
*/
|
|
153
|
+
initialize(): Promise<void>;
|
|
154
|
+
/**
|
|
155
|
+
* Verify that the attachment storage directory is accessible.
|
|
156
|
+
*
|
|
157
|
+
* Returns false when the directory cannot be read — e.g. a NAS or SLOW_STORAGE
|
|
158
|
+
* volume that has been unmounted or an SMB share that has dropped. AssetManager
|
|
159
|
+
* uses this to skip the provider during fan-out rather than surfacing I/O errors
|
|
160
|
+
* to end users.
|
|
161
|
+
*/
|
|
162
|
+
healthCheck(): Promise<boolean>;
|
|
163
|
+
/**
|
|
164
|
+
* Format bytes to human-readable size
|
|
165
|
+
* @param bytes - Size in bytes
|
|
166
|
+
* @returns Formatted size
|
|
167
|
+
* @private
|
|
168
|
+
*/
|
|
169
|
+
private formatSize;
|
|
170
|
+
/**
|
|
171
|
+
* Rewrite stale storageLocation paths after a data migration.
|
|
172
|
+
*
|
|
173
|
+
* Compares each entry's directory against the current storageDirectory.
|
|
174
|
+
* If they differ, the absolute path is replaced with the correct one
|
|
175
|
+
* (preserving the basename/hash filename) and metadata is saved once.
|
|
176
|
+
* Private attachments are corrected to the page store (legacy leftovers
|
|
177
|
+
* stay at attachments/{legacyprivateroot} until the file itself moves).
|
|
178
|
+
*/
|
|
179
|
+
private migrateStaleStoragePaths;
|
|
180
|
+
/**
|
|
181
|
+
* On-disk path for an attachment. Private files live in the page store;
|
|
182
|
+
* a leftover under attachments/{legacyprivateroot} is read fallback only.
|
|
183
|
+
*/
|
|
184
|
+
private resolveAttachmentFilePath;
|
|
185
|
+
/**
|
|
186
|
+
* Load metadata from JSON file
|
|
187
|
+
* @private
|
|
188
|
+
*/
|
|
189
|
+
private loadMetadata;
|
|
190
|
+
/**
|
|
191
|
+
* Save metadata to JSON file
|
|
192
|
+
* @private
|
|
193
|
+
*/
|
|
194
|
+
private saveMetadata;
|
|
195
|
+
/**
|
|
196
|
+
* Generate unique attachment ID using SHA-256 hash of content
|
|
197
|
+
* @param buffer - File data
|
|
198
|
+
* @returns Attachment ID (hash)
|
|
199
|
+
* @private
|
|
200
|
+
*/
|
|
201
|
+
private generateAttachmentId;
|
|
202
|
+
/**
|
|
203
|
+
* Validate file against constraints
|
|
204
|
+
* @param fileInfo - File information
|
|
205
|
+
* @private
|
|
206
|
+
*/
|
|
207
|
+
private validateFile;
|
|
208
|
+
/**
|
|
209
|
+
* Store an attachment with metadata (internal method using Schema.org format)
|
|
210
|
+
* @param fileBuffer - File data
|
|
211
|
+
* @param fileInfo - { originalName, mimeType, size }
|
|
212
|
+
* @param metadata - Schema.org CreativeWork metadata
|
|
213
|
+
* @param user - User object { name, email }
|
|
214
|
+
* @param options - Privacy-aware storage options
|
|
215
|
+
* @returns Complete attachment metadata
|
|
216
|
+
* @private
|
|
217
|
+
*/
|
|
218
|
+
private storeAttachmentInternal;
|
|
219
|
+
/**
|
|
220
|
+
* Store an attachment with metadata (BaseAttachmentProvider interface method)
|
|
221
|
+
* @param fileBuffer - File data
|
|
222
|
+
* @param fileInfo - { originalName, mimeType, size }
|
|
223
|
+
* @param metadata - Attachment metadata
|
|
224
|
+
* @param user - User object
|
|
225
|
+
* @returns Attachment metadata
|
|
226
|
+
*/
|
|
227
|
+
storeAttachment(fileBuffer: Buffer, fileInfo: FileInfo, metadata?: Partial<AttachmentMetadata>, user?: User | null): Promise<AttachmentMetadata>;
|
|
228
|
+
/**
|
|
229
|
+
* Get attachment file and metadata
|
|
230
|
+
*
|
|
231
|
+
* Falls back to a disk scan when metadata is missing but a file matching
|
|
232
|
+
* `{attachmentId}.*` exists in the storage directory (orphaned file). This
|
|
233
|
+
* handles the case where attachment metadata was lost without requiring a
|
|
234
|
+
* data repair before the file can be served. A warning is logged so operators
|
|
235
|
+
* know the metadata repair is still needed.
|
|
236
|
+
*
|
|
237
|
+
* @param attachmentId - Attachment identifier
|
|
238
|
+
* @returns File buffer and metadata or null
|
|
239
|
+
*/
|
|
240
|
+
getAttachment(attachmentId: string): Promise<AttachmentResult | null>;
|
|
241
|
+
/**
|
|
242
|
+
* Disk-scan fallback for orphaned attachment files (file on disk, no metadata record).
|
|
243
|
+
* @param attachmentId - Attachment identifier (SHA-256 hash)
|
|
244
|
+
* @returns File buffer and synthetic metadata, or null if not found
|
|
245
|
+
* @private
|
|
246
|
+
*/
|
|
247
|
+
private getOrphanedAttachment;
|
|
248
|
+
private storeIndexFile;
|
|
249
|
+
private storeFilePath;
|
|
250
|
+
private requirePagesDirectory;
|
|
251
|
+
private readStoreIndex;
|
|
252
|
+
private writeStoreIndex;
|
|
253
|
+
storeFileInStore(location: StoreFileLocation, bytes: Buffer, file: {
|
|
254
|
+
originalName: string;
|
|
255
|
+
mimeType: string;
|
|
256
|
+
description: string;
|
|
257
|
+
author?: string;
|
|
258
|
+
pageName?: string;
|
|
259
|
+
}): Promise<StoreFileEntry>;
|
|
260
|
+
getFileInStore(location: StoreFileLocation, id: string): Promise<{
|
|
261
|
+
entry: StoreFileEntry;
|
|
262
|
+
bytes: Buffer;
|
|
263
|
+
} | null>;
|
|
264
|
+
/** Everything this store lists, newest first — the store's half of a merged list (#1460). */
|
|
265
|
+
listFilesInStore(location: StoreFileLocation): Promise<StoreFileEntry[]>;
|
|
266
|
+
filesInStoreForPage(location: StoreFileLocation, pageName: string): Promise<StoreFileEntry[]>;
|
|
267
|
+
/**
|
|
268
|
+
* Add or remove `pageName` in one store file's mentions (#1460) — the store
|
|
269
|
+
* index's half of save-time mention sync. `false` when this store does not
|
|
270
|
+
* list `id`, so a caller can try the next of its own stores.
|
|
271
|
+
*/
|
|
272
|
+
setFileMentionInStore(location: StoreFileLocation, id: string, pageName: string, mentioned: boolean): Promise<boolean>;
|
|
273
|
+
/**
|
|
274
|
+
* Move one record out of the global `attachment-metadata.json` and into its
|
|
275
|
+
* store's own index (#1460), bytes and all.
|
|
276
|
+
*
|
|
277
|
+
* The file KEEPS the name it has: renaming it would break nothing that is
|
|
278
|
+
* written down, but it would rewrite a file for no reason, and a store is
|
|
279
|
+
* meant to be a directory an operator can read. The entry keeps the record's
|
|
280
|
+
* identifier too — that id is the `/attachments/{id}` URL on every page that
|
|
281
|
+
* references the file.
|
|
282
|
+
*
|
|
283
|
+
* Idempotent: a record already gone from the map, or a store that already
|
|
284
|
+
* lists the id, is a no-op that answers `null`. The move itself is skipped
|
|
285
|
+
* when the bytes are already in place.
|
|
286
|
+
*
|
|
287
|
+
* @returns the store entry it wrote, or null when there was nothing to move
|
|
288
|
+
*/
|
|
289
|
+
adoptRecordIntoStore(location: StoreFileLocation, id: string): Promise<StoreFileEntry | null>;
|
|
290
|
+
/**
|
|
291
|
+
* The private records still sitting in the shared index (#1460) — what the
|
|
292
|
+
* start-up migration has to move. Identifier, owner and store only: enough
|
|
293
|
+
* to place the file, and nothing of its name leaves this method.
|
|
294
|
+
*
|
|
295
|
+
* Two ways a record says it is private, in order:
|
|
296
|
+
*
|
|
297
|
+
* - `isPrivate`, #1398's flag, written by `storeAttachmentInternal` together
|
|
298
|
+
* with `creator` and `store`. That is the record deciding from itself.
|
|
299
|
+
* - failing that, a mention naming a private page — `private/{owner}/{store}/{title}`
|
|
300
|
+
* since #1456. The record is then placed by the page it is attached to,
|
|
301
|
+
* with `owner: null` so the caller confirms it through PageManager, which
|
|
302
|
+
* is what actually knows whose store a page is in.
|
|
303
|
+
*
|
|
304
|
+
* A record that is neither is a public attachment and is not listed: the
|
|
305
|
+
* shared pool is exactly what stays behind.
|
|
306
|
+
*/
|
|
307
|
+
privateRecordsInSharedIndex(): Array<{
|
|
308
|
+
id: string;
|
|
309
|
+
owner: string | null;
|
|
310
|
+
store: string | null;
|
|
311
|
+
pages: string[];
|
|
312
|
+
}>;
|
|
313
|
+
deleteFileInStore(location: StoreFileLocation, id: string): Promise<StoreFileEntry | null>;
|
|
314
|
+
/**
|
|
315
|
+
* Copy a shared-pool file into a store under the same id, mentioned by
|
|
316
|
+
* `pageName` there. The shared record is left as it is. A store that already
|
|
317
|
+
* lists the id just gains the mention.
|
|
318
|
+
*
|
|
319
|
+
* @returns the store entry, or null when the pool has no such file
|
|
320
|
+
*/
|
|
321
|
+
copyRecordIntoStore(location: StoreFileLocation, id: string, pageName: string): Promise<StoreFileEntry | null>;
|
|
322
|
+
/**
|
|
323
|
+
* Copy a store's file into another store under the same id, mentioned by
|
|
324
|
+
* `pageName` there. A destination that already lists the id just gains the
|
|
325
|
+
* mention.
|
|
326
|
+
*
|
|
327
|
+
* @returns the destination's entry, or null when the source does not list it
|
|
328
|
+
*/
|
|
329
|
+
copyStoreFileToStore(from: StoreFileLocation, to: StoreFileLocation, id: string, pageName: string): Promise<StoreFileEntry | null>;
|
|
330
|
+
/**
|
|
331
|
+
* Copy a store's file into the shared pool under the same id, opened, and
|
|
332
|
+
* mentioned by `pageName` (a public page). A pool that already holds the id
|
|
333
|
+
* just gains the mention.
|
|
334
|
+
*
|
|
335
|
+
* @returns true when the pool holds the file afterwards
|
|
336
|
+
*/
|
|
337
|
+
copyStoreFileToPool(from: StoreFileLocation, id: string, pageName: string): Promise<boolean>;
|
|
338
|
+
/**
|
|
339
|
+
* Take a file out of the shared pool: its record, its bytes and any cached
|
|
340
|
+
* thumbnails of it (#1842) — used when the file has moved into a vault and
|
|
341
|
+
* no public page uses it any more, so no public copy of it is left.
|
|
342
|
+
*/
|
|
343
|
+
removeRecordFromPool(id: string): Promise<boolean>;
|
|
344
|
+
/**
|
|
345
|
+
* Set a shared-pool record's mentions to exactly `names` (#1842), keeping the
|
|
346
|
+
* mention objects it already has for those names.
|
|
347
|
+
*/
|
|
348
|
+
setPoolMentions(id: string, names: string[]): Promise<boolean>;
|
|
349
|
+
/**
|
|
350
|
+
* Get attachment metadata only
|
|
351
|
+
* @param attachmentId - Attachment identifier
|
|
352
|
+
* @returns Attachment metadata or null
|
|
353
|
+
*/
|
|
354
|
+
getAttachmentMetadata(attachmentId: string): Promise<AttachmentMetadata | null>;
|
|
355
|
+
/**
|
|
356
|
+
* Update attachment metadata
|
|
357
|
+
* @param attachmentId - Attachment identifier
|
|
358
|
+
* @param updates - Metadata updates
|
|
359
|
+
* @returns Success status
|
|
360
|
+
*/
|
|
361
|
+
updateAttachmentMetadata(attachmentId: string, updates: Partial<AttachmentMetadata>): Promise<boolean>;
|
|
362
|
+
/**
|
|
363
|
+
* Delete an attachment
|
|
364
|
+
* @param attachmentId - Attachment identifier
|
|
365
|
+
* @returns True if deleted, false if not found
|
|
366
|
+
*/
|
|
367
|
+
deleteAttachment(attachmentId: string): Promise<boolean>;
|
|
368
|
+
/**
|
|
369
|
+
* Check if attachment exists
|
|
370
|
+
* @param attachmentId - Attachment identifier
|
|
371
|
+
* @returns True if exists
|
|
372
|
+
*/
|
|
373
|
+
attachmentExists(attachmentId: string): Promise<boolean>;
|
|
374
|
+
/**
|
|
375
|
+
* Get all attachments metadata
|
|
376
|
+
* @returns Array of attachment metadata
|
|
377
|
+
*/
|
|
378
|
+
getAllAttachments(): Promise<AttachmentMetadata[]>;
|
|
379
|
+
/**
|
|
380
|
+
* Get attachments used by a specific page
|
|
381
|
+
* @param pageName - Page name/title
|
|
382
|
+
* @returns Array of attachment metadata
|
|
383
|
+
*/
|
|
384
|
+
getAttachmentsForPage(pageName: string): Promise<AttachmentMetadata[]>;
|
|
385
|
+
/**
|
|
386
|
+
* Find an attachment by its original filename across all attachments
|
|
387
|
+
* @param filename - Original filename to search for
|
|
388
|
+
* @returns Matching attachment metadata or null
|
|
389
|
+
*/
|
|
390
|
+
getAttachmentByFilename(filename: string): Promise<AttachmentMetadata | null>;
|
|
391
|
+
/**
|
|
392
|
+
* List attachments for a page (AttachmentProvider interface method)
|
|
393
|
+
* @param pageUuid - Page UUID
|
|
394
|
+
* @returns Array of attachment metadata
|
|
395
|
+
*/
|
|
396
|
+
listAttachments(pageUuid: string): Promise<AttachmentMetadata[]>;
|
|
397
|
+
/**
|
|
398
|
+
* Delete all attachments for a page
|
|
399
|
+
* @param pageUuid - Page UUID
|
|
400
|
+
* @returns Number of attachments deleted
|
|
401
|
+
*/
|
|
402
|
+
deletePageAttachments(pageUuid: string): Promise<number>;
|
|
403
|
+
/**
|
|
404
|
+
* Refresh attachment list (rescan storage)
|
|
405
|
+
* @returns Promise that resolves when complete
|
|
406
|
+
*/
|
|
407
|
+
refreshAttachmentList(): Promise<void>;
|
|
408
|
+
/**
|
|
409
|
+
* #865 Slice 2: basenames of all stored attachment files on disk (top-level
|
|
410
|
+
* storage dir; excludes .json bookkeeping). Used by the health report to
|
|
411
|
+
* find recordless files and missing-file records.
|
|
412
|
+
*/
|
|
413
|
+
listStorageFiles(): Promise<string[]>;
|
|
414
|
+
/**
|
|
415
|
+
* #865 Slice 3: move an attachment (record + stored file) into the
|
|
416
|
+
* quarantine subdirectory instead of hard-deleting. The record is removed
|
|
417
|
+
* from live metadata and appended to a per-run manifest inside quarantine/
|
|
418
|
+
* so the operation is reversible by hand. Skips (returns false) on any
|
|
419
|
+
* error — never deletes on failure (media-prune #867 precedent).
|
|
420
|
+
*/
|
|
421
|
+
quarantineAttachment(identifier: string, manifestPath: string): Promise<boolean>;
|
|
422
|
+
/**
|
|
423
|
+
* #865 Slice 3: move a recordless disk file into quarantine. Skips on error.
|
|
424
|
+
*/
|
|
425
|
+
quarantineFile(basename: string): Promise<boolean>;
|
|
426
|
+
/** #865 Slice 3: absolute quarantine directory path (for manifests/report). */
|
|
427
|
+
getQuarantineDir(): string | null;
|
|
428
|
+
/**
|
|
429
|
+
* Get provider information
|
|
430
|
+
* @returns Provider metadata
|
|
431
|
+
*/
|
|
432
|
+
getProviderInfo(): ProviderInfo;
|
|
433
|
+
/**
|
|
434
|
+
* Backup provider data
|
|
435
|
+
* @returns Backup data
|
|
436
|
+
*/
|
|
437
|
+
backup(): Promise<BackupData>;
|
|
438
|
+
/**
|
|
439
|
+
* Restore provider data from backup
|
|
440
|
+
* @param backupData - Backup data
|
|
441
|
+
* @returns Promise that resolves when complete
|
|
442
|
+
*/
|
|
443
|
+
restore(backupData: Record<string, unknown>): Promise<void>;
|
|
444
|
+
readonly id = "local";
|
|
445
|
+
readonly displayName = "Local Attachments";
|
|
446
|
+
readonly capabilities: import('../types/Asset.js').ProviderCapability[];
|
|
447
|
+
/**
|
|
448
|
+
* AssetProvider.getThumbnail() — generate (and cache) a JPEG thumbnail for image attachments.
|
|
449
|
+
* Returns null for non-image attachments or when the source file cannot be processed.
|
|
450
|
+
*/
|
|
451
|
+
getThumbnail(id: string, size: string): Promise<Buffer | null>;
|
|
452
|
+
/**
|
|
453
|
+
* Extract embedded document metadata via ExifTool (Slice 5 of #755 / #759).
|
|
454
|
+
*
|
|
455
|
+
* Handles PDFs and Office Open XML (`.docx`, `.xlsx`, `.pptx`). Returns the
|
|
456
|
+
* subset of fields we map into `SchemaCreativeWork` per the schemas.md
|
|
457
|
+
* `DigitalDocument` per-source mapping. Returns null for non-document MIME
|
|
458
|
+
* types or when extraction fails (treated as non-fatal — uploads always
|
|
459
|
+
* succeed even if metadata extraction trips).
|
|
460
|
+
*/
|
|
461
|
+
private extractDocMetadata;
|
|
462
|
+
/**
|
|
463
|
+
* Slice 5b of #760 (#763) — walk every stored attachment and re-extract
|
|
464
|
+
* embedded document metadata for the supported doc MIMEs. Backfills the
|
|
465
|
+
* seven Slice-5 fields (documentTitle / documentAuthor / documentSubject /
|
|
466
|
+
* documentKeywords / documentDateCreated / documentDateModified /
|
|
467
|
+
* inLanguage) on pre-v3.27.0 records that never went through the
|
|
468
|
+
* Slice-5 extraction path at upload time.
|
|
469
|
+
*
|
|
470
|
+
* Per-file failures are non-fatal (logged + counted) — mirrors the
|
|
471
|
+
* existing `extractDocMetadata` contract where uploads succeed even when
|
|
472
|
+
* exiftool trips. Non-document MIMEs are skipped without modification.
|
|
473
|
+
* Returns a summary suitable for the background-job report.
|
|
474
|
+
*/
|
|
475
|
+
backfillDocMetadata(onProgress?: (processed: number, total: number) => void): Promise<{
|
|
476
|
+
scanned: number;
|
|
477
|
+
updated: number;
|
|
478
|
+
skipped: number;
|
|
479
|
+
errors: number;
|
|
480
|
+
}>;
|
|
481
|
+
/**
|
|
482
|
+
* Apply extracted doc-metadata to a stored record field-by-field. Sets each
|
|
483
|
+
* field when the extracted value exists; clears when extraction returned
|
|
484
|
+
* null/undefined for that field. Per-field mutation so a partial re-extract
|
|
485
|
+
* doesn't drop unrelated existing data. Returns true when the record
|
|
486
|
+
* changed (caller decides whether to persist).
|
|
487
|
+
*
|
|
488
|
+
* Shared by `backfillDocMetadata` (Slice 5b / #763) and
|
|
489
|
+
* `storeAttachmentInternal`'s dedup-by-hash branch (#764). Keeping the
|
|
490
|
+
* two call sites on the same helper ensures their "set vs clear stale"
|
|
491
|
+
* semantics stay in lockstep.
|
|
492
|
+
*/
|
|
493
|
+
private applyDocMetadataFields;
|
|
494
|
+
/**
|
|
495
|
+
* Format an exiftool-vendored date value to ISO-ish "YYYY-MM-DD HH:MM:SS".
|
|
496
|
+
* Accepts the `ExifDateTime` shape (object with year/month/etc.) or a string
|
|
497
|
+
* passthrough. Returns undefined for anything unparseable.
|
|
498
|
+
*/
|
|
499
|
+
private formatExifDate;
|
|
500
|
+
/**
|
|
501
|
+
* Convert a SchemaCreativeWork record to a schema.org-shaped CreativeWork
|
|
502
|
+
* (Slice 5 of #755 / #759).
|
|
503
|
+
*
|
|
504
|
+
* For PDF / docx / xlsx / pptx attachments → `DigitalDocument` with embedded
|
|
505
|
+
* doc-metadata fields populated. For everything else → a base CreativeWork
|
|
506
|
+
* (no subtype specialisation) — image/video attachments that need full
|
|
507
|
+
* ImageObject / VideoObject treatment are out-of-scope for this slice
|
|
508
|
+
* (they go through the media path).
|
|
509
|
+
*
|
|
510
|
+
* Public so AttachmentManager (the registered `CatalogSource`) can call it
|
|
511
|
+
* without exposing the internal SchemaCreativeWork shape.
|
|
512
|
+
*/
|
|
513
|
+
toCreativeWork(schema: SchemaCreativeWork): CreativeWork;
|
|
514
|
+
/** Convert a SchemaCreativeWork record to a unified AssetRecord. */
|
|
515
|
+
private schemaToAssetRecord;
|
|
516
|
+
/**
|
|
517
|
+
* AssetProvider.search() — searches by filename and description.
|
|
518
|
+
*
|
|
519
|
+
* The shared pool only. A private store's files are in no shared index, so
|
|
520
|
+
* they are searched through {@link searchFilesInStore}, by the one caller
|
|
521
|
+
* that has the requester's context to say which stores are theirs (#1460).
|
|
522
|
+
*/
|
|
523
|
+
search(query: AssetQuery): Promise<AssetPage>;
|
|
524
|
+
/**
|
|
525
|
+
* One private store's files as search results (#1460) — the store's half of
|
|
526
|
+
* an asset search, matched by the SAME rules the shared pool is, so a
|
|
527
|
+
* private file is findable the way a public one is and no filter exists in
|
|
528
|
+
* two places. Merging, sorting and paging are the caller's: it has the other
|
|
529
|
+
* halves.
|
|
530
|
+
*/
|
|
531
|
+
searchFilesInStore(location: StoreFileLocation, query: AssetQuery): Promise<AssetRecord[]>;
|
|
532
|
+
/**
|
|
533
|
+
* A store file as the CreativeWork shape the rest of this provider speaks
|
|
534
|
+
* (#1460), so one converter, one filter and one record shape serve both
|
|
535
|
+
* halves of a merged list. `storageLocation` is deliberately absent: where a
|
|
536
|
+
* private file sits on disk is not something a search result carries.
|
|
537
|
+
*/
|
|
538
|
+
private storeEntryToSchema;
|
|
539
|
+
/** The free-text and MIME-category rules of an asset search, in one place (#1460). */
|
|
540
|
+
private matchSchemas;
|
|
541
|
+
/**
|
|
542
|
+
* AssetProvider.updateMetadata() — edit an attachment's descriptive metadata (#999).
|
|
543
|
+
*
|
|
544
|
+
* **SIDECAR ONLY. This must never write into the file.**
|
|
545
|
+
*
|
|
546
|
+
* Attachment IDs are CONTENT HASHES — see `calculateHash`, and note the
|
|
547
|
+
* stored filename is `<sha256>.<ext>`. Media items are not content-addressed;
|
|
548
|
+
* attachments are. Writing embedded metadata (EXIF/IPTC/XMP) rewrites the
|
|
549
|
+
* file, so the id and filename stop matching the bytes they name:
|
|
550
|
+
*
|
|
551
|
+
* id c3939c4391744bc8006f726c4e8333...
|
|
552
|
+
* file sha c7ae23c100d515d5... <- after a single metadata write
|
|
553
|
+
*
|
|
554
|
+
* Nothing errors; dedup and any integrity check simply stop being true. An
|
|
555
|
+
* earlier version of this method did exactly that and was backed out
|
|
556
|
+
* (`ffe16c0d`); the failure was only caught because restoring a test file
|
|
557
|
+
* with `cmp` failed on a byte comparison.
|
|
558
|
+
*
|
|
559
|
+
* Operator decision (2026-07-28): sidecar over re-hash-and-re-key. Re-keying
|
|
560
|
+
* would be more honest — the file and its name would stay in agreement — but
|
|
561
|
+
* the id is the URL, so every existing `[{ATTACH}]` reference on every page
|
|
562
|
+
* would break on an edit. Content addressing is worth more than embedded
|
|
563
|
+
* fidelity here.
|
|
564
|
+
*
|
|
565
|
+
* **The consequence, which is real:** an attachment's ngdpbase metadata and
|
|
566
|
+
* its embedded metadata diverge after an edit, and a download carries the
|
|
567
|
+
* file's original values. Media items do not behave this way. If embedded
|
|
568
|
+
* fidelity matters for a given file, it belongs in the media library, which
|
|
569
|
+
* is not content-addressed and does write through.
|
|
570
|
+
*
|
|
571
|
+
* The tag mapping in `utils/assetMetadataTags` is deliberately NOT used here.
|
|
572
|
+
* It is correct, and it is for providers that write to files.
|
|
573
|
+
*
|
|
574
|
+
* @param id - Attachment identifier (content hash)
|
|
575
|
+
* @param patch - Fields to change; `null` clears, omission leaves alone
|
|
576
|
+
* @returns The refreshed record, or null when the attachment is unknown
|
|
577
|
+
* @throws Error when `dateTimeOriginal` is present but unparseable
|
|
578
|
+
*/
|
|
579
|
+
updateMetadata(id: string, patch: AssetMetadataPatch): Promise<AssetRecord | null>;
|
|
580
|
+
/**
|
|
581
|
+
* AssetProvider.getById() — returns AssetRecord for the given attachment ID.
|
|
582
|
+
*/
|
|
583
|
+
getById(id: string): Promise<AssetRecord | null>;
|
|
584
|
+
/**
|
|
585
|
+
* AssetProvider.store() — routed through the asset-upload door,
|
|
586
|
+
* AttachmentManager.uploadAttachment (#1629), so it gets the same
|
|
587
|
+
* permission check, destination rules and audit record as every upload.
|
|
588
|
+
*/
|
|
589
|
+
store(buffer: Buffer, info: AssetInput, ctx: ActorContext): Promise<AssetRecord>;
|
|
590
|
+
/**
|
|
591
|
+
* AssetProvider.delete() — delegates to deleteAttachment().
|
|
592
|
+
*/
|
|
593
|
+
delete(id: string): Promise<boolean>;
|
|
594
|
+
/**
|
|
595
|
+
* AssetProvider.stream() — opens a read stream for the attachment file.
|
|
596
|
+
*/
|
|
597
|
+
stream(id: string): Promise<NodeJS.ReadableStream | null>;
|
|
598
|
+
}
|
|
599
|
+
export default BasicAttachmentProvider;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CloudflareAccessAuthProvider — JWT-based trust of Cloudflare Access (#649).
|
|
3
|
+
*
|
|
4
|
+
* Cloudflare Access is a zero-trust gateway: it authenticates users at the
|
|
5
|
+
* edge (against your IdP) and forwards a signed JWT to the origin in the
|
|
6
|
+
* `Cf-Access-Jwt-Assertion` header. This provider verifies that JWT and
|
|
7
|
+
* coordinates the identity to a local User record.
|
|
8
|
+
*
|
|
9
|
+
* Design decisions (per #649 operator-confirmed 2026-05-25):
|
|
10
|
+
* - Q1 — User coordination by **email** (`identity.email` from the JWT).
|
|
11
|
+
* - Q2 — Unknown user → **JIT-provision** with default-role (overridable
|
|
12
|
+
* per CF group via `group-map`).
|
|
13
|
+
* - Q3 — CF `identity.groups[]` → ngdpbase roles via **config-map**.
|
|
14
|
+
*
|
|
15
|
+
* Cloudflare-Access-specific — not a generalised federated-IdP abstraction.
|
|
16
|
+
*
|
|
17
|
+
* Wire-up: this provider is invoked by the request-time middleware in
|
|
18
|
+
* `src/app.ts` (header → verify → JIT-or-lookup → `req.session.username`).
|
|
19
|
+
* It does NOT participate in the explicit /login flow; routes call AuthManager
|
|
20
|
+
* with `providerId='cloudflare-access'` only from the middleware path.
|
|
21
|
+
*
|
|
22
|
+
* Token verification uses `jose.createRemoteJWKSet` against
|
|
23
|
+
* `https://<team-domain>/cdn-cgi/access/certs` — keys are fetched on demand
|
|
24
|
+
* and cached + rotated by jose internally.
|
|
25
|
+
*/
|
|
26
|
+
import { type JWTVerifyGetKey } from 'jose';
|
|
27
|
+
import type { WikiEngine } from '../types/WikiEngine.js';
|
|
28
|
+
import type { AuthProvider, AuthVerifyCredentials, AuthResult, FactorDescription } from './BaseAuthProvider.js';
|
|
29
|
+
export interface CloudflareAccessConfig {
|
|
30
|
+
/** Cloudflare team domain, e.g. `mjwilleke.cloudflareaccess.com`. */
|
|
31
|
+
teamDomain: string;
|
|
32
|
+
/** Application AUD tag (one per CF Access Application). */
|
|
33
|
+
applicationAud: string;
|
|
34
|
+
/** Role assigned to JIT-provisioned users when no CF group maps. */
|
|
35
|
+
defaultRole: string;
|
|
36
|
+
/**
|
|
37
|
+
* Map of CF group name → ngdpbase role name. CF groups absent from this
|
|
38
|
+
* map are silently ignored at provisioning time (user still gets defaultRole).
|
|
39
|
+
*/
|
|
40
|
+
groupMap: Record<string, string>;
|
|
41
|
+
}
|
|
42
|
+
export declare class CloudflareAccessAuthProvider implements AuthProvider {
|
|
43
|
+
readonly id = "cloudflare-access";
|
|
44
|
+
readonly displayName = "Cloudflare Access";
|
|
45
|
+
/** An identity provider, as Google: AAL1 with no `amr` of its own (#1523). */
|
|
46
|
+
readonly factor: FactorDescription;
|
|
47
|
+
private readonly engine;
|
|
48
|
+
private readonly config;
|
|
49
|
+
private readonly jwks;
|
|
50
|
+
private readonly issuer;
|
|
51
|
+
/**
|
|
52
|
+
* @param jwksOverride optional pre-built JWKS getter for tests; production
|
|
53
|
+
* omits this and uses `createRemoteJWKSet` against the team-domain certs
|
|
54
|
+
* endpoint.
|
|
55
|
+
*/
|
|
56
|
+
constructor(engine: WikiEngine, config: CloudflareAccessConfig, jwksOverride?: JWTVerifyGetKey);
|
|
57
|
+
/**
|
|
58
|
+
* Verify the Cloudflare Access JWT and resolve (or provision) the local user.
|
|
59
|
+
* `credentials.token` is the raw JWT lifted from the `Cf-Access-Jwt-Assertion`
|
|
60
|
+
* header by the request-time middleware.
|
|
61
|
+
*/
|
|
62
|
+
verify(credentials: AuthVerifyCredentials): Promise<AuthResult | null>;
|
|
63
|
+
private resolveOrProvision;
|
|
64
|
+
/**
|
|
65
|
+
* Map CF identity.groups[] to ngdpbase role names. Groups without an
|
|
66
|
+
* entry in config.groupMap are dropped silently. Result always contains
|
|
67
|
+
* config.defaultRole — even with no group hits, user gets the default.
|
|
68
|
+
*/
|
|
69
|
+
private mapGroupsToRoles;
|
|
70
|
+
private findUserByEmail;
|
|
71
|
+
private deriveUniqueUsername;
|
|
72
|
+
}
|