@geekity/cms 0.3.0 → 0.4.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/README.md +2091 -214
- package/admin/components/fields.njk +165 -0
- package/admin/layouts/base.njk +1 -1
- package/admin/layouts/settings-page.njk +26 -0
- package/admin/layouts/shell.njk +17 -3
- package/admin/pages/account/forgot.njk +47 -0
- package/admin/pages/account/login.njk +26 -0
- package/admin/pages/account/reset.njk +38 -0
- package/admin/pages/account/setup.njk +28 -0
- package/admin/pages/appearance/themes.njk +69 -0
- package/admin/pages/comments/all.njk +133 -0
- package/admin/{layouts/dashboard.njk → pages/dashboard/home.njk} +8 -15
- package/admin/{layouts/document-conflict.njk → pages/documents/conflict.njk} +1 -0
- package/admin/pages/documents/editor.njk +196 -0
- package/admin/{layouts/document-list.njk → pages/documents/list.njk} +19 -2
- package/admin/pages/documents/taxonomy.njk +95 -0
- package/admin/pages/federation/followers.njk +238 -0
- package/admin/pages/media/library.njk +160 -0
- package/admin/pages/messages/all.njk +110 -0
- package/admin/{layouts → pages}/placeholder.njk +5 -1
- package/admin/pages/settings/discussion.njk +99 -0
- package/admin/pages/settings/email.njk +203 -0
- package/admin/pages/settings/federation.njk +75 -0
- package/admin/pages/settings/general.njk +29 -0
- package/admin/pages/settings/permalinks.njk +50 -0
- package/admin/pages/settings/reading.njk +72 -0
- package/admin/pages/users/edit.njk +239 -0
- package/admin/pages/users/list.njk +48 -0
- package/admin/pages/users/new.njk +41 -0
- package/admin/static/admin.css +498 -3
- package/admin/static/copy.js +52 -0
- package/admin/static/editor.js +16 -16
- package/admin/static/slug.js +61 -0
- package/dist/admin/accounts.d.ts +413 -0
- package/dist/admin/accounts.d.ts.map +1 -0
- package/dist/admin/accounts.js +680 -0
- package/dist/admin/accounts.js.map +1 -0
- package/dist/admin/appearance.d.ts +80 -0
- package/dist/admin/appearance.d.ts.map +1 -0
- package/dist/admin/appearance.js +136 -0
- package/dist/admin/appearance.js.map +1 -0
- package/dist/admin/comments.d.ts +90 -0
- package/dist/admin/comments.d.ts.map +1 -0
- package/dist/admin/comments.js +244 -0
- package/dist/admin/comments.js.map +1 -0
- package/dist/admin/credentials.d.ts +26 -2
- package/dist/admin/credentials.d.ts.map +1 -1
- package/dist/admin/credentials.js +35 -2
- package/dist/admin/credentials.js.map +1 -1
- package/dist/admin/documents.d.ts +127 -10
- package/dist/admin/documents.d.ts.map +1 -1
- package/dist/admin/documents.js +360 -41
- package/dist/admin/documents.js.map +1 -1
- package/dist/admin/federation.d.ts +151 -50
- package/dist/admin/federation.d.ts.map +1 -1
- package/dist/admin/federation.js +225 -93
- package/dist/admin/federation.js.map +1 -1
- package/dist/admin/formatting.d.ts +20 -0
- package/dist/admin/formatting.d.ts.map +1 -0
- package/dist/admin/formatting.js +72 -0
- package/dist/admin/formatting.js.map +1 -0
- package/dist/admin/headers.d.ts +65 -0
- package/dist/admin/headers.d.ts.map +1 -0
- package/dist/admin/headers.js +104 -0
- package/dist/admin/headers.js.map +1 -0
- package/dist/admin/index.d.ts +38 -12
- package/dist/admin/index.d.ts.map +1 -1
- package/dist/admin/index.js +25 -7
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/media.d.ts +168 -0
- package/dist/admin/media.d.ts.map +1 -0
- package/dist/admin/media.js +295 -0
- package/dist/admin/media.js.map +1 -0
- package/dist/admin/menu.d.ts +79 -0
- package/dist/admin/menu.d.ts.map +1 -0
- package/dist/admin/menu.js +126 -0
- package/dist/admin/menu.js.map +1 -0
- package/dist/admin/messages.d.ts +80 -0
- package/dist/admin/messages.d.ts.map +1 -0
- package/dist/admin/messages.js +152 -0
- package/dist/admin/messages.js.map +1 -0
- package/dist/admin/preview.d.ts.map +1 -1
- package/dist/admin/preview.js +31 -7
- package/dist/admin/preview.js.map +1 -1
- package/dist/admin/recovery.d.ts +92 -0
- package/dist/admin/recovery.d.ts.map +1 -0
- package/dist/admin/recovery.js +229 -0
- package/dist/admin/recovery.js.map +1 -0
- package/dist/admin/routes.d.ts +0 -20
- package/dist/admin/routes.d.ts.map +1 -1
- package/dist/admin/routes.js +155 -105
- package/dist/admin/routes.js.map +1 -1
- package/dist/admin/settings-discussion.d.ts +37 -0
- package/dist/admin/settings-discussion.d.ts.map +1 -0
- package/dist/admin/settings-discussion.js +117 -0
- package/dist/admin/settings-discussion.js.map +1 -0
- package/dist/admin/settings-email.d.ts +54 -0
- package/dist/admin/settings-email.d.ts.map +1 -0
- package/dist/admin/settings-email.js +189 -0
- package/dist/admin/settings-email.js.map +1 -0
- package/dist/admin/settings-federation.d.ts +39 -0
- package/dist/admin/settings-federation.d.ts.map +1 -0
- package/dist/admin/settings-federation.js +103 -0
- package/dist/admin/settings-federation.js.map +1 -0
- package/dist/admin/settings-general.d.ts +12 -0
- package/dist/admin/settings-general.d.ts.map +1 -0
- package/dist/admin/settings-general.js +48 -0
- package/dist/admin/settings-general.js.map +1 -0
- package/dist/admin/settings-page.d.ts +102 -0
- package/dist/admin/settings-page.d.ts.map +1 -0
- package/dist/admin/settings-page.js +126 -0
- package/dist/admin/settings-page.js.map +1 -0
- package/dist/admin/settings-pages.d.ts +19 -0
- package/dist/admin/settings-pages.d.ts.map +1 -0
- package/dist/admin/settings-pages.js +33 -0
- package/dist/admin/settings-pages.js.map +1 -0
- package/dist/admin/settings-permalinks.d.ts +16 -0
- package/dist/admin/settings-permalinks.d.ts.map +1 -0
- package/dist/admin/settings-permalinks.js +32 -0
- package/dist/admin/settings-permalinks.js.map +1 -0
- package/dist/admin/settings-reading.d.ts +33 -0
- package/dist/admin/settings-reading.d.ts.map +1 -0
- package/dist/admin/settings-reading.js +48 -0
- package/dist/admin/settings-reading.js.map +1 -0
- package/dist/admin/settings.d.ts +325 -96
- package/dist/admin/settings.d.ts.map +1 -1
- package/dist/admin/settings.js +650 -308
- package/dist/admin/settings.js.map +1 -1
- package/dist/admin/store.d.ts +606 -152
- package/dist/admin/store.d.ts.map +1 -1
- package/dist/admin/store.js +863 -268
- package/dist/admin/store.js.map +1 -1
- package/dist/admin/taxonomy.d.ts +114 -0
- package/dist/admin/taxonomy.d.ts.map +1 -0
- package/dist/admin/taxonomy.js +289 -0
- package/dist/admin/taxonomy.js.map +1 -0
- package/dist/admin/templates.d.ts +44 -14
- package/dist/admin/templates.d.ts.map +1 -1
- package/dist/admin/templates.js +44 -14
- package/dist/admin/templates.js.map +1 -1
- package/dist/admin/throttle.d.ts +84 -0
- package/dist/admin/throttle.d.ts.map +1 -0
- package/dist/admin/throttle.js +143 -0
- package/dist/admin/throttle.js.map +1 -0
- package/dist/admin/uploads.d.ts +28 -2
- package/dist/admin/uploads.d.ts.map +1 -1
- package/dist/admin/uploads.js +43 -4
- package/dist/admin/uploads.js.map +1 -1
- package/dist/admin/users.d.ts +100 -13
- package/dist/admin/users.d.ts.map +1 -1
- package/dist/admin/users.js +412 -39
- package/dist/admin/users.js.map +1 -1
- package/dist/cache.d.ts +141 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +207 -0
- package/dist/cache.js.map +1 -0
- package/dist/cli.d.ts +14 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +424 -21
- package/dist/cli.js.map +1 -1
- package/dist/comments/akismet.d.ts +130 -0
- package/dist/comments/akismet.d.ts.map +1 -0
- package/dist/comments/akismet.js +274 -0
- package/dist/comments/akismet.js.map +1 -0
- package/dist/comments/conversation.d.ts +29 -0
- package/dist/comments/conversation.d.ts.map +1 -0
- package/dist/comments/conversation.js +60 -0
- package/dist/comments/conversation.js.map +1 -0
- package/dist/comments/form.d.ts +75 -0
- package/dist/comments/form.d.ts.map +1 -0
- package/dist/comments/form.js +64 -0
- package/dist/comments/form.js.map +1 -0
- package/dist/comments/index.d.ts +15 -0
- package/dist/comments/index.d.ts.map +1 -0
- package/dist/comments/index.js +9 -0
- package/dist/comments/index.js.map +1 -0
- package/dist/comments/markdown.d.ts +8 -0
- package/dist/comments/markdown.d.ts.map +1 -0
- package/dist/comments/markdown.js +85 -0
- package/dist/comments/markdown.js.map +1 -0
- package/dist/comments/moderate.d.ts +71 -0
- package/dist/comments/moderate.d.ts.map +1 -0
- package/dist/comments/moderate.js +88 -0
- package/dist/comments/moderate.js.map +1 -0
- package/dist/comments/policy.d.ts +57 -0
- package/dist/comments/policy.d.ts.map +1 -0
- package/dist/comments/policy.js +80 -0
- package/dist/comments/policy.js.map +1 -0
- package/dist/comments/records.d.ts +266 -0
- package/dist/comments/records.d.ts.map +1 -0
- package/dist/comments/records.js +487 -0
- package/dist/comments/records.js.map +1 -0
- package/dist/comments/routes.d.ts +58 -0
- package/dist/comments/routes.d.ts.map +1 -0
- package/dist/comments/routes.js +177 -0
- package/dist/comments/routes.js.map +1 -0
- package/dist/comments/submission.d.ts +263 -0
- package/dist/comments/submission.d.ts.map +1 -0
- package/dist/comments/submission.js +241 -0
- package/dist/comments/submission.js.map +1 -0
- package/dist/config.d.ts +190 -5
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +118 -6
- package/dist/config.js.map +1 -1
- package/dist/contact/delivery.d.ts +60 -0
- package/dist/contact/delivery.d.ts.map +1 -0
- package/dist/contact/delivery.js +87 -0
- package/dist/contact/delivery.js.map +1 -0
- package/dist/contact/form.d.ts +130 -0
- package/dist/contact/form.d.ts.map +1 -0
- package/dist/contact/form.js +163 -0
- package/dist/contact/form.js.map +1 -0
- package/dist/contact/index.d.ts +17 -0
- package/dist/contact/index.d.ts.map +1 -0
- package/dist/contact/index.js +13 -0
- package/dist/contact/index.js.map +1 -0
- package/dist/contact/records.d.ts +124 -0
- package/dist/contact/records.d.ts.map +1 -0
- package/dist/contact/records.js +218 -0
- package/dist/contact/records.js.map +1 -0
- package/dist/contact/routes.d.ts +17 -0
- package/dist/contact/routes.d.ts.map +1 -0
- package/dist/contact/routes.js +127 -0
- package/dist/contact/routes.js.map +1 -0
- package/dist/contact/submission.d.ts +103 -0
- package/dist/contact/submission.d.ts.map +1 -0
- package/dist/contact/submission.js +166 -0
- package/dist/contact/submission.js.map +1 -0
- package/dist/content/document.d.ts +7 -2
- package/dist/content/document.d.ts.map +1 -1
- package/dist/content/document.js +1 -0
- package/dist/content/document.js.map +1 -1
- package/dist/content/index.d.ts +7 -2
- package/dist/content/index.d.ts.map +1 -1
- package/dist/content/index.js +4 -1
- package/dist/content/index.js.map +1 -1
- package/dist/content/markdown.d.ts.map +1 -1
- package/dist/content/markdown.js +24 -2
- package/dist/content/markdown.js.map +1 -1
- package/dist/content/parser.d.ts.map +1 -1
- package/dist/content/parser.js +11 -4
- package/dist/content/parser.js.map +1 -1
- package/dist/content/save.d.ts +5 -0
- package/dist/content/save.d.ts.map +1 -1
- package/dist/content/save.js +44 -1
- package/dist/content/save.js.map +1 -1
- package/dist/content/schedule.d.ts +125 -0
- package/dist/content/schedule.d.ts.map +1 -0
- package/dist/content/schedule.js +207 -0
- package/dist/content/schedule.js.map +1 -0
- package/dist/content/search.d.ts +64 -0
- package/dist/content/search.d.ts.map +1 -0
- package/dist/content/search.js +136 -0
- package/dist/content/search.js.map +1 -0
- package/dist/content/store.d.ts +202 -7
- package/dist/content/store.d.ts.map +1 -1
- package/dist/content/store.js +374 -67
- package/dist/content/store.js.map +1 -1
- package/dist/content/sync.d.ts +7 -1
- package/dist/content/sync.d.ts.map +1 -1
- package/dist/content/sync.js +18 -10
- package/dist/content/sync.js.map +1 -1
- package/dist/content/time.d.ts +56 -0
- package/dist/content/time.d.ts.map +1 -0
- package/dist/content/time.js +141 -0
- package/dist/content/time.js.map +1 -0
- package/dist/content/writer.d.ts.map +1 -1
- package/dist/content/writer.js +3 -0
- package/dist/content/writer.js.map +1 -1
- package/dist/env.d.ts +58 -4
- package/dist/env.d.ts.map +1 -1
- package/dist/federation/actor.d.ts +95 -41
- package/dist/federation/actor.d.ts.map +1 -1
- package/dist/federation/actor.js +180 -53
- package/dist/federation/actor.js.map +1 -1
- package/dist/federation/article.d.ts +44 -17
- package/dist/federation/article.d.ts.map +1 -1
- package/dist/federation/article.js +98 -46
- package/dist/federation/article.js.map +1 -1
- package/dist/federation/delivery.d.ts +63 -15
- package/dist/federation/delivery.d.ts.map +1 -1
- package/dist/federation/delivery.js +154 -80
- package/dist/federation/delivery.js.map +1 -1
- package/dist/federation/federation.d.ts +22 -17
- package/dist/federation/federation.d.ts.map +1 -1
- package/dist/federation/federation.js +98 -77
- package/dist/federation/federation.js.map +1 -1
- package/dist/federation/followers.d.ts +3 -2
- package/dist/federation/followers.d.ts.map +1 -1
- package/dist/federation/followers.js +6 -5
- package/dist/federation/followers.js.map +1 -1
- package/dist/federation/import-wordpress.d.ts +128 -0
- package/dist/federation/import-wordpress.d.ts.map +1 -0
- package/dist/federation/import-wordpress.js +426 -0
- package/dist/federation/import-wordpress.js.map +1 -0
- package/dist/federation/inbox.d.ts +36 -13
- package/dist/federation/inbox.d.ts.map +1 -1
- package/dist/federation/inbox.js +120 -49
- package/dist/federation/inbox.js.map +1 -1
- package/dist/federation/index.d.ts +22 -10
- package/dist/federation/index.d.ts.map +1 -1
- package/dist/federation/index.js +13 -8
- package/dist/federation/index.js.map +1 -1
- package/dist/federation/keys.d.ts +98 -20
- package/dist/federation/keys.d.ts.map +1 -1
- package/dist/federation/keys.js +269 -39
- package/dist/federation/keys.js.map +1 -1
- package/dist/federation/mount.d.ts +42 -10
- package/dist/federation/mount.d.ts.map +1 -1
- package/dist/federation/mount.js +266 -26
- package/dist/federation/mount.js.map +1 -1
- package/dist/federation/paths.d.ts +23 -35
- package/dist/federation/paths.d.ts.map +1 -1
- package/dist/federation/paths.js +26 -39
- package/dist/federation/paths.js.map +1 -1
- package/dist/federation/records.d.ts +223 -0
- package/dist/federation/records.d.ts.map +1 -0
- package/dist/federation/records.js +506 -0
- package/dist/federation/records.js.map +1 -0
- package/dist/federation/relays.d.ts +114 -0
- package/dist/federation/relays.d.ts.map +1 -0
- package/dist/federation/relays.js +290 -0
- package/dist/federation/relays.js.map +1 -0
- package/dist/federation/replies.d.ts +80 -0
- package/dist/federation/replies.d.ts.map +1 -0
- package/dist/federation/replies.js +166 -0
- package/dist/federation/replies.js.map +1 -0
- package/dist/federation/wordpress.d.ts +131 -0
- package/dist/federation/wordpress.d.ts.map +1 -0
- package/dist/federation/wordpress.js +341 -0
- package/dist/federation/wordpress.js.map +1 -0
- package/dist/files/atomic.d.ts +103 -0
- package/dist/files/atomic.d.ts.map +1 -0
- package/dist/files/atomic.js +150 -0
- package/dist/files/atomic.js.map +1 -0
- package/dist/files/index.d.ts +3 -0
- package/dist/files/index.d.ts.map +1 -0
- package/dist/files/index.js +2 -0
- package/dist/files/index.js.map +1 -0
- package/dist/forms/protection.d.ts +85 -0
- package/dist/forms/protection.d.ts.map +1 -0
- package/dist/forms/protection.js +116 -0
- package/dist/forms/protection.js.map +1 -0
- package/dist/images/icons.d.ts +59 -0
- package/dist/images/icons.d.ts.map +1 -0
- package/dist/images/icons.js +131 -0
- package/dist/images/icons.js.map +1 -0
- package/dist/images/index.d.ts +7 -0
- package/dist/images/index.d.ts.map +1 -0
- package/dist/images/index.js +4 -0
- package/dist/images/index.js.map +1 -0
- package/dist/images/markup.d.ts +47 -0
- package/dist/images/markup.d.ts.map +1 -0
- package/dist/images/markup.js +175 -0
- package/dist/images/markup.js.map +1 -0
- package/dist/images/paths.d.ts +34 -0
- package/dist/images/paths.d.ts.map +1 -0
- package/dist/images/paths.js +41 -0
- package/dist/images/paths.js.map +1 -0
- package/dist/images/variants.d.ts +104 -0
- package/dist/images/variants.d.ts.map +1 -0
- package/dist/images/variants.js +320 -0
- package/dist/images/variants.js.map +1 -0
- package/dist/index.d.ts +123 -19
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +327 -25
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts +18 -0
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +34 -3
- package/dist/init.js.map +1 -1
- package/dist/mail/brevo.d.ts +35 -0
- package/dist/mail/brevo.d.ts.map +1 -0
- package/dist/mail/brevo.js +85 -0
- package/dist/mail/brevo.js.map +1 -0
- package/dist/mail/credentials.d.ts +62 -0
- package/dist/mail/credentials.d.ts.map +1 -0
- package/dist/mail/credentials.js +86 -0
- package/dist/mail/credentials.js.map +1 -0
- package/dist/mail/index.d.ts +15 -0
- package/dist/mail/index.d.ts.map +1 -0
- package/dist/mail/index.js +8 -0
- package/dist/mail/index.js.map +1 -0
- package/dist/mail/memory.d.ts +35 -0
- package/dist/mail/memory.d.ts.map +1 -0
- package/dist/mail/memory.js +29 -0
- package/dist/mail/memory.js.map +1 -0
- package/dist/mail/provider.d.ts +80 -0
- package/dist/mail/provider.d.ts.map +1 -0
- package/dist/mail/provider.js +23 -0
- package/dist/mail/provider.js.map +1 -0
- package/dist/mail/service.d.ts +156 -0
- package/dist/mail/service.d.ts.map +1 -0
- package/dist/mail/service.js +265 -0
- package/dist/mail/service.js.map +1 -0
- package/dist/mail/smtp.d.ts +39 -0
- package/dist/mail/smtp.d.ts.map +1 -0
- package/dist/mail/smtp.js +58 -0
- package/dist/mail/smtp.js.map +1 -0
- package/dist/mail/templates.d.ts +91 -0
- package/dist/mail/templates.d.ts.map +1 -0
- package/dist/mail/templates.js +69 -0
- package/dist/mail/templates.js.map +1 -0
- package/dist/notifications/comments.d.ts +66 -0
- package/dist/notifications/comments.d.ts.map +1 -0
- package/dist/notifications/comments.js +151 -0
- package/dist/notifications/comments.js.map +1 -0
- package/dist/notifications/digest.d.ts +135 -0
- package/dist/notifications/digest.d.ts.map +1 -0
- package/dist/notifications/digest.js +287 -0
- package/dist/notifications/digest.js.map +1 -0
- package/dist/notifications/index.d.ts +13 -0
- package/dist/notifications/index.d.ts.map +1 -0
- package/dist/notifications/index.js +8 -0
- package/dist/notifications/index.js.map +1 -0
- package/dist/notifications/links.d.ts +60 -0
- package/dist/notifications/links.d.ts.map +1 -0
- package/dist/notifications/links.js +63 -0
- package/dist/notifications/links.js.map +1 -0
- package/dist/notifications/optouts.d.ts +48 -0
- package/dist/notifications/optouts.d.ts.map +1 -0
- package/dist/notifications/optouts.js +93 -0
- package/dist/notifications/optouts.js.map +1 -0
- package/dist/notifications/preferences.d.ts +158 -0
- package/dist/notifications/preferences.d.ts.map +1 -0
- package/dist/notifications/preferences.js +195 -0
- package/dist/notifications/preferences.js.map +1 -0
- package/dist/notifications/routes.d.ts +28 -0
- package/dist/notifications/routes.d.ts.map +1 -0
- package/dist/notifications/routes.js +184 -0
- package/dist/notifications/routes.js.map +1 -0
- package/dist/notifications/tokens.d.ts +60 -0
- package/dist/notifications/tokens.d.ts.map +1 -0
- package/dist/notifications/tokens.js +125 -0
- package/dist/notifications/tokens.js.map +1 -0
- package/dist/notify.d.ts +84 -0
- package/dist/notify.d.ts.map +1 -0
- package/dist/notify.js +149 -0
- package/dist/notify.js.map +1 -0
- package/dist/web/archive.d.ts +49 -0
- package/dist/web/archive.d.ts.map +1 -0
- package/dist/web/archive.js +59 -0
- package/dist/web/archive.js.map +1 -0
- package/dist/web/assets.d.ts +6 -5
- package/dist/web/assets.d.ts.map +1 -1
- package/dist/web/assets.js +5 -7
- package/dist/web/assets.js.map +1 -1
- package/dist/web/authors.d.ts +143 -0
- package/dist/web/authors.d.ts.map +1 -0
- package/dist/web/authors.js +178 -0
- package/dist/web/authors.js.map +1 -0
- package/dist/web/comments.d.ts +60 -0
- package/dist/web/comments.d.ts.map +1 -0
- package/dist/web/comments.js +207 -0
- package/dist/web/comments.js.map +1 -0
- package/dist/web/context.d.ts +162 -28
- package/dist/web/context.d.ts.map +1 -1
- package/dist/web/context.js +123 -26
- package/dist/web/context.js.map +1 -1
- package/dist/web/conversation.d.ts +209 -0
- package/dist/web/conversation.d.ts.map +1 -0
- package/dist/web/conversation.js +557 -0
- package/dist/web/conversation.js.map +1 -0
- package/dist/web/documents.d.ts +36 -6
- package/dist/web/documents.d.ts.map +1 -1
- package/dist/web/documents.js +52 -10
- package/dist/web/documents.js.map +1 -1
- package/dist/web/feed-atom.d.ts +22 -0
- package/dist/web/feed-atom.d.ts.map +1 -0
- package/dist/web/feed-atom.js +83 -0
- package/dist/web/feed-atom.js.map +1 -0
- package/dist/web/feed-item.d.ts +145 -0
- package/dist/web/feed-item.d.ts.map +1 -0
- package/dist/web/feed-item.js +120 -0
- package/dist/web/feed-item.js.map +1 -0
- package/dist/web/feed-json.d.ts +79 -0
- package/dist/web/feed-json.d.ts.map +1 -0
- package/dist/web/feed-json.js +53 -0
- package/dist/web/feed-json.js.map +1 -0
- package/dist/web/feed-rss.d.ts +26 -0
- package/dist/web/feed-rss.d.ts.map +1 -0
- package/dist/web/feed-rss.js +203 -0
- package/dist/web/feed-rss.js.map +1 -0
- package/dist/web/feed-source.d.ts +244 -0
- package/dist/web/feed-source.d.ts.map +1 -0
- package/dist/web/feed-source.js +201 -0
- package/dist/web/feed-source.js.map +1 -0
- package/dist/web/feed-xml.d.ts +63 -0
- package/dist/web/feed-xml.d.ts.map +1 -0
- package/dist/web/feed-xml.js +116 -0
- package/dist/web/feed-xml.js.map +1 -0
- package/dist/web/feeds.d.ts +31 -96
- package/dist/web/feeds.d.ts.map +1 -1
- package/dist/web/feeds.js +94 -198
- package/dist/web/feeds.js.map +1 -1
- package/dist/web/health.d.ts +31 -0
- package/dist/web/health.d.ts.map +1 -0
- package/dist/web/health.js +44 -0
- package/dist/web/health.js.map +1 -0
- package/dist/web/index.d.ts +30 -10
- package/dist/web/index.d.ts.map +1 -1
- package/dist/web/index.js +18 -7
- package/dist/web/index.js.map +1 -1
- package/dist/web/navigation.d.ts +73 -0
- package/dist/web/navigation.d.ts.map +1 -0
- package/dist/web/navigation.js +110 -0
- package/dist/web/navigation.js.map +1 -0
- package/dist/web/negotiate.d.ts +9 -0
- package/dist/web/negotiate.d.ts.map +1 -1
- package/dist/web/negotiate.js +6 -1
- package/dist/web/negotiate.js.map +1 -1
- package/dist/web/recent.d.ts +43 -0
- package/dist/web/recent.d.ts.map +1 -0
- package/dist/web/recent.js +37 -0
- package/dist/web/recent.js.map +1 -0
- package/dist/web/render.d.ts +197 -9
- package/dist/web/render.d.ts.map +1 -1
- package/dist/web/render.js +334 -17
- package/dist/web/render.js.map +1 -1
- package/dist/web/routes.d.ts +25 -8
- package/dist/web/routes.d.ts.map +1 -1
- package/dist/web/routes.js +845 -93
- package/dist/web/routes.js.map +1 -1
- package/dist/web/sanitize.d.ts +19 -0
- package/dist/web/sanitize.d.ts.map +1 -0
- package/dist/web/sanitize.js +272 -0
- package/dist/web/sanitize.js.map +1 -0
- package/dist/web/search.d.ts +79 -0
- package/dist/web/search.d.ts.map +1 -0
- package/dist/web/search.js +94 -0
- package/dist/web/search.js.map +1 -0
- package/dist/web/sitemap.d.ts +120 -0
- package/dist/web/sitemap.d.ts.map +1 -0
- package/dist/web/sitemap.js +199 -0
- package/dist/web/sitemap.js.map +1 -0
- package/dist/web/taxonomy.d.ts +152 -0
- package/dist/web/taxonomy.d.ts.map +1 -0
- package/dist/web/taxonomy.js +237 -0
- package/dist/web/taxonomy.js.map +1 -0
- package/dist/web/templates.d.ts +54 -16
- package/dist/web/templates.d.ts.map +1 -1
- package/dist/web/templates.js +109 -28
- package/dist/web/templates.js.map +1 -1
- package/dist/web/themes.d.ts +205 -0
- package/dist/web/themes.d.ts.map +1 -0
- package/dist/web/themes.js +277 -0
- package/dist/web/themes.js.map +1 -0
- package/dist/webmention/discovery.d.ts +51 -0
- package/dist/webmention/discovery.d.ts.map +1 -0
- package/dist/webmention/discovery.js +176 -0
- package/dist/webmention/discovery.js.map +1 -0
- package/dist/webmention/html.d.ts +71 -0
- package/dist/webmention/html.d.ts.map +1 -0
- package/dist/webmention/html.js +285 -0
- package/dist/webmention/html.js.map +1 -0
- package/dist/webmention/index.d.ts +12 -0
- package/dist/webmention/index.d.ts.map +1 -0
- package/dist/webmention/index.js +8 -0
- package/dist/webmention/index.js.map +1 -0
- package/dist/webmention/links.d.ts +18 -0
- package/dist/webmention/links.d.ts.map +1 -0
- package/dist/webmention/links.js +64 -0
- package/dist/webmention/links.js.map +1 -0
- package/dist/webmention/microformats.d.ts +93 -0
- package/dist/webmention/microformats.d.ts.map +1 -0
- package/dist/webmention/microformats.js +376 -0
- package/dist/webmention/microformats.js.map +1 -0
- package/dist/webmention/receive.d.ts +141 -0
- package/dist/webmention/receive.d.ts.map +1 -0
- package/dist/webmention/receive.js +264 -0
- package/dist/webmention/receive.js.map +1 -0
- package/dist/webmention/routes.d.ts +37 -0
- package/dist/webmention/routes.d.ts.map +1 -0
- package/dist/webmention/routes.js +75 -0
- package/dist/webmention/routes.js.map +1 -0
- package/dist/webmention/service.d.ts +94 -0
- package/dist/webmention/service.d.ts.map +1 -0
- package/dist/webmention/service.js +207 -0
- package/dist/webmention/service.js.map +1 -0
- package/package.json +11 -6
- package/templates/site/content/_data/site.json +1 -0
- package/templates/site/content/posts/2026-01-01-hello-world.md +5 -3
- package/templates/site/geekity.config.ts +11 -1
- package/templates/site/tsconfig.json +1 -1
- package/themes/default/README.md +1096 -50
- package/themes/default/layouts/404.njk +2 -3
- package/themes/default/layouts/author.njk +37 -0
- package/themes/default/layouts/base.njk +172 -31
- package/themes/default/layouts/category.njk +27 -0
- package/themes/default/layouts/front-page.njk +57 -0
- package/themes/default/layouts/home.njk +17 -1
- package/themes/default/layouts/page.njk +57 -5
- package/themes/default/layouts/post.njk +78 -19
- package/themes/default/layouts/search.njk +57 -0
- package/themes/default/layouts/tag.njk +3 -6
- package/themes/default/mail/comment-digest.html.njk +37 -0
- package/themes/default/mail/comment-digest.subject.njk +3 -0
- package/themes/default/mail/comment-digest.txt.njk +40 -0
- package/themes/default/mail/comment-pending.html.njk +27 -0
- package/themes/default/mail/comment-pending.subject.njk +2 -0
- package/themes/default/mail/comment-pending.txt.njk +24 -0
- package/themes/default/mail/comment-reply.html.njk +21 -0
- package/themes/default/mail/comment-reply.subject.njk +2 -0
- package/themes/default/mail/comment-reply.txt.njk +22 -0
- package/themes/default/mail/contact-message.html.njk +24 -0
- package/themes/default/mail/contact-message.subject.njk +5 -0
- package/themes/default/mail/contact-message.txt.njk +20 -0
- package/themes/default/mail/password-changed.html.njk +18 -0
- package/themes/default/mail/password-changed.subject.njk +2 -0
- package/themes/default/mail/password-changed.txt.njk +17 -0
- package/themes/default/mail/password-reset.html.njk +22 -0
- package/themes/default/mail/password-reset.subject.njk +2 -0
- package/themes/default/mail/password-reset.txt.njk +18 -0
- package/themes/default/mail/test.html.njk +14 -0
- package/themes/default/mail/test.subject.njk +2 -0
- package/themes/default/mail/test.txt.njk +12 -0
- package/themes/default/partials/archive.njk +27 -0
- package/themes/default/partials/bio.njk +77 -0
- package/themes/default/partials/comment-form.njk +109 -0
- package/themes/default/partials/contact-form.njk +88 -0
- package/themes/default/partials/conversation.njk +139 -0
- package/themes/default/partials/feeds.njk +26 -0
- package/themes/default/partials/jsonld.njk +120 -0
- package/themes/default/partials/pagination.njk +12 -6
- package/themes/default/partials/post-list.njk +51 -18
- package/themes/default/partials/search-form.njk +17 -0
- package/themes/default/partials/tags.njk +26 -5
- package/themes/default/static/highlight.js +4 -0
- package/themes/default/static/style.css +1119 -194
- package/themes/default/theme.json +5 -0
- package/admin/layouts/document-editor.njk +0 -167
- package/admin/layouts/federation.njk +0 -145
- package/admin/layouts/login.njk +0 -23
- package/admin/layouts/settings.njk +0 -116
- package/admin/layouts/setup.njk +0 -27
- package/admin/layouts/users.njk +0 -91
- /package/admin/{layouts/_flash.njk → components/flash.njk} +0 -0
package/dist/federation/keys.js
CHANGED
|
@@ -1,60 +1,290 @@
|
|
|
1
|
+
import { mkdirSync } from 'node:fs';
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
1
4
|
import { exportJwk, generateCryptoKeyPair, importJwk } from '@fedify/fedify';
|
|
2
|
-
import {
|
|
5
|
+
import { readFileIfPresentSync, updateFileAtomically, writeFileAtomicallySync, } from '../files/atomic.js';
|
|
3
6
|
/**
|
|
4
|
-
* The
|
|
7
|
+
* The algorithms an actor holds a key pair for, in the order Fedify wants them:
|
|
8
|
+
* the RSA pair signs HTTP Signatures for Mastodon and friends, the Ed25519
|
|
9
|
+
* pair signs FEP-8b32 integrity proofs.
|
|
10
|
+
*/
|
|
11
|
+
export const ACTOR_KEY_ALGORITHMS = ['RSASSA-PKCS1-v1_5', 'Ed25519'];
|
|
12
|
+
/** Where an actor's key files live: `data/keys`, beside the disposable index. */
|
|
13
|
+
export function actorKeysDir(dataDir) {
|
|
14
|
+
return path.join(dataDir, 'keys');
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The file one key pair lives in, e.g. `data/keys/ada.ed25519.jwk`.
|
|
18
|
+
*
|
|
19
|
+
* The identifier is the user's username (decision-14), which is also what
|
|
20
|
+
* their actor id is built from, so a site can tell at a glance whose key a
|
|
21
|
+
* file is; and the algorithm is in the name too, so the two pairs are
|
|
22
|
+
* independent files that can be backed up, restored and regenerated one at a
|
|
23
|
+
* time.
|
|
24
|
+
*
|
|
25
|
+
* `algorithm` is a bare string rather than an {@link ActorKeyAlgorithm}, for
|
|
26
|
+
* the migration's sake: a row written by a version that knows an algorithm
|
|
27
|
+
* this one does not still has to reach a file before the table is dropped.
|
|
28
|
+
*/
|
|
29
|
+
export function actorKeyFile(dataDir, identifier, algorithm) {
|
|
30
|
+
return path.join(actorKeysDir(dataDir), `${fileToken(identifier)}.${fileToken(algorithm)}.jwk`);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Put one private JWK on disk as a user's key file for an algorithm, replacing
|
|
34
|
+
* whatever was there, and answer with the path it was written to.
|
|
35
|
+
*
|
|
36
|
+
* The only door into `data/keys` that is not {@link loadActorKeyPairs}, and it
|
|
37
|
+
* exists for the import (TASK-71): a key pair that arrives from somewhere else
|
|
38
|
+
* is the one case where a file has to be written from bytes the CMS did not
|
|
39
|
+
* mint. Everything about the layout stays here rather than at the caller — the
|
|
40
|
+
* name, the `0700` directory and the `0600` file — so there is one answer to
|
|
41
|
+
* where a user's key lives.
|
|
5
42
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* and its stored keys are all built from. Renaming `@blog@example.com` to
|
|
10
|
-
* `@notes@example.com` therefore leaves every URL — and every follower — alone.
|
|
43
|
+
* It does not decide whether writing is allowed: an existing key is somebody's
|
|
44
|
+
* identity, and the caller is the one that knows whether it was told to
|
|
45
|
+
* replace it.
|
|
11
46
|
*/
|
|
12
|
-
export
|
|
47
|
+
export function writeActorKeyFile(dataDir, identifier, algorithm, privateJwk) {
|
|
48
|
+
const file = actorKeyFile(dataDir, identifier, algorithm);
|
|
49
|
+
ensureKeysDir(dataDir);
|
|
50
|
+
writeFileAtomicallySync(file, `${privateJwk.trimEnd()}\n`, { mode: KEY_FILE_MODE });
|
|
51
|
+
return file;
|
|
52
|
+
}
|
|
13
53
|
/**
|
|
14
|
-
*
|
|
15
|
-
* every one after that.
|
|
54
|
+
* One user's key pairs, generated on the first call and read from
|
|
55
|
+
* `data/keys` on every one after that.
|
|
16
56
|
*
|
|
17
|
-
* Both of {@link ACTOR_KEY_ALGORITHMS} are returned, in that order
|
|
18
|
-
* the
|
|
19
|
-
*
|
|
57
|
+
* Both of {@link ACTOR_KEY_ALGORITHMS} are returned, in that order. Each file
|
|
58
|
+
* holds the private JWK alone, because the public key is derivable from it:
|
|
59
|
+
* one file per pair is one thing to back up and one thing that cannot fall
|
|
60
|
+
* half out of step with itself.
|
|
20
61
|
*
|
|
21
|
-
* A
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
62
|
+
* A file that will not import is thrown over rather than replaced (decision-9).
|
|
63
|
+
* The old code healed a damaged row by generating a new pair, which is exactly
|
|
64
|
+
* the wrong thing to do with an identity: every follower holds the public key
|
|
65
|
+
* and would stop verifying the site's posts. A site that really does want a
|
|
66
|
+
* new key deletes the file, which is a deliberate act rather than an accident
|
|
67
|
+
* of a half-written byte.
|
|
26
68
|
*/
|
|
27
|
-
export async function loadActorKeyPairs(
|
|
28
|
-
const stored = new Map(store.listActorKeys(identifier).map((key) => [key.algorithm, key]));
|
|
69
|
+
export async function loadActorKeyPairs(dataDir, identifier) {
|
|
29
70
|
const pairs = [];
|
|
30
71
|
for (const algorithm of ACTOR_KEY_ALGORITHMS) {
|
|
31
|
-
|
|
32
|
-
const imported = row === undefined ? undefined : await importPair(row.privateJwk, row.publicJwk);
|
|
33
|
-
pairs.push(imported ?? (await generatePair(store, identifier, algorithm)));
|
|
72
|
+
pairs.push(await loadPair(dataDir, identifier, algorithm));
|
|
34
73
|
}
|
|
35
74
|
return pairs;
|
|
36
75
|
}
|
|
37
|
-
/**
|
|
38
|
-
|
|
76
|
+
/**
|
|
77
|
+
* Turn an older site's `actor_keys` rows into files under `data/keys`, once,
|
|
78
|
+
* and drop the table.
|
|
79
|
+
*
|
|
80
|
+
* The rows this writes out are the site actor's, which no version after
|
|
81
|
+
* TASK-68 has: decision-14 replaced it with one actor per user, and a user's
|
|
82
|
+
* keys are named after their username rather than after the sentinel `actor`.
|
|
83
|
+
* The files are still written rather than dropped on the floor, because a
|
|
84
|
+
* private key is the one thing this CMS never deletes for somebody — an
|
|
85
|
+
* operator who wants the old identity back has it on disk to move.
|
|
86
|
+
*
|
|
87
|
+
* This is the migration decision-9 calls the one that must not fail. Settings
|
|
88
|
+
* a site could type again and followers a site could ask for again; an actor's
|
|
89
|
+
* private key is the site's identity, and losing it means every follower's
|
|
90
|
+
* cached public key stops verifying its posts for good. So the rows are
|
|
91
|
+
* written out before the table goes, never after, and a file that is already
|
|
92
|
+
* there always wins — a site that has booted this version once has the truth
|
|
93
|
+
* on disk, and a row left over from before it did must not overwrite it.
|
|
94
|
+
*
|
|
95
|
+
* Synchronous because `createCms` is: it runs before the server is listening
|
|
96
|
+
* and before anything has asked for a key.
|
|
97
|
+
*/
|
|
98
|
+
export function migrateActorKeysToFiles(options) {
|
|
99
|
+
const { admin, dataDir } = options;
|
|
100
|
+
const rows = admin.legacyActorKeys();
|
|
101
|
+
if (rows !== undefined && rows.length > 0) {
|
|
102
|
+
ensureKeysDir(dataDir);
|
|
103
|
+
for (const row of rows) {
|
|
104
|
+
const file = actorKeyFile(dataDir, row.identifier, row.algorithm);
|
|
105
|
+
// Only the private half is written: the public one is derived from it,
|
|
106
|
+
// and a stored pair whose halves disagreed would be worse than none. The
|
|
107
|
+
// row is written out as it stands, byte for byte apart from the trailing
|
|
108
|
+
// newline every file here ends with — a key is not something to
|
|
109
|
+
// re-encode on the way past.
|
|
110
|
+
if (readFileIfPresentSync(file) === undefined) {
|
|
111
|
+
writeFileAtomicallySync(file, `${row.privateJwk.trimEnd()}\n`, { mode: KEY_FILE_MODE });
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// Dropped whether or not it had rows: a fresh database gets the table from
|
|
116
|
+
// migration 4, which has shipped and so is never edited, and a site that has
|
|
117
|
+
// been migrated must not be asked again on the next boot.
|
|
118
|
+
admin.dropLegacyTable('actor_keys');
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Refuse to boot on a key file that is there but is not a key.
|
|
122
|
+
*
|
|
123
|
+
* `loadActorKeyPairs` throws over such a file, but nothing useful happens to
|
|
124
|
+
* that throw: Fedify catches whatever the key pairs dispatcher raises and
|
|
125
|
+
* hands back an empty list, so the site would go on answering with an actor
|
|
126
|
+
* that publishes no `publicKey` and no `assertionMethod` — unverifiable to
|
|
127
|
+
* every follower, and silent about it. Boot is where that is caught instead,
|
|
128
|
+
* and refusing to start is the report: a site is down for a minute and the
|
|
129
|
+
* message names the file to restore, rather than up for a week signing
|
|
130
|
+
* nothing.
|
|
131
|
+
*
|
|
132
|
+
* The checks are the ones `importJwk` makes, minus the arithmetic, because
|
|
133
|
+
* they are all that can be made without an `await` inside a synchronous boot.
|
|
134
|
+
* That is enough for every way a key file really goes wrong — truncated by a
|
|
135
|
+
* crash, emptied, replaced by something that is not a key at all. A JWK that
|
|
136
|
+
* is well formed and still will not import is left to
|
|
137
|
+
* {@link loadActorKeyPairs}, which throws the same error with the same advice.
|
|
138
|
+
*/
|
|
139
|
+
export function assertActorKeysUsable(dataDir, identifier) {
|
|
140
|
+
for (const algorithm of ACTOR_KEY_ALGORITHMS) {
|
|
141
|
+
const file = actorKeyFile(dataDir, identifier, algorithm);
|
|
142
|
+
const contents = readFileIfPresentSync(file);
|
|
143
|
+
// Absent is not damaged: the first boot of a new site has no key files at
|
|
144
|
+
// all, and the first actor request writes them.
|
|
145
|
+
if (contents === undefined)
|
|
146
|
+
continue;
|
|
147
|
+
let jwk;
|
|
148
|
+
try {
|
|
149
|
+
jwk = JSON.parse(contents);
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
throw unusableKey(file, error);
|
|
153
|
+
}
|
|
154
|
+
const problem = jwkProblem(jwk, algorithm);
|
|
155
|
+
if (problem !== undefined)
|
|
156
|
+
throw unusableKey(file, new Error(problem));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/** What is wrong with a parsed key file, or `undefined` when nothing is. */
|
|
160
|
+
function jwkProblem(jwk, algorithm) {
|
|
161
|
+
if (typeof jwk !== 'object' || jwk === null)
|
|
162
|
+
return 'it is not a JSON object';
|
|
163
|
+
const key = jwk;
|
|
164
|
+
const has = (member) => typeof key[member] === 'string';
|
|
165
|
+
if (!has('d'))
|
|
166
|
+
return 'it carries no private key: a JWK with no "d" is only the public half';
|
|
167
|
+
if (algorithm === 'RSASSA-PKCS1-v1_5') {
|
|
168
|
+
if (key['kty'] !== 'RSA')
|
|
169
|
+
return `its "kty" is ${JSON.stringify(key['kty'])}, not "RSA"`;
|
|
170
|
+
if (key['alg'] !== 'RS256')
|
|
171
|
+
return `its "alg" is ${JSON.stringify(key['alg'])}, not "RS256"`;
|
|
172
|
+
if (!has('n') || !has('e'))
|
|
173
|
+
return 'an RSA key needs both "n" and "e"';
|
|
174
|
+
return undefined;
|
|
175
|
+
}
|
|
176
|
+
if (key['kty'] !== 'OKP')
|
|
177
|
+
return `its "kty" is ${JSON.stringify(key['kty'])}, not "OKP"`;
|
|
178
|
+
if (key['crv'] !== 'Ed25519') {
|
|
179
|
+
return `its "crv" is ${JSON.stringify(key['crv'])}, not "Ed25519"`;
|
|
180
|
+
}
|
|
181
|
+
if (!has('x'))
|
|
182
|
+
return 'an Ed25519 key needs an "x"';
|
|
183
|
+
return undefined;
|
|
184
|
+
}
|
|
185
|
+
/** One algorithm's pair: the file's, or a new one written to the file. */
|
|
186
|
+
async function loadPair(dataDir, identifier, algorithm) {
|
|
187
|
+
const file = actorKeyFile(dataDir, identifier, algorithm);
|
|
188
|
+
const stored = await readIfPresent(file);
|
|
189
|
+
if (stored !== undefined)
|
|
190
|
+
return await importPair(file, stored);
|
|
191
|
+
// Absent: generate. The write goes through the queue and looks again inside
|
|
192
|
+
// it, so two first calls racing each other cannot each mint a key and leave
|
|
193
|
+
// the site publishing one it does not hold.
|
|
194
|
+
let jwk = '';
|
|
195
|
+
ensureKeysDir(dataDir);
|
|
196
|
+
await updateFileAtomically(file, async (current) => {
|
|
197
|
+
if (current !== undefined) {
|
|
198
|
+
jwk = current;
|
|
199
|
+
return current;
|
|
200
|
+
}
|
|
201
|
+
const pair = await generateCryptoKeyPair(algorithm);
|
|
202
|
+
jwk = `${JSON.stringify(await exportJwk(pair.privateKey), undefined, 2)}\n`;
|
|
203
|
+
return jwk;
|
|
204
|
+
}, { mode: KEY_FILE_MODE });
|
|
205
|
+
return await importPair(file, jwk);
|
|
206
|
+
}
|
|
207
|
+
/** A file's contents, or `undefined` when it is not there. */
|
|
208
|
+
async function readIfPresent(file) {
|
|
39
209
|
try {
|
|
40
|
-
return
|
|
41
|
-
privateKey: await importJwk(JSON.parse(privateJwk), 'private'),
|
|
42
|
-
publicKey: await importJwk(JSON.parse(publicJwk), 'public'),
|
|
43
|
-
};
|
|
210
|
+
return await readFile(file, 'utf8');
|
|
44
211
|
}
|
|
45
212
|
catch {
|
|
46
213
|
return undefined;
|
|
47
214
|
}
|
|
48
215
|
}
|
|
49
|
-
/**
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
216
|
+
/**
|
|
217
|
+
* The pair a stored private JWK stands for, or a thrown error naming the file.
|
|
218
|
+
*
|
|
219
|
+
* The public half is derived rather than stored: the private JWK carries every
|
|
220
|
+
* public member already, so dropping the private ones leaves exactly the
|
|
221
|
+
* public key. Nothing else could be true — a stored public key that disagreed
|
|
222
|
+
* with the private one would be a site signing with a key nobody could check.
|
|
223
|
+
*/
|
|
224
|
+
async function importPair(file, contents) {
|
|
225
|
+
let jwk;
|
|
226
|
+
try {
|
|
227
|
+
jwk = JSON.parse(contents);
|
|
228
|
+
}
|
|
229
|
+
catch (error) {
|
|
230
|
+
throw unusableKey(file, error);
|
|
231
|
+
}
|
|
232
|
+
try {
|
|
233
|
+
return {
|
|
234
|
+
privateKey: await importJwk(jwk, 'private'),
|
|
235
|
+
publicKey: await importJwk(publicHalfOf(jwk), 'public'),
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
catch (error) {
|
|
239
|
+
throw unusableKey(file, error);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* The public members of a JWK, and only those.
|
|
244
|
+
*
|
|
245
|
+
* `d`, `p`, `q`, `dp`, `dq` and `qi` are the private ones; `key_ops` has to go
|
|
246
|
+
* too, because a key exported for signing says `["sign"]` and importing it for
|
|
247
|
+
* verification with that still on it is refused.
|
|
248
|
+
*/
|
|
249
|
+
function publicHalfOf(jwk) {
|
|
250
|
+
const publicMembers = ['kty', 'alg', 'crv', 'n', 'e', 'x'];
|
|
251
|
+
const half = {};
|
|
252
|
+
for (const member of publicMembers) {
|
|
253
|
+
if (jwk[member] !== undefined)
|
|
254
|
+
half[member] = jwk[member];
|
|
255
|
+
}
|
|
256
|
+
return half;
|
|
257
|
+
}
|
|
258
|
+
/** The error a key file that will not import raises, with what to do about it. */
|
|
259
|
+
function unusableKey(file, cause) {
|
|
260
|
+
return new Error(`The actor key file ${file} could not be read as a JWK private key: ` +
|
|
261
|
+
`${cause instanceof Error ? cause.message : String(cause)}. ` +
|
|
262
|
+
'It has deliberately not been replaced, because a new key would change the ' +
|
|
263
|
+
'actor’s identity and every follower would stop verifying the site. Restore ' +
|
|
264
|
+
'the file from a backup, or delete it to ask for a new key on purpose.', { cause });
|
|
265
|
+
}
|
|
266
|
+
/** The permissions a private key file is created and rewritten with. */
|
|
267
|
+
const KEY_FILE_MODE = 0o600;
|
|
268
|
+
/** The permissions `data/keys` is created with, when this is what creates it. */
|
|
269
|
+
const KEYS_DIR_MODE = 0o700;
|
|
270
|
+
/**
|
|
271
|
+
* The part of a file name one identifier or algorithm contributes.
|
|
272
|
+
*
|
|
273
|
+
* Lower case, because `RSASSA-PKCS1-v1_5` on a case-insensitive filesystem is
|
|
274
|
+
* the same file as `rsassa-pkcs1-v1_5` and only one of them should ever be
|
|
275
|
+
* written; and anything that is not a letter, a digit, a dash or an underscore
|
|
276
|
+
* becomes a dash, so nothing a name carries — a dot, a slash, a `..` — can
|
|
277
|
+
* reach out of `data/keys` or split the file name into more parts than it has.
|
|
278
|
+
*/
|
|
279
|
+
function fileToken(value) {
|
|
280
|
+
return value.toLowerCase().replace(/[^a-z0-9_-]+/g, '-');
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Make `data/keys` before anything is written into it, so it exists with the
|
|
284
|
+
* permissions a directory of private keys wants rather than the ones the
|
|
285
|
+
* atomic writer's `mkdir -p` would give it.
|
|
286
|
+
*/
|
|
287
|
+
function ensureKeysDir(dataDir) {
|
|
288
|
+
mkdirSync(actorKeysDir(dataDir), { recursive: true, mode: KEYS_DIR_MODE });
|
|
59
289
|
}
|
|
60
290
|
//# sourceMappingURL=keys.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keys.js","sourceRoot":"","sources":["../../src/federation/keys.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"keys.js","sourceRoot":"","sources":["../../src/federation/keys.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,23 +1,55 @@
|
|
|
1
|
-
import type { Hono } from 'hono';
|
|
1
|
+
import type { Context, Hono } from 'hono';
|
|
2
|
+
import type { User } from '../admin/accounts.ts';
|
|
2
3
|
import type { GeekityEnv } from '../env.ts';
|
|
3
4
|
import type { SiteFederation } from './federation.ts';
|
|
4
5
|
/**
|
|
5
6
|
* Put Fedify in front of the rest of the app.
|
|
6
7
|
*
|
|
7
8
|
* The middleware only answers the paths Fedify registered — the actor, its
|
|
8
|
-
* collections,
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* request.
|
|
9
|
+
* collections, WebFinger and NodeInfo; everything else falls through to
|
|
10
|
+
* `next()` and reaches the admin and the public site as before. That is why it
|
|
11
|
+
* is mounted first: the public site claims every unmatched path in its
|
|
12
|
+
* not-found handler, so anything registered after it never sees a request.
|
|
13
13
|
*
|
|
14
|
-
* A post
|
|
15
|
-
*
|
|
16
|
-
*
|
|
14
|
+
* A post's object is not one of Fedify's paths at all. decision-13 makes a
|
|
15
|
+
* post's ActivityStreams id its permalink, so {@link activityStreamsDocument}
|
|
16
|
+
* is what serves the `Article`: one URL, answering a browser with the page and
|
|
17
|
+
* a peer with the object. The same handler answers at the `activitypub.id` a
|
|
18
|
+
* migrated post's file names, and sends a browser from there to the permalink.
|
|
17
19
|
*
|
|
18
20
|
* The dispatchers are handed the stores off the Hono context rather than
|
|
19
21
|
* closing over them, so one federation object could serve more than one CMS
|
|
20
22
|
* and so a dispatcher is never reading a store the request did not come with.
|
|
21
23
|
*/
|
|
22
|
-
export declare function mountFederation(app: Hono<GeekityEnv>, federation: SiteFederation): void;
|
|
24
|
+
export declare function mountFederation(app: Hono<GeekityEnv>, federation: SiteFederation, options?: MountFederationOptions): void;
|
|
25
|
+
/** What {@link mountFederation} takes beyond the site's own federation. */
|
|
26
|
+
export interface MountFederationOptions {
|
|
27
|
+
/**
|
|
28
|
+
* The WordPress compatibility federation, built on demand (TASK-70).
|
|
29
|
+
*
|
|
30
|
+
* A factory rather than an object, because most sites will never turn the
|
|
31
|
+
* switch on and a second `Federation` they never use is a second set of
|
|
32
|
+
* dispatchers to build at boot. It is called the first time a request
|
|
33
|
+
* actually reaches one of the plugin's paths with the setting on, and the
|
|
34
|
+
* result is kept for the life of the site.
|
|
35
|
+
*/
|
|
36
|
+
wordpress?: (() => SiteFederation) | undefined;
|
|
37
|
+
}
|
|
38
|
+
/** Where WebFinger lives, which is defined on the host rather than under a site. */
|
|
39
|
+
export declare const WEBFINGER_PATH = "/.well-known/webfinger";
|
|
40
|
+
/** `acct:{username}@{host}`, the handle a person types into a search box. */
|
|
41
|
+
export declare function acctOf(username: string, baseUrl: string): string;
|
|
42
|
+
/**
|
|
43
|
+
* The user a WebFinger `resource` asks about, or `undefined` for one this site
|
|
44
|
+
* answers for nobody.
|
|
45
|
+
*
|
|
46
|
+
* Every spelling of a person resolves, and they are the ones decision-14 lists
|
|
47
|
+
* as their aliases: the `acct:` handle, the author archive, `/@{username}` and
|
|
48
|
+
* — for somebody who was published elsewhere first — the id they were
|
|
49
|
+
* published under. Matching every one of them is what lets a peer that holds
|
|
50
|
+
* any one URL for this person find the others, which is the whole job of
|
|
51
|
+
* WebFinger, and it is how a server holding only `?author=2` discovers that
|
|
52
|
+
* the account it follows is still here.
|
|
53
|
+
*/
|
|
54
|
+
export declare function webFingerSubject(c: Context<GeekityEnv>, resource: string): User | undefined;
|
|
23
55
|
//# sourceMappingURL=mount.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../../src/federation/mount.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../../src/federation/mount.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAqB,MAAM,MAAM,CAAC;AAG7D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAGjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAO5C,OAAO,KAAK,EAAyB,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAQ7E;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,IAAI,CAAC,UAAU,CAAC,EACrB,UAAU,EAAE,cAAc,EAC1B,OAAO,GAAE,sBAA2B,GACnC,IAAI,CAgGN;AAED,2EAA2E;AAC3E,MAAM,WAAW,sBAAsB;IACrC;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,CAAC,MAAM,cAAc,CAAC,GAAG,SAAS,CAAC;CAChD;AA8KD,oFAAoF;AACpF,eAAO,MAAM,cAAc,2BAA2B,CAAC;AAEvD,6EAA6E;AAC7E,wBAAgB,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAgB3F"}
|