@geekity/cms 0.3.0 → 0.5.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 +2217 -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/{layouts/document-editor.njk → pages/documents/editor.njk} +75 -59
- 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/federation/settings.njk +77 -0
- package/admin/pages/media/library.njk +160 -0
- package/admin/pages/messages/all.njk +110 -0
- package/admin/pages/navigation/menus.njk +129 -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/general.njk +29 -0
- package/admin/pages/settings/permalinks.njk +50 -0
- package/admin/pages/settings/reading.njk +64 -0
- package/admin/pages/tools/content-index.njk +89 -0
- package/admin/pages/users/edit.njk +239 -0
- package/admin/pages/users/list.njk +51 -0
- package/admin/pages/users/new.njk +41 -0
- package/admin/static/admin.css +558 -3
- package/admin/static/copy.js +52 -0
- package/admin/static/editor.js +16 -16
- package/admin/static/slug.js +61 -0
- package/dist/access-log.d.ts +44 -0
- package/dist/access-log.d.ts.map +1 -0
- package/dist/access-log.js +71 -0
- package/dist/access-log.js.map +1 -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 +117 -10
- package/dist/admin/documents.d.ts.map +1 -1
- package/dist/admin/documents.js +328 -41
- package/dist/admin/documents.js.map +1 -1
- package/dist/admin/federation.d.ts +161 -50
- package/dist/admin/federation.d.ts.map +1 -1
- package/dist/admin/federation.js +235 -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 +143 -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/navigation.d.ts +155 -0
- package/dist/admin/navigation.d.ts.map +1 -0
- package/dist/admin/navigation.js +292 -0
- package/dist/admin/navigation.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 +164 -105
- package/dist/admin/routes.js.map +1 -1
- package/dist/admin/session.d.ts +17 -3
- package/dist/admin/session.d.ts.map +1 -1
- package/dist/admin/session.js +19 -5
- package/dist/admin/session.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 +48 -0
- package/dist/admin/settings-federation.d.ts.map +1 -0
- package/dist/admin/settings-federation.js +123 -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 +119 -0
- package/dist/admin/settings-page.d.ts.map +1 -0
- package/dist/admin/settings-page.js +132 -0
- package/dist/admin/settings-page.js.map +1 -0
- package/dist/admin/settings-pages.d.ts +30 -0
- package/dist/admin/settings-pages.d.ts.map +1 -0
- package/dist/admin/settings-pages.js +43 -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 +34 -0
- package/dist/admin/settings-reading.d.ts.map +1 -0
- package/dist/admin/settings-reading.js +49 -0
- package/dist/admin/settings-reading.js.map +1 -0
- package/dist/admin/settings.d.ts +339 -96
- package/dist/admin/settings.d.ts.map +1 -1
- package/dist/admin/settings.js +600 -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 +46 -14
- package/dist/admin/templates.d.ts.map +1 -1
- package/dist/admin/templates.js +46 -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/tools.d.ts +111 -0
- package/dist/admin/tools.d.ts.map +1 -0
- package/dist/admin/tools.js +182 -0
- package/dist/admin/tools.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 +429 -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 +123 -0
- package/dist/comments/form.d.ts.map +1 -0
- package/dist/comments/form.js +79 -0
- package/dist/comments/form.js.map +1 -0
- package/dist/comments/index.d.ts +16 -0
- package/dist/comments/index.d.ts.map +1 -0
- package/dist/comments/index.js +10 -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 +60 -0
- package/dist/comments/routes.d.ts.map +1 -0
- package/dist/comments/routes.js +212 -0
- package/dist/comments/routes.js.map +1 -0
- package/dist/comments/submission.d.ts +297 -0
- package/dist/comments/submission.d.ts.map +1 -0
- package/dist/comments/submission.js +280 -0
- package/dist/comments/submission.js.map +1 -0
- package/dist/comments/viewer.d.ts +21 -0
- package/dist/comments/viewer.d.ts.map +1 -0
- package/dist/comments/viewer.js +45 -0
- package/dist/comments/viewer.js.map +1 -0
- package/dist/config.d.ts +225 -5
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +121 -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 +220 -7
- package/dist/content/store.d.ts.map +1 -1
- package/dist/content/store.js +392 -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 +70 -5
- 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 +46 -10
- package/dist/federation/mount.d.ts.map +1 -1
- package/dist/federation/mount.js +300 -28
- 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 +344 -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 +195 -0
- package/dist/web/navigation.d.ts.map +1 -0
- package/dist/web/navigation.js +300 -0
- package/dist/web/navigation.js.map +1 -0
- package/dist/web/negotiate.d.ts +31 -0
- package/dist/web/negotiate.d.ts.map +1 -1
- package/dist/web/negotiate.js +31 -11
- 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 +203 -9
- package/dist/web/render.d.ts.map +1 -1
- package/dist/web/render.js +341 -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 +854 -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 +226 -0
- package/dist/web/themes.d.ts.map +1 -0
- package/dist/web/themes.js +314 -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 +8 -0
- package/templates/site/content/pages/about.md +7 -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 +1216 -50
- package/themes/default/layouts/404.njk +2 -3
- package/themes/default/layouts/author.njk +36 -0
- package/themes/default/layouts/base.njk +161 -31
- package/themes/default/layouts/category.njk +27 -0
- package/themes/default/layouts/front-page.njk +56 -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 +71 -0
- package/themes/default/partials/comment-form.njk +137 -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/menu.njk +32 -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 +22 -0
- package/themes/default/partials/tags.njk +26 -5
- package/themes/default/static/highlight.js +4 -0
- package/themes/default/static/style.css +1142 -194
- package/themes/default/theme.json +9 -0
- 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/admin/preview.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { renderMarkdown } from '../content/markdown.js';
|
|
2
2
|
import { defaultPermalink, slugify } from '../content/slug.js';
|
|
3
|
+
import { calendarDayIn, toUtcInstant } from '../content/time.js';
|
|
3
4
|
import { normalizeBody } from '../content/writer.js';
|
|
5
|
+
import { authorContext } from '../web/authors.js';
|
|
4
6
|
import { documentContext } from '../web/context.js';
|
|
7
|
+
import { findUserById, listUsers } from './accounts.js';
|
|
5
8
|
import { TEMPLATES } from '../web/render.js';
|
|
6
9
|
import { splitTags } from './documents.js';
|
|
10
|
+
import { readSiteSettings } from './settings.js';
|
|
7
11
|
import { ADMIN_PREFIX } from './session.js';
|
|
8
12
|
/** Where the editor posts a body it wants to see rendered. */
|
|
9
13
|
export const PREVIEW_PATH = `${ADMIN_PREFIX}/preview`;
|
|
@@ -23,14 +27,24 @@ export function mountPreview(app) {
|
|
|
23
27
|
app.post(PREVIEW_PATH, async (c) => {
|
|
24
28
|
const body = await c.req.parseBody();
|
|
25
29
|
const type = text(body['type']) === 'page' ? 'page' : 'post';
|
|
26
|
-
|
|
30
|
+
const document = previewDocument(c, { type, body });
|
|
31
|
+
return c.html(c.var.renderer.render(type === 'post' ? TEMPLATES.post : TEMPLATES.page,
|
|
32
|
+
// With the site's image config, so a preview shows the `<picture>` the
|
|
33
|
+
// published page would show rather than the plain image behind it, and
|
|
34
|
+
// with the author resolved, so the byline reads the way the published
|
|
35
|
+
// page's would (TASK-67).
|
|
36
|
+
documentContext(document, c.var.config, authorContext(listUsers(c.var.config.dataDir), document.author))));
|
|
27
37
|
});
|
|
28
38
|
}
|
|
29
39
|
/** What a submitted editor form looks like as a document nobody has saved. */
|
|
30
40
|
function previewDocument(c, input) {
|
|
31
41
|
const { type, body } = input;
|
|
42
|
+
const timezone = readSiteSettings(c.var.config.contentDir).timezone;
|
|
32
43
|
const title = text(body['title']).trim();
|
|
33
|
-
|
|
44
|
+
// The editor's field is wall-clock time in the site's zone (decision-11), so
|
|
45
|
+
// the preview reads it the way the save will and shows the date the saved
|
|
46
|
+
// post would show rather than one the server's own zone invented.
|
|
47
|
+
const date = type === 'post' ? orNow(text(body['date']).trim(), timezone, c.var.store.now()) : undefined;
|
|
34
48
|
const slug = slugify(text(body['slug']).trim()) || slugify(title) || 'preview';
|
|
35
49
|
const markdown = normalizeBody(text(body['body']));
|
|
36
50
|
return {
|
|
@@ -39,10 +53,16 @@ function previewDocument(c, input) {
|
|
|
39
53
|
// prints them; neither is ever written anywhere.
|
|
40
54
|
path: `${type === 'post' ? 'posts' : 'pages'}/${slug}.md`,
|
|
41
55
|
slug,
|
|
42
|
-
permalink: permalinkFor({
|
|
56
|
+
permalink: permalinkFor({
|
|
57
|
+
type,
|
|
58
|
+
slug,
|
|
59
|
+
date: date === undefined ? undefined : (calendarDayIn(date, timezone) ?? date),
|
|
60
|
+
submitted: text(body['permalink']).trim(),
|
|
61
|
+
}),
|
|
43
62
|
title: title === '' ? 'Untitled' : title,
|
|
44
63
|
...(date === undefined ? {} : { date }),
|
|
45
64
|
tags: splitTags(text(body['tags'])),
|
|
65
|
+
categories: splitTags(text(body['categories'])),
|
|
46
66
|
draft: body['draft'] !== undefined,
|
|
47
67
|
...(text(body['description']) === '' ? {} : { description: text(body['description']).trim() }),
|
|
48
68
|
...(currentUsername(c) === undefined ? {} : { author: currentUsername(c) }),
|
|
@@ -65,16 +85,20 @@ function permalinkFor(input) {
|
|
|
65
85
|
return '/';
|
|
66
86
|
}
|
|
67
87
|
}
|
|
68
|
-
/**
|
|
69
|
-
|
|
70
|
-
|
|
88
|
+
/**
|
|
89
|
+
* The date field as a UTC instant. One that is empty or unusable becomes now,
|
|
90
|
+
* so the layout always has one to print.
|
|
91
|
+
*/
|
|
92
|
+
function orNow(value, timezone, now) {
|
|
93
|
+
const instant = /^\d{4}-\d{2}-\d{2}/.test(value) ? toUtcInstant(value, timezone) : undefined;
|
|
94
|
+
return instant ?? now.toISOString();
|
|
71
95
|
}
|
|
72
96
|
/** The signed-in user's login, so a byline in the theme has something to print. */
|
|
73
97
|
function currentUsername(c) {
|
|
74
98
|
const userId = c.var.session?.userId;
|
|
75
99
|
if (userId == null)
|
|
76
100
|
return undefined;
|
|
77
|
-
return c.var.
|
|
101
|
+
return findUserById(c.var.config.dataDir, userId)?.username;
|
|
78
102
|
}
|
|
79
103
|
/** A form field as a string. A file upload, or a missing field, is the empty one. */
|
|
80
104
|
function text(value) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preview.js","sourceRoot":"","sources":["../../src/admin/preview.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,8DAA8D;AAC9D,MAAM,CAAC,MAAM,YAAY,GAAG,GAAG,YAAY,UAAU,CAAC;AAEtD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY,CAAC,GAAqB;IAChD,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACjC,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;QACrC,MAAM,IAAI,GAAiB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"preview.js","sourceRoot":"","sources":["../../src/admin/preview.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { Context, Hono } from 'hono';
|
|
2
|
+
import type { ResolvedConfig } from '../config.ts';
|
|
3
|
+
import type { GeekityEnv } from '../env.ts';
|
|
4
|
+
import type { AdminRender } from './documents.ts';
|
|
5
|
+
import type { Session } from './store.ts';
|
|
6
|
+
import type { LoginThrottle } from './throttle.ts';
|
|
7
|
+
/**
|
|
8
|
+
* Forgetting a password, and getting back in without a shell.
|
|
9
|
+
*
|
|
10
|
+
* Two unauthenticated screens, built to the OWASP Forgot Password guidance,
|
|
11
|
+
* and four rules that between them are the whole design:
|
|
12
|
+
*
|
|
13
|
+
* - **One answer.** The request form says exactly the same thing to a name
|
|
14
|
+
* that exists, a name that does not, and a name whose user has no email
|
|
15
|
+
* address. A recovery form that answered differently would be a list of
|
|
16
|
+
* which accounts a site has, handed to anybody who asked.
|
|
17
|
+
* - **The link is the secret.** 256 random bits, in the URL, sent to an
|
|
18
|
+
* address somebody put on their own account. The database keeps only its
|
|
19
|
+
* SHA-256 (see the `password_resets` migration), so a copy of the cache is
|
|
20
|
+
* not a stack of working links, and the token is never rendered into the
|
|
21
|
+
* page of the browser that asked for it — only into the message.
|
|
22
|
+
* - **It is spent when it is used.** Setting a password deletes every reset
|
|
23
|
+
* that user had outstanding and ends every session they had, because the
|
|
24
|
+
* ordinary reason to reset a password is that somebody else may have had it.
|
|
25
|
+
* - **It cannot be a lever.** Requests are rate limited exactly as sign-ins
|
|
26
|
+
* are (TASK-47), on a throttle of their own, so a flood of recovery requests
|
|
27
|
+
* for one username cannot lock that person out of logging in.
|
|
28
|
+
*/
|
|
29
|
+
/** Where the request-a-link form lives. */
|
|
30
|
+
export declare const FORGOT_PATH = "/admin/forgot";
|
|
31
|
+
/** Where the set-a-new-password form lives. The link points here. */
|
|
32
|
+
export declare const RESET_PATH = "/admin/reset";
|
|
33
|
+
/** The fields the two forms submit. */
|
|
34
|
+
export declare const RECOVERY_FIELDS: {
|
|
35
|
+
/** A username or an email address; the form does not ask which. */
|
|
36
|
+
readonly identifier: 'identifier';
|
|
37
|
+
/** The token, carried from the link's query string into the form. */
|
|
38
|
+
readonly token: 'token';
|
|
39
|
+
readonly password: 'password';
|
|
40
|
+
readonly passwordConfirmation: 'password_confirmation';
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* How long a link lasts, in seconds.
|
|
44
|
+
*
|
|
45
|
+
* An hour, which is what the task asks for and what OWASP calls a reasonable
|
|
46
|
+
* upper bound: long enough to walk to another machine and read the mail there,
|
|
47
|
+
* short enough that a link left in an inbox is not a spare key.
|
|
48
|
+
*/
|
|
49
|
+
export declare const RESET_TOKEN_LIFETIME_SECONDS = 3600;
|
|
50
|
+
/** The message asking somebody whether they meant to do this. */
|
|
51
|
+
export declare const RESET_TEMPLATE = "password-reset";
|
|
52
|
+
/** The message telling them it happened. */
|
|
53
|
+
export declare const PASSWORD_CHANGED_TEMPLATE = "password-changed";
|
|
54
|
+
/**
|
|
55
|
+
* The one thing the request form ever says.
|
|
56
|
+
*
|
|
57
|
+
* Spelled once, and rendered whatever happened, so the two paths through the
|
|
58
|
+
* handler cannot drift into two different answers.
|
|
59
|
+
*/
|
|
60
|
+
export declare const RECOVERY_ANSWER: string;
|
|
61
|
+
/** What {@link mountRecovery} needs from the admin around it. */
|
|
62
|
+
export interface MountRecoveryOptions {
|
|
63
|
+
/** The admin's renderer, which injects the chrome, the CSRF token and the flash. */
|
|
64
|
+
render: AdminRender;
|
|
65
|
+
/**
|
|
66
|
+
* A session to hang a CSRF token on, made on the spot if the visitor has
|
|
67
|
+
* none. The same one the login and setup forms use: these pages are reached
|
|
68
|
+
* by somebody with no login, and a form with no session has no token.
|
|
69
|
+
*/
|
|
70
|
+
anonymousSession: (c: Context<GeekityEnv>) => Session;
|
|
71
|
+
/**
|
|
72
|
+
* The throttle recovery requests are counted against.
|
|
73
|
+
*
|
|
74
|
+
* Its own, not the login one. Sharing would mean a stranger could lock
|
|
75
|
+
* somebody out of signing in by asking for their password to be reset over
|
|
76
|
+
* and over — turning a recovery feature into a denial of service against the
|
|
77
|
+
* person it exists to help.
|
|
78
|
+
*/
|
|
79
|
+
throttle: (config: ResolvedConfig) => LoginThrottle;
|
|
80
|
+
}
|
|
81
|
+
/** Register the forgot-password and reset screens. */
|
|
82
|
+
export declare function mountRecovery(app: Hono<GeekityEnv>, options: MountRecoveryOptions): void;
|
|
83
|
+
/**
|
|
84
|
+
* What is wrong with the password somebody typed into the reset form.
|
|
85
|
+
*
|
|
86
|
+
* The same rules the change-password form and `geekity user add` enforce, so a
|
|
87
|
+
* password set through a reset link is one every other door would have taken.
|
|
88
|
+
*/
|
|
89
|
+
export declare function newPasswordProblem(password: string, confirmation: string): string | undefined;
|
|
90
|
+
/** The link that goes in the message, absolute because it is read elsewhere. */
|
|
91
|
+
export declare function resetLink(baseUrl: string, token: string): string;
|
|
92
|
+
//# sourceMappingURL=recovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery.d.ts","sourceRoot":"","sources":["../../src/admin/recovery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAG5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGlD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAG1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,2CAA2C;AAC3C,eAAO,MAAM,WAAW,kBAA2B,CAAC;AAEpD,qEAAqE;AACrE,eAAO,MAAM,UAAU,iBAA0B,CAAC;AAElD,uCAAuC;AACvC,eAAO,MAAM,eAAe;IAC1B,mEAAmE;aACnE,UAAU,EAAE,YAAY;IACxB,qEAAqE;aACrE,KAAK,EAAE,OAAO;aACd,QAAQ,EAAE,UAAU;aACpB,oBAAoB,EAAE,uBAAuB;CACrC,CAAC;AAEX;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,OAAO,CAAC;AAEjD,iEAAiE;AACjE,eAAO,MAAM,cAAc,mBAAmB,CAAC;AAE/C,4CAA4C;AAC5C,eAAO,MAAM,yBAAyB,qBAAqB,CAAC;AAE5D;;;;;GAKG;AACH,eAAO,MAAM,eAAe,QAEoE,CAAC;AAEjG,iEAAiE;AACjE,MAAM,WAAW,oBAAoB;IACnC,oFAAoF;IACpF,MAAM,EAAE,WAAW,CAAC;IACpB;;;;OAIG;IACH,gBAAgB,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,OAAO,CAAC;IACtD;;;;;;;OAOG;IACH,QAAQ,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,aAAa,CAAC;CACrD;AAED,sDAAsD;AACtD,wBAAgB,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,oBAAoB,GAAG,IAAI,CA6JxF;AAiBD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAK7F;AAED,gFAAgF;AAChF,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAIhE"}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { findUserById, findUserByIdentifier, setUserPassword } from './accounts.js';
|
|
2
|
+
import { passwordProblem } from './credentials.js';
|
|
3
|
+
import { flash } from './flash.js';
|
|
4
|
+
import { ADMIN_PREFIX } from './session.js';
|
|
5
|
+
import { ADMIN_TEMPLATES } from './templates.js';
|
|
6
|
+
import { clientAddress, describeWait, loginKeys } from './throttle.js';
|
|
7
|
+
/**
|
|
8
|
+
* Forgetting a password, and getting back in without a shell.
|
|
9
|
+
*
|
|
10
|
+
* Two unauthenticated screens, built to the OWASP Forgot Password guidance,
|
|
11
|
+
* and four rules that between them are the whole design:
|
|
12
|
+
*
|
|
13
|
+
* - **One answer.** The request form says exactly the same thing to a name
|
|
14
|
+
* that exists, a name that does not, and a name whose user has no email
|
|
15
|
+
* address. A recovery form that answered differently would be a list of
|
|
16
|
+
* which accounts a site has, handed to anybody who asked.
|
|
17
|
+
* - **The link is the secret.** 256 random bits, in the URL, sent to an
|
|
18
|
+
* address somebody put on their own account. The database keeps only its
|
|
19
|
+
* SHA-256 (see the `password_resets` migration), so a copy of the cache is
|
|
20
|
+
* not a stack of working links, and the token is never rendered into the
|
|
21
|
+
* page of the browser that asked for it — only into the message.
|
|
22
|
+
* - **It is spent when it is used.** Setting a password deletes every reset
|
|
23
|
+
* that user had outstanding and ends every session they had, because the
|
|
24
|
+
* ordinary reason to reset a password is that somebody else may have had it.
|
|
25
|
+
* - **It cannot be a lever.** Requests are rate limited exactly as sign-ins
|
|
26
|
+
* are (TASK-47), on a throttle of their own, so a flood of recovery requests
|
|
27
|
+
* for one username cannot lock that person out of logging in.
|
|
28
|
+
*/
|
|
29
|
+
/** Where the request-a-link form lives. */
|
|
30
|
+
export const FORGOT_PATH = `${ADMIN_PREFIX}/forgot`;
|
|
31
|
+
/** Where the set-a-new-password form lives. The link points here. */
|
|
32
|
+
export const RESET_PATH = `${ADMIN_PREFIX}/reset`;
|
|
33
|
+
/** The fields the two forms submit. */
|
|
34
|
+
export const RECOVERY_FIELDS = {
|
|
35
|
+
/** A username or an email address; the form does not ask which. */
|
|
36
|
+
identifier: 'identifier',
|
|
37
|
+
/** The token, carried from the link's query string into the form. */
|
|
38
|
+
token: 'token',
|
|
39
|
+
password: 'password',
|
|
40
|
+
passwordConfirmation: 'password_confirmation',
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* How long a link lasts, in seconds.
|
|
44
|
+
*
|
|
45
|
+
* An hour, which is what the task asks for and what OWASP calls a reasonable
|
|
46
|
+
* upper bound: long enough to walk to another machine and read the mail there,
|
|
47
|
+
* short enough that a link left in an inbox is not a spare key.
|
|
48
|
+
*/
|
|
49
|
+
export const RESET_TOKEN_LIFETIME_SECONDS = 3600;
|
|
50
|
+
/** The message asking somebody whether they meant to do this. */
|
|
51
|
+
export const RESET_TEMPLATE = 'password-reset';
|
|
52
|
+
/** The message telling them it happened. */
|
|
53
|
+
export const PASSWORD_CHANGED_TEMPLATE = 'password-changed';
|
|
54
|
+
/**
|
|
55
|
+
* The one thing the request form ever says.
|
|
56
|
+
*
|
|
57
|
+
* Spelled once, and rendered whatever happened, so the two paths through the
|
|
58
|
+
* handler cannot drift into two different answers.
|
|
59
|
+
*/
|
|
60
|
+
export const RECOVERY_ANSWER = 'If that matches an account with an email address on it, a link to set a new password is on ' +
|
|
61
|
+
'its way. The link lasts an hour and works once. Check the spam folder if it does not arrive.';
|
|
62
|
+
/** Register the forgot-password and reset screens. */
|
|
63
|
+
export function mountRecovery(app, options) {
|
|
64
|
+
const { render, anonymousSession, throttle } = options;
|
|
65
|
+
app.get(FORGOT_PATH, (c) => {
|
|
66
|
+
anonymousSession(c);
|
|
67
|
+
return render(c, ADMIN_TEMPLATES.forgot, forgotScreen(c));
|
|
68
|
+
});
|
|
69
|
+
app.post(FORGOT_PATH, async (c) => {
|
|
70
|
+
const config = c.var.config;
|
|
71
|
+
const body = await c.req.parseBody();
|
|
72
|
+
const identifier = field(body[RECOVERY_FIELDS.identifier]).trim();
|
|
73
|
+
const address = clientAddress(c, config);
|
|
74
|
+
const keys = loginKeys(identifier, address);
|
|
75
|
+
const throttled = throttle(config);
|
|
76
|
+
const wait = throttled.retryAfter(keys);
|
|
77
|
+
if (wait !== undefined) {
|
|
78
|
+
anonymousSession(c);
|
|
79
|
+
c.status(429);
|
|
80
|
+
c.header('Retry-After', String(wait));
|
|
81
|
+
return render(c, ADMIN_TEMPLATES.forgot,
|
|
82
|
+
// Says nothing about whether that account exists: an unknown name is
|
|
83
|
+
// counted and locked out exactly as a real one is.
|
|
84
|
+
forgotScreen(c, { error: `Too many requests. Try again in ${describeWait(wait)}.` }));
|
|
85
|
+
}
|
|
86
|
+
// Every request is counted, not only the ones that matched: counting a
|
|
87
|
+
// match differently would make the lockout itself the answer the rest of
|
|
88
|
+
// this handler refuses to give.
|
|
89
|
+
throttled.fail(keys);
|
|
90
|
+
const user = identifier === '' ? undefined : findUserByIdentifier(config.dataDir, identifier);
|
|
91
|
+
if (user?.email !== undefined && c.var.mail.configured()) {
|
|
92
|
+
// A good moment to sweep: resets are rare, and this is the one handler
|
|
93
|
+
// that writes a row to the table.
|
|
94
|
+
c.var.admin.prunePasswordResets();
|
|
95
|
+
const reset = c.var.admin.createPasswordReset({
|
|
96
|
+
userId: user.id,
|
|
97
|
+
lifetimeSeconds: RESET_TOKEN_LIFETIME_SECONDS,
|
|
98
|
+
});
|
|
99
|
+
// Dropped rather than awaited, for two reasons: the answer is the same
|
|
100
|
+
// whatever the provider says, and waiting for a provider on one path and
|
|
101
|
+
// not the other is how the page's timing would start telling people
|
|
102
|
+
// which usernames exist.
|
|
103
|
+
void c.var.mail.send({
|
|
104
|
+
to: user.email,
|
|
105
|
+
template: RESET_TEMPLATE,
|
|
106
|
+
data: {
|
|
107
|
+
username: user.username,
|
|
108
|
+
resetUrl: resetLink(config.baseUrl, reset.token),
|
|
109
|
+
expiresAt: reset.expiresAt,
|
|
110
|
+
expiresInHours: RESET_TOKEN_LIFETIME_SECONDS / 3600,
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
anonymousSession(c);
|
|
115
|
+
return render(c, ADMIN_TEMPLATES.forgot, forgotScreen(c, { sent: true }));
|
|
116
|
+
});
|
|
117
|
+
app.get(RESET_PATH, (c) => {
|
|
118
|
+
anonymousSession(c);
|
|
119
|
+
const token = c.req.query(RECOVERY_FIELDS.token) ?? '';
|
|
120
|
+
const reset = token === '' ? undefined : c.var.admin.getPasswordReset(token);
|
|
121
|
+
if (reset === undefined)
|
|
122
|
+
return refuseToken(c);
|
|
123
|
+
return render(c, ADMIN_TEMPLATES.reset, resetScreen(token));
|
|
124
|
+
});
|
|
125
|
+
app.post(RESET_PATH, async (c) => {
|
|
126
|
+
const dataDir = c.var.config.dataDir;
|
|
127
|
+
const body = await c.req.parseBody();
|
|
128
|
+
const token = field(body[RECOVERY_FIELDS.token]);
|
|
129
|
+
const password = field(body[RECOVERY_FIELDS.password]);
|
|
130
|
+
const confirmation = field(body[RECOVERY_FIELDS.passwordConfirmation]);
|
|
131
|
+
// Checked before the password rules, so a stale link is a stale link
|
|
132
|
+
// whatever was typed into it — and so a refused form never spends one.
|
|
133
|
+
const reset = token === '' ? undefined : c.var.admin.getPasswordReset(token);
|
|
134
|
+
if (reset === undefined)
|
|
135
|
+
return refuseToken(c);
|
|
136
|
+
const problem = newPasswordProblem(password, confirmation);
|
|
137
|
+
if (problem !== undefined) {
|
|
138
|
+
c.status(400);
|
|
139
|
+
// Nothing typed is echoed back: both fields are passwords.
|
|
140
|
+
return render(c, ADMIN_TEMPLATES.reset, resetScreen(token, { problem }));
|
|
141
|
+
}
|
|
142
|
+
const user = findUserById(dataDir, reset.userId);
|
|
143
|
+
if (user === undefined) {
|
|
144
|
+
// The account went while the link was in flight. The token is worthless
|
|
145
|
+
// now, and saying so beats a 500 from a write against nobody.
|
|
146
|
+
c.var.admin.deletePasswordResetsForUser(reset.userId);
|
|
147
|
+
return refuseToken(c);
|
|
148
|
+
}
|
|
149
|
+
await setUserPassword({ dataDir, userId: user.id, password });
|
|
150
|
+
// Everything that was a way into this account is now closed: the link that
|
|
151
|
+
// was just used, every other link asked for while it was in flight, and
|
|
152
|
+
// every browser that was signed in. Nobody is spared, because the person
|
|
153
|
+
// doing this is not signed in — they are about to be.
|
|
154
|
+
c.var.admin.deletePasswordResetsForUser(user.id);
|
|
155
|
+
const ended = c.var.admin.deleteSessionsForUser(user.id);
|
|
156
|
+
if (user.email !== undefined) {
|
|
157
|
+
// The other half of the OWASP guidance: whoever owns the address hears
|
|
158
|
+
// that the password changed, so a reset they did not ask for is
|
|
159
|
+
// something they find out about rather than something they discover.
|
|
160
|
+
void c.var.mail.send({
|
|
161
|
+
to: user.email,
|
|
162
|
+
template: PASSWORD_CHANGED_TEMPLATE,
|
|
163
|
+
data: { username: user.username, signedOut: ended },
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
flash(c, 'notice', 'Your password was changed. Sign in with the new one.');
|
|
167
|
+
return c.redirect(LOGIN_REDIRECT, 303);
|
|
168
|
+
});
|
|
169
|
+
/** What both handlers say to a token that buys nothing. */
|
|
170
|
+
function refuseToken(c) {
|
|
171
|
+
anonymousSession(c);
|
|
172
|
+
c.status(400);
|
|
173
|
+
return render(c, ADMIN_TEMPLATES.reset, {
|
|
174
|
+
forgotUrl: FORGOT_PATH,
|
|
175
|
+
resetUrl: RESET_PATH,
|
|
176
|
+
fields: RECOVERY_FIELDS,
|
|
177
|
+
invalid: true,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
/** Everything the forgot-password template renders. */
|
|
181
|
+
function forgotScreen(c, extra = {}) {
|
|
182
|
+
return {
|
|
183
|
+
forgotUrl: FORGOT_PATH,
|
|
184
|
+
loginUrl: LOGIN_REDIRECT,
|
|
185
|
+
fields: RECOVERY_FIELDS,
|
|
186
|
+
// Read per request, exactly as the mail service reads it: a credential
|
|
187
|
+
// pasted into the settings screen turns recovery on for the next visitor
|
|
188
|
+
// without a restart.
|
|
189
|
+
configured: c.var.mail.configured(),
|
|
190
|
+
answer: RECOVERY_ANSWER,
|
|
191
|
+
sent: false,
|
|
192
|
+
...extra,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
/** Where a finished reset sends the browser. Spelled here to avoid a cycle. */
|
|
197
|
+
const LOGIN_REDIRECT = `${ADMIN_PREFIX}/login`;
|
|
198
|
+
/** Everything the reset template renders for a link that is still good. */
|
|
199
|
+
function resetScreen(token, extra = {}) {
|
|
200
|
+
return {
|
|
201
|
+
forgotUrl: FORGOT_PATH,
|
|
202
|
+
resetUrl: RESET_PATH,
|
|
203
|
+
fields: RECOVERY_FIELDS,
|
|
204
|
+
token,
|
|
205
|
+
invalid: false,
|
|
206
|
+
...extra,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* What is wrong with the password somebody typed into the reset form.
|
|
211
|
+
*
|
|
212
|
+
* The same rules the change-password form and `geekity user add` enforce, so a
|
|
213
|
+
* password set through a reset link is one every other door would have taken.
|
|
214
|
+
*/
|
|
215
|
+
export function newPasswordProblem(password, confirmation) {
|
|
216
|
+
return (passwordProblem(password) ??
|
|
217
|
+
(password === confirmation ? undefined : 'The two passwords do not match.'));
|
|
218
|
+
}
|
|
219
|
+
/** The link that goes in the message, absolute because it is read elsewhere. */
|
|
220
|
+
export function resetLink(baseUrl, token) {
|
|
221
|
+
const url = new URL(RESET_PATH, baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`);
|
|
222
|
+
url.searchParams.set(RECOVERY_FIELDS.token, token);
|
|
223
|
+
return url.href;
|
|
224
|
+
}
|
|
225
|
+
/** A form field as a string. A file upload, or a missing field, is the empty one. */
|
|
226
|
+
function field(value) {
|
|
227
|
+
return typeof value === 'string' ? value : '';
|
|
228
|
+
}
|
|
229
|
+
//# sourceMappingURL=recovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery.js","sourceRoot":"","sources":["../../src/admin/recovery.ts"],"names":[],"mappings":"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"}
|
package/dist/admin/routes.d.ts
CHANGED
|
@@ -6,26 +6,6 @@ export declare const LOGIN_PATH = "/admin/login";
|
|
|
6
6
|
export declare const SETUP_PATH = "/admin/setup";
|
|
7
7
|
/** Where the logout form posts. */
|
|
8
8
|
export declare const LOGOUT_PATH = "/admin/logout";
|
|
9
|
-
/** Where the dashboard's quick draft form posts. */
|
|
10
|
-
export declare const QUICK_DRAFT_PATH = "/admin/quick-draft";
|
|
11
|
-
/** One entry in the admin's left-hand navigation. */
|
|
12
|
-
export interface AdminSection {
|
|
13
|
-
/** The name a screen passes as `section` to mark itself current. */
|
|
14
|
-
section: string;
|
|
15
|
-
/** What the link says. */
|
|
16
|
-
label: string;
|
|
17
|
-
/** Where it goes. */
|
|
18
|
-
url: string;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* The sections of the admin, in the order doc-5 lists them.
|
|
22
|
-
*
|
|
23
|
-
* Every screen renders the same list and marks one of them, so a screen added
|
|
24
|
-
* later only has to name its section. The screens behind most of these links
|
|
25
|
-
* are still placeholders; the navigation is the shape of the whole admin, not
|
|
26
|
-
* of the part that is built.
|
|
27
|
-
*/
|
|
28
|
-
export declare const ADMIN_SECTIONS: readonly AdminSection[];
|
|
29
9
|
/** How many recent posts the dashboard lists. */
|
|
30
10
|
export declare const DASHBOARD_RECENT_POSTS = 5;
|
|
31
11
|
/** Where the editor for a post lives. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/admin/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,IAAI,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/admin/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,IAAI,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAI7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAyC5C,kCAAkC;AAClC,eAAO,MAAM,UAAU,iBAA0B,CAAC;AAClD,sCAAsC;AACtC,eAAO,MAAM,UAAU,iBAA0B,CAAC;AAClD,mCAAmC;AACnC,eAAO,MAAM,WAAW,kBAA2B,CAAC;AAEpD,iDAAiD;AACjD,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC,yCAAyC;AACzC,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,UAAU,CAAC,GAAG,IAAI,CA6UtD;AAKD;;;;;GAKG;AACH,eAAO,MAAM,KAAK,EAAE,iBAAiB,CAAC,UAAU,CAwC/C,CAAC"}
|