@geekity/cms 0.4.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 +234 -108
- package/admin/pages/documents/editor.njk +0 -13
- package/admin/pages/{settings/federation.njk → federation/settings.njk} +7 -5
- package/admin/pages/navigation/menus.njk +129 -0
- package/admin/pages/settings/reading.njk +2 -10
- package/admin/pages/tools/content-index.njk +89 -0
- package/admin/pages/users/list.njk +5 -2
- package/admin/static/admin.css +60 -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/documents.d.ts +3 -13
- package/dist/admin/documents.d.ts.map +1 -1
- package/dist/admin/documents.js +2 -34
- package/dist/admin/documents.js.map +1 -1
- package/dist/admin/federation.d.ts +10 -0
- package/dist/admin/federation.d.ts.map +1 -1
- package/dist/admin/federation.js +10 -0
- package/dist/admin/federation.js.map +1 -1
- package/dist/admin/index.d.ts +3 -3
- package/dist/admin/index.d.ts.map +1 -1
- package/dist/admin/index.js +2 -2
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/menu.d.ts.map +1 -1
- package/dist/admin/menu.js +19 -2
- package/dist/admin/menu.js.map +1 -1
- 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/routes.d.ts.map +1 -1
- package/dist/admin/routes.js +9 -0
- 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-federation.d.ts +10 -1
- package/dist/admin/settings-federation.d.ts.map +1 -1
- package/dist/admin/settings-federation.js +26 -6
- package/dist/admin/settings-federation.js.map +1 -1
- package/dist/admin/settings-page.d.ts +26 -9
- package/dist/admin/settings-page.d.ts.map +1 -1
- package/dist/admin/settings-page.js +18 -12
- package/dist/admin/settings-page.js.map +1 -1
- package/dist/admin/settings-pages.d.ts +14 -3
- package/dist/admin/settings-pages.d.ts.map +1 -1
- package/dist/admin/settings-pages.js +15 -5
- package/dist/admin/settings-pages.js.map +1 -1
- package/dist/admin/settings-reading.d.ts +5 -4
- package/dist/admin/settings-reading.d.ts.map +1 -1
- package/dist/admin/settings-reading.js +6 -5
- package/dist/admin/settings-reading.js.map +1 -1
- package/dist/admin/settings.d.ts +29 -15
- package/dist/admin/settings.d.ts.map +1 -1
- package/dist/admin/settings.js +28 -78
- package/dist/admin/settings.js.map +1 -1
- package/dist/admin/templates.d.ts +3 -1
- package/dist/admin/templates.d.ts.map +1 -1
- package/dist/admin/templates.js +3 -1
- package/dist/admin/templates.js.map +1 -1
- 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/cli.d.ts.map +1 -1
- package/dist/cli.js +6 -1
- package/dist/cli.js.map +1 -1
- package/dist/comments/form.d.ts +48 -0
- package/dist/comments/form.d.ts.map +1 -1
- package/dist/comments/form.js +15 -0
- package/dist/comments/form.js.map +1 -1
- package/dist/comments/index.d.ts +4 -3
- package/dist/comments/index.d.ts.map +1 -1
- package/dist/comments/index.js +2 -1
- package/dist/comments/index.js.map +1 -1
- package/dist/comments/routes.d.ts +3 -1
- package/dist/comments/routes.d.ts.map +1 -1
- package/dist/comments/routes.js +46 -11
- package/dist/comments/routes.js.map +1 -1
- package/dist/comments/submission.d.ts +37 -3
- package/dist/comments/submission.d.ts.map +1 -1
- package/dist/comments/submission.js +59 -20
- package/dist/comments/submission.js.map +1 -1
- 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 +35 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +3 -0
- package/dist/config.js.map +1 -1
- package/dist/content/store.d.ts +18 -0
- package/dist/content/store.d.ts.map +1 -1
- package/dist/content/store.js +18 -0
- package/dist/content/store.js.map +1 -1
- package/dist/env.d.ts +12 -1
- package/dist/env.d.ts.map +1 -1
- package/dist/federation/mount.d.ts +4 -0
- package/dist/federation/mount.d.ts.map +1 -1
- package/dist/federation/mount.js +44 -12
- package/dist/federation/mount.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -4
- package/dist/index.js.map +1 -1
- package/dist/web/index.d.ts +3 -3
- package/dist/web/index.d.ts.map +1 -1
- package/dist/web/index.js +1 -1
- package/dist/web/index.js.map +1 -1
- package/dist/web/navigation.d.ts +158 -36
- package/dist/web/navigation.d.ts.map +1 -1
- package/dist/web/navigation.js +250 -60
- package/dist/web/navigation.js.map +1 -1
- package/dist/web/negotiate.d.ts +22 -0
- package/dist/web/negotiate.d.ts.map +1 -1
- package/dist/web/negotiate.js +25 -10
- package/dist/web/negotiate.js.map +1 -1
- package/dist/web/render.d.ts +16 -10
- package/dist/web/render.d.ts.map +1 -1
- package/dist/web/render.js +21 -14
- package/dist/web/render.js.map +1 -1
- package/dist/web/routes.d.ts.map +1 -1
- package/dist/web/routes.js +11 -2
- package/dist/web/routes.js.map +1 -1
- package/dist/web/themes.d.ts +21 -0
- package/dist/web/themes.d.ts.map +1 -1
- package/dist/web/themes.js +37 -0
- package/dist/web/themes.js.map +1 -1
- package/package.json +1 -1
- package/templates/site/content/_data/site.json +7 -0
- package/templates/site/content/pages/about.md +7 -0
- package/themes/default/README.md +200 -80
- package/themes/default/layouts/author.njk +3 -4
- package/themes/default/layouts/base.njk +38 -49
- package/themes/default/layouts/front-page.njk +1 -2
- package/themes/default/partials/bio.njk +15 -21
- package/themes/default/partials/comment-form.njk +31 -3
- package/themes/default/partials/menu.njk +32 -0
- package/themes/default/partials/search-form.njk +5 -0
- package/themes/default/static/style.css +31 -8
- package/themes/default/theme.json +5 -1
package/dist/comments/form.d.ts
CHANGED
|
@@ -38,7 +38,55 @@ export interface CommentFormContext {
|
|
|
38
38
|
nameLength: number;
|
|
39
39
|
/** The longest a comment may be, for the textarea's `maxlength`. */
|
|
40
40
|
bodyLength: number;
|
|
41
|
+
/**
|
|
42
|
+
* Who the site knows is filling this in, when a session says so (TASK-103).
|
|
43
|
+
*
|
|
44
|
+
* Absent for a stranger, so a theme asks `{% if commentForm.signedInAs %}`
|
|
45
|
+
* and draws the short form — the comment box and a sentence naming the
|
|
46
|
+
* person — instead of the name, email and website boxes and the honeypot.
|
|
47
|
+
* Nothing about the account is here but the two things the sentence prints:
|
|
48
|
+
* the email is never handed to a template, exactly as a stranger's never is.
|
|
49
|
+
*/
|
|
50
|
+
signedInAs?: {
|
|
51
|
+
name: string;
|
|
52
|
+
url: string;
|
|
53
|
+
} | undefined;
|
|
54
|
+
/**
|
|
55
|
+
* The token the signed-in form carries, and absent on a stranger's.
|
|
56
|
+
*
|
|
57
|
+
* A form that acts on nobody's behalf needs none; the moment this one posts
|
|
58
|
+
* under somebody's name, a page on another site could make them post without
|
|
59
|
+
* knowing it, so it carries the same per-session token every admin form
|
|
60
|
+
* does and the endpoint checks it the way the admin guard does.
|
|
61
|
+
*/
|
|
62
|
+
csrfToken?: string | undefined;
|
|
41
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Who the site knows is commenting, when a valid session says so.
|
|
66
|
+
*
|
|
67
|
+
* Read from the session on the request rather than from anything the browser
|
|
68
|
+
* typed: `email` is the account's, which the comment is stored with and which
|
|
69
|
+
* no template is ever handed, and `csrfToken` is that session's own.
|
|
70
|
+
*/
|
|
71
|
+
export interface CommentViewer {
|
|
72
|
+
/** What the comment goes under: their display name, else their username. */
|
|
73
|
+
name: string;
|
|
74
|
+
/** Their author archive, which is the comment's website. */
|
|
75
|
+
url: string;
|
|
76
|
+
/** The account's email, which is stored and never shown. */
|
|
77
|
+
email: string | null;
|
|
78
|
+
/** This session's CSRF token, which the form carries. */
|
|
79
|
+
csrfToken: string;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The same form drawn for somebody the site knows rather than for a stranger.
|
|
83
|
+
*
|
|
84
|
+
* A function over a built form rather than another parameter on the two
|
|
85
|
+
* builders, so `commentForm` and `refilledCommentForm` keep the signatures the
|
|
86
|
+
* package publishes and there is one place that decides what "signed in"
|
|
87
|
+
* changes about a form.
|
|
88
|
+
*/
|
|
89
|
+
export declare function signedInCommentForm(form: CommentFormContext, viewer: CommentViewer): CommentFormContext;
|
|
42
90
|
/** Where the comment form posts. */
|
|
43
91
|
export declare const COMMENT_POST_PATH = "/_geekity/comments";
|
|
44
92
|
/** The query the redirect after a submission carries, and what it can say. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../../src/comments/form.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,cAAc,EAA4C,MAAM,iBAAiB,CAAC;AAC3F,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEpE;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB;IACjC,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,MAAM,EAAE,OAAO,cAAc,CAAC;IAC9B,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,qFAAqF;IACrF,MAAM,EAAE,MAAM,CAAC,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,GAAG,WAAW,GAAG,QAAQ,EAAE,MAAM,CAAC,CAAC;IACnF;;;;;OAKG;IACH,UAAU,EAAE,OAAO,CAAC;IACpB,8EAA8E;IAC9E,QAAQ,EAAE,eAAe,CAAC;IAC1B,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,8DAA8D;IAC9D,UAAU,EAAE,MAAM,CAAC;IACnB,oEAAoE;IACpE,UAAU,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../../src/comments/form.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,cAAc,EAA4C,MAAM,iBAAiB,CAAC;AAC3F,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEpE;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB;IACjC,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,MAAM,EAAE,OAAO,cAAc,CAAC;IAC9B,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,qFAAqF;IACrF,MAAM,EAAE,MAAM,CAAC,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,GAAG,WAAW,GAAG,QAAQ,EAAE,MAAM,CAAC,CAAC;IACnF;;;;;OAKG;IACH,UAAU,EAAE,OAAO,CAAC;IACpB,8EAA8E;IAC9E,QAAQ,EAAE,eAAe,CAAC;IAC1B,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,8DAA8D;IAC9D,UAAU,EAAE,MAAM,CAAC;IACnB,oEAAoE;IACpE,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IACvD;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAC;IACb,4DAA4D;IAC5D,GAAG,EAAE,MAAM,CAAC;IACZ,4DAA4D;IAC5D,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,kBAAkB,EACxB,MAAM,EAAE,aAAa,GACpB,kBAAkB,CAMpB;AAED,oCAAoC;AACpC,eAAO,MAAM,iBAAiB,uBAAuB,CAAC;AAEtD,8EAA8E;AAC9E,eAAO,MAAM,oBAAoB,YAAY,CAAC;AAE9C;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,aAAa,CAAC;AAE9C;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAG5D,CAAC;AAEF,8DAA8D;AAC9D,wBAAgB,WAAW,CACzB,QAAQ,EAAE,QAAQ,EAClB,GAAG,GAAE,IAAiB,EACtB,UAAU,UAAQ,GACjB,kBAAkB,CAEpB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,kBAAkB,CAAC,QAAQ,CAAC,EACpC,QAAQ,EAAE,eAAe,EACzB,GAAG,GAAE,IAAiB,EACtB,KAAK,CAAC,EAAE,MAAM,EACd,UAAU,UAAQ,GACjB,kBAAkB,CAapB;AAED,wDAAwD;AACxD,wBAAgB,WAAW,IAAI,kBAAkB,CAAC,QAAQ,CAAC,CAE1D;AAED,sEAAsE;AACtE,wBAAgB,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CASxE"}
|
package/dist/comments/form.js
CHANGED
|
@@ -1,4 +1,19 @@
|
|
|
1
1
|
import { COMMENT_FIELDS, MAXIMUM_BODY_LENGTH, MAXIMUM_NAME_LENGTH } from './submission.js';
|
|
2
|
+
/**
|
|
3
|
+
* The same form drawn for somebody the site knows rather than for a stranger.
|
|
4
|
+
*
|
|
5
|
+
* A function over a built form rather than another parameter on the two
|
|
6
|
+
* builders, so `commentForm` and `refilledCommentForm` keep the signatures the
|
|
7
|
+
* package publishes and there is one place that decides what "signed in"
|
|
8
|
+
* changes about a form.
|
|
9
|
+
*/
|
|
10
|
+
export function signedInCommentForm(form, viewer) {
|
|
11
|
+
return {
|
|
12
|
+
...form,
|
|
13
|
+
signedInAs: { name: viewer.name, url: viewer.url },
|
|
14
|
+
csrfToken: viewer.csrfToken,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
2
17
|
/** Where the comment form posts. */
|
|
3
18
|
export const COMMENT_POST_PATH = '/_geekity/comments';
|
|
4
19
|
/** The query the redirect after a submission carries, and what it can say. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form.js","sourceRoot":"","sources":["../../src/comments/form.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"form.js","sourceRoot":"","sources":["../../src/comments/form.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AA+E3F;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CACjC,IAAwB,EACxB,MAAqB;IAErB,OAAO;QACL,GAAG,IAAI;QACP,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE;QAClD,SAAS,EAAE,MAAM,CAAC,SAAS;KAC5B,CAAC;AACJ,CAAC;AAED,oCAAoC;AACpC,MAAM,CAAC,MAAM,iBAAiB,GAAG,oBAAoB,CAAC;AAEtD,8EAA8E;AAC9E,MAAM,CAAC,MAAM,oBAAoB,GAAG,SAAS,CAAC;AAE9C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,UAAU,CAAC;AAE9C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,eAAe,GAAqC;IAC/D,MAAM,EAAE,0CAA0C;IAClD,OAAO,EAAE,qDAAqD;CAC/D,CAAC;AAEF,8DAA8D;AAC9D,MAAM,UAAU,WAAW,CACzB,QAAkB,EAClB,GAAG,GAAS,IAAI,IAAI,EAAE,EACtB,UAAU,GAAG,KAAK;IAElB,OAAO,mBAAmB,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;AACtF,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CACjC,QAAkB,EAClB,MAAoC,EACpC,QAAyB,EACzB,GAAG,GAAS,IAAI,IAAI,EAAE,EACtB,KAAc,EACd,UAAU,GAAG,KAAK;IAElB,OAAO;QACL,MAAM,EAAE,iBAAiB;QACzB,MAAM,EAAE,cAAc;QACtB,IAAI,EAAE,QAAQ,CAAC,IAAI;QACnB,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QAC7B,MAAM;QACN,QAAQ;QACR,UAAU;QACV,UAAU,EAAE,mBAAmB;QAC/B,UAAU,EAAE,mBAAmB;QAC/B,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;KAC1C,CAAC;AACJ,CAAC;AAED,wDAAwD;AACxD,MAAM,UAAU,WAAW;IACzB,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;AAC/E,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,QAAQ,CAAC,IAAiB;IACxC,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAC;AACJ,CAAC"}
|
package/dist/comments/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { AKISMET_ENDPOINT, AKISMET_KEY_FILE, AKISMET_TIMEOUT_MS, AKISMET_USER_AGENT, akismetKeyPath, createAkismetChecker, readAkismetKey, removeAkismetKey, verifyAkismetKey, writeAkismetKey, } from './akismet.ts';
|
|
2
2
|
export type { AkismetCheckerOptions, AkismetKeyRecord, AkismetKeyStatus, VerifyAkismetKeyOptions, } from './akismet.ts';
|
|
3
|
-
export { blankValues, COMMENT_NOTICE_PARAM, COMMENT_NOTICES, COMMENT_POST_PATH, COMMENT_REPLY_PARAM, commentForm, refilledCommentForm, valuesOf, } from './form.ts';
|
|
4
|
-
export type { CommentFormContext } from './form.ts';
|
|
3
|
+
export { blankValues, COMMENT_NOTICE_PARAM, COMMENT_NOTICES, COMMENT_POST_PATH, COMMENT_REPLY_PARAM, commentForm, refilledCommentForm, signedInCommentForm, valuesOf, } from './form.ts';
|
|
4
|
+
export type { CommentFormContext, CommentViewer } from './form.ts';
|
|
5
5
|
export { renderCommentMarkdown } from './markdown.ts';
|
|
6
6
|
export { isModerationAction, moderateComment, MODERATION_ACTIONS } from './moderate.ts';
|
|
7
7
|
export type { ModerateCommentOptions, ModerationAction, ModerationOutcome } from './moderate.ts';
|
|
@@ -11,5 +11,6 @@ export { addComment, COMMENTS_DATA_DIRECTORY, commentsDirectory, commentsFile, d
|
|
|
11
11
|
export type { CommentIndexReport, CommentIntakeOutcome, CommentNotices, CommentOrigin, CommentRecords, IntakeCommentOptions, NewComment, ProposedComment, } from './records.ts';
|
|
12
12
|
export { commentFormFor, commentNoticeFor, mountComments } from './routes.ts';
|
|
13
13
|
export { COMMENT_FIELDS, COMMENT_RATE_LIMIT, COMMENT_RATE_WINDOW_SECONDS, COMMENT_SALT_FILE, commentKeys, commentProblems, hashClientAddress, MAXIMUM_BODY_LENGTH, MAXIMUM_NAME_LENGTH, MAXIMUM_URL_LENGTH, MAXIMUM_FORM_AGE_SECONDS, MINIMUM_SUBMIT_SECONDS, normalizeWebsite, submitComment, } from './submission.ts';
|
|
14
|
-
export type { CommentChecker, CommentForm, CommentOutcome, CommentProblems, CommentRefusal, CommentReport, CommentSubmission, SubmissionType, CommentThrottle, CommentVerdict, SubmitCommentOptions, } from './submission.ts';
|
|
14
|
+
export type { CommentChecker, CommentForm, CommentOutcome, CommentProblems, CommentRefusal, CommentReport, CommentSubmission, SubmissionType, CommentThrottle, CommentVerdict, SignedInAuthor, SubmitCommentOptions, } from './submission.ts';
|
|
15
|
+
export { signedInCommenter } from './viewer.ts';
|
|
15
16
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/comments/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EAClB,cAAc,EACd,oBAAoB,EACpB,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,GAChB,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,qBAAqB,EACrB,gBAAgB,EAChB,gBAAgB,EAChB,uBAAuB,GACxB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,WAAW,EACX,mBAAmB,EACnB,QAAQ,GACT,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/comments/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EAClB,cAAc,EACd,oBAAoB,EACpB,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,GAChB,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,qBAAqB,EACrB,gBAAgB,EAChB,gBAAgB,EAChB,uBAAuB,GACxB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,WAAW,EACX,mBAAmB,EACnB,mBAAmB,EACnB,QAAQ,GACT,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACnE,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxF,YAAY,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACjG,OAAO,EACL,yBAAyB,EACzB,eAAe,EACf,YAAY,EACZ,iCAAiC,GAClC,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EACL,UAAU,EACV,uBAAuB,EACvB,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,cAAc,EACd,aAAa,EACb,YAAY,EACZ,qBAAqB,EACrB,aAAa,GACd,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,kBAAkB,EAClB,oBAAoB,EACpB,cAAc,EACd,aAAa,EACb,cAAc,EACd,oBAAoB,EACpB,UAAU,EACV,eAAe,GAChB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,2BAA2B,EAC3B,iBAAiB,EACjB,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,wBAAwB,EACxB,sBAAsB,EACtB,gBAAgB,EAChB,aAAa,GACd,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,cAAc,EACd,WAAW,EACX,cAAc,EACd,eAAe,EACf,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,cAAc,EACd,cAAc,EACd,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/comments/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
export { AKISMET_ENDPOINT, AKISMET_KEY_FILE, AKISMET_TIMEOUT_MS, AKISMET_USER_AGENT, akismetKeyPath, createAkismetChecker, readAkismetKey, removeAkismetKey, verifyAkismetKey, writeAkismetKey, } from './akismet.js';
|
|
2
|
-
export { blankValues, COMMENT_NOTICE_PARAM, COMMENT_NOTICES, COMMENT_POST_PATH, COMMENT_REPLY_PARAM, commentForm, refilledCommentForm, valuesOf, } from './form.js';
|
|
2
|
+
export { blankValues, COMMENT_NOTICE_PARAM, COMMENT_NOTICES, COMMENT_POST_PATH, COMMENT_REPLY_PARAM, commentForm, refilledCommentForm, signedInCommentForm, valuesOf, } from './form.js';
|
|
3
3
|
export { renderCommentMarkdown } from './markdown.js';
|
|
4
4
|
export { isModerationAction, moderateComment, MODERATION_ACTIONS } from './moderate.js';
|
|
5
5
|
export { COMMENTS_FRONT_MATTER_KEY, commentPolicyOf, commentsOpen, DEFAULT_COMMENTS_CLOSE_AFTER_DAYS, } from './policy.js';
|
|
6
6
|
export { addComment, COMMENTS_DATA_DIRECTORY, commentsDirectory, commentsFile, deleteComment, heldWebmention, intakeComment, readComments, rebuildCommentIndexes, updateComment, } from './records.js';
|
|
7
7
|
export { commentFormFor, commentNoticeFor, mountComments } from './routes.js';
|
|
8
8
|
export { COMMENT_FIELDS, COMMENT_RATE_LIMIT, COMMENT_RATE_WINDOW_SECONDS, COMMENT_SALT_FILE, commentKeys, commentProblems, hashClientAddress, MAXIMUM_BODY_LENGTH, MAXIMUM_NAME_LENGTH, MAXIMUM_URL_LENGTH, MAXIMUM_FORM_AGE_SECONDS, MINIMUM_SUBMIT_SECONDS, normalizeWebsite, submitComment, } from './submission.js';
|
|
9
|
+
export { signedInCommenter } from './viewer.js';
|
|
9
10
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/comments/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EAClB,cAAc,EACd,oBAAoB,EACpB,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,GAChB,MAAM,cAAc,CAAC;AAOtB,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,WAAW,EACX,mBAAmB,EACnB,QAAQ,GACT,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAExF,OAAO,EACL,yBAAyB,EACzB,eAAe,EACf,YAAY,EACZ,iCAAiC,GAClC,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,UAAU,EACV,uBAAuB,EACvB,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,cAAc,EACd,aAAa,EACb,YAAY,EACZ,qBAAqB,EACrB,aAAa,GACd,MAAM,cAAc,CAAC;AAWtB,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,2BAA2B,EAC3B,iBAAiB,EACjB,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,wBAAwB,EACxB,sBAAsB,EACtB,gBAAgB,EAChB,aAAa,GACd,MAAM,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/comments/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EAClB,cAAc,EACd,oBAAoB,EACpB,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,GAChB,MAAM,cAAc,CAAC;AAOtB,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,WAAW,EACX,mBAAmB,EACnB,mBAAmB,EACnB,QAAQ,GACT,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAExF,OAAO,EACL,yBAAyB,EACzB,eAAe,EACf,YAAY,EACZ,iCAAiC,GAClC,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,UAAU,EACV,uBAAuB,EACvB,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,cAAc,EACd,aAAa,EACb,YAAY,EACZ,qBAAqB,EACrB,aAAa,GACd,MAAM,cAAc,CAAC;AAWtB,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,2BAA2B,EAC3B,iBAAiB,EACjB,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,wBAAwB,EACxB,sBAAsB,EACtB,gBAAgB,EAChB,aAAa,GACd,MAAM,iBAAiB,CAAC;AAezB,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -2,7 +2,7 @@ import type { Hono } from 'hono';
|
|
|
2
2
|
import type { AdminStore } from '../admin/store.ts';
|
|
3
3
|
import type { Document } from '../content/document.ts';
|
|
4
4
|
import type { GeekityEnv } from '../env.ts';
|
|
5
|
-
import type { CommentFormContext } from './form.ts';
|
|
5
|
+
import type { CommentFormContext, CommentViewer } from './form.ts';
|
|
6
6
|
/**
|
|
7
7
|
* The one public endpoint comments add: where the form under a post posts to.
|
|
8
8
|
*
|
|
@@ -54,5 +54,7 @@ export declare function commentFormFor(options: {
|
|
|
54
54
|
now: Date;
|
|
55
55
|
/** Whether the site can send mail, which is whether the box is offered. */
|
|
56
56
|
notifiable?: boolean | undefined;
|
|
57
|
+
/** Who the request's session says is reading, when it says anybody. */
|
|
58
|
+
viewer?: CommentViewer | undefined;
|
|
57
59
|
}): CommentFormContext | undefined;
|
|
58
60
|
//# sourceMappingURL=routes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/comments/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,IAAI,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/comments/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,IAAI,EAAE,MAAM,MAAM,CAAC;AAG1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAGpD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAY5C,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAYnE;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAEnE,iEAAiE;AACjE,wBAAgB,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,UAAU,CAAC,GAAG,IAAI,CAiHzD;AAqCD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAE9E;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE;IAC1C,KAAK,EAAE,UAAU,CAAC;IAClB,QAAQ,EAAE,QAAQ,CAAC;IACnB,EAAE,EAAE,MAAM,GAAG,SAAS,CAAC;CACxB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQ1B;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE;IACtC,QAAQ,EAAE,QAAQ,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,GAAG,EAAE,IAAI,CAAC;IACV,2EAA2E;IAC3E,UAAU,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACjC,uEAAuE;IACvE,MAAM,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;CACpC,GAAG,kBAAkB,GAAG,SAAS,CAKjC"}
|
package/dist/comments/routes.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import { csrfTokenMatches } from '../admin/session.js';
|
|
1
2
|
import { clientAddress, createLoginThrottle } from '../admin/throttle.js';
|
|
2
3
|
import { isPublicDocument } from '../web/documents.js';
|
|
3
|
-
import {
|
|
4
|
+
import { PRIVATE_CACHE_CONTROL } from '../web/negotiate.js';
|
|
5
|
+
import { COMMENT_NOTICE_PARAM, COMMENT_NOTICES, COMMENT_POST_PATH, commentForm, refilledCommentForm, signedInCommentForm, valuesOf, } from './form.js';
|
|
4
6
|
import { commentPolicyOf, commentsOpen } from './policy.js';
|
|
5
7
|
import { commentAnchor } from '../web/conversation.js';
|
|
6
8
|
import { COMMENT_FIELDS, COMMENT_RATE_LIMIT, COMMENT_RATE_WINDOW_SECONDS, submitComment, } from './submission.js';
|
|
9
|
+
import { signedInCommenter } from './viewer.js';
|
|
7
10
|
/**
|
|
8
11
|
* The one public endpoint comments add: where the form under a post posts to.
|
|
9
12
|
*
|
|
@@ -37,6 +40,17 @@ export function mountComments(app) {
|
|
|
37
40
|
const { store, admin, renderer, config } = c.var;
|
|
38
41
|
const body = await c.req.parseBody();
|
|
39
42
|
const form = formOf(body);
|
|
43
|
+
// Who the session says this is, read before anything else is decided: it
|
|
44
|
+
// settles the token, the attribution and where the comment lands.
|
|
45
|
+
const viewer = signedInCommenter(c);
|
|
46
|
+
// A form that acts on nobody's behalf needs no token, and the public one
|
|
47
|
+
// still carries none. This one posts under somebody's name, so without a
|
|
48
|
+
// matching token a page on another site could make them say something they
|
|
49
|
+
// never typed. Refused in the words and with the status the admin guard
|
|
50
|
+
// uses, because it is the same check on the same token.
|
|
51
|
+
if (viewer !== undefined && !csrfTokenMatches(viewer.csrfToken, form.csrf)) {
|
|
52
|
+
return c.text('That form was stale or came from somewhere else. Reload and try again.', 403);
|
|
53
|
+
}
|
|
40
54
|
const document = store.getBySlug(form.post);
|
|
41
55
|
if (document === undefined || !isPublicDocument(document, store.now())) {
|
|
42
56
|
return c.text('There is no such post to comment on.', 404);
|
|
@@ -46,8 +60,8 @@ export function mountComments(app) {
|
|
|
46
60
|
// 403 rather than 404: the post is there, and the reader can see for
|
|
47
61
|
// themselves that it is. Saying so is more honest than pretending the
|
|
48
62
|
// URL is wrong, and a closed post is a state rather than a mistake.
|
|
49
|
-
return page(c, document, 403, {
|
|
50
|
-
...refilledCommentForm(document, valuesOf(form), {}, now),
|
|
63
|
+
return page(c, document, 403, viewer, {
|
|
64
|
+
...drawnFor(refilledCommentForm(document, valuesOf(form), {}, now), viewer),
|
|
51
65
|
error: 'This post is not taking comments any more.',
|
|
52
66
|
});
|
|
53
67
|
}
|
|
@@ -58,6 +72,10 @@ export function mountComments(app) {
|
|
|
58
72
|
dataDir: config.dataDir,
|
|
59
73
|
baseUrl: config.baseUrl,
|
|
60
74
|
checker: config.commentChecker,
|
|
75
|
+
// Who the site knows is writing, when it knows (TASK-103). Set, it is
|
|
76
|
+
// the whole of the comment's attribution and the reason it is approved
|
|
77
|
+
// on arrival.
|
|
78
|
+
author: viewer,
|
|
61
79
|
// Who hears about what lands is the intake's to decide, and neither
|
|
62
80
|
// message is awaited: the reader is redirected now and they go out
|
|
63
81
|
// behind them (TASK-55).
|
|
@@ -90,8 +108,8 @@ export function mountComments(app) {
|
|
|
90
108
|
}
|
|
91
109
|
if (refusal.kind === 'rate-limited') {
|
|
92
110
|
c.header('Retry-After', String(refusal.retryAfter));
|
|
93
|
-
return page(c, document, 429, {
|
|
94
|
-
...refilledCommentForm(document, valuesOf(form), {}, now),
|
|
111
|
+
return page(c, document, 429, viewer, {
|
|
112
|
+
...drawnFor(refilledCommentForm(document, valuesOf(form), {}, now), viewer),
|
|
95
113
|
error: 'That is a lot of comments in a short time. Try again in a few minutes.',
|
|
96
114
|
});
|
|
97
115
|
}
|
|
@@ -100,16 +118,31 @@ export function mountComments(app) {
|
|
|
100
118
|
: refusal.kind === 'stale'
|
|
101
119
|
? 'That form had been open a long time. Here it is again — the words are still there.'
|
|
102
120
|
: undefined;
|
|
103
|
-
return page(c, document, 400, {
|
|
104
|
-
...refilledCommentForm(document, valuesOf(form), problemsOf(refusal), now),
|
|
121
|
+
return page(c, document, 400, viewer, {
|
|
122
|
+
...drawnFor(refilledCommentForm(document, valuesOf(form), problemsOf(refusal), now), viewer),
|
|
105
123
|
...(message === undefined ? {} : { error: message }),
|
|
106
124
|
});
|
|
107
125
|
});
|
|
108
126
|
}
|
|
109
|
-
/**
|
|
110
|
-
|
|
127
|
+
/**
|
|
128
|
+
* The same form drawn for whoever is filling it in: the short one when the
|
|
129
|
+
* site knows them, and the stranger's one when it does not.
|
|
130
|
+
*/
|
|
131
|
+
function drawnFor(form, viewer) {
|
|
132
|
+
return viewer === undefined ? form : signedInCommentForm(form, viewer);
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* The post's own page, rendered again with this form on it.
|
|
136
|
+
*
|
|
137
|
+
* A page drawn for a named reader says so, for the reason the rendered post
|
|
138
|
+
* does: it is one person's page rather than the post, and nothing in front of
|
|
139
|
+
* the site may hold it and hand it to the next reader.
|
|
140
|
+
*/
|
|
141
|
+
function page(c, document, status, viewer, form) {
|
|
111
142
|
c.status(status);
|
|
112
|
-
|
|
143
|
+
if (viewer !== undefined)
|
|
144
|
+
c.header('cache-control', PRIVATE_CACHE_CONTROL);
|
|
145
|
+
return c.html(c.var.renderer.renderDocument(document, { commentForm: form }, viewer));
|
|
113
146
|
}
|
|
114
147
|
/** The per-field messages a refusal carries, if it carries any. */
|
|
115
148
|
function problemsOf(refusal) {
|
|
@@ -154,7 +187,8 @@ export function commentReplyTarget(options) {
|
|
|
154
187
|
export function commentFormFor(options) {
|
|
155
188
|
if (!commentsOpen(options.document, commentPolicyOf(options.site), options.now))
|
|
156
189
|
return undefined;
|
|
157
|
-
|
|
190
|
+
const form = commentForm(options.document, options.now, options.notifiable ?? false);
|
|
191
|
+
return drawnFor(form, options.viewer);
|
|
158
192
|
}
|
|
159
193
|
/** A submitted body as the form it is, every field a string. */
|
|
160
194
|
function formOf(body) {
|
|
@@ -168,6 +202,7 @@ function formOf(body) {
|
|
|
168
202
|
trap: text(body[COMMENT_FIELDS.trap]),
|
|
169
203
|
loaded: text(body[COMMENT_FIELDS.loaded]),
|
|
170
204
|
notify: text(body[COMMENT_FIELDS.notify]),
|
|
205
|
+
csrf: text(body[COMMENT_FIELDS.csrf]),
|
|
171
206
|
};
|
|
172
207
|
}
|
|
173
208
|
/** A form field as a string. A file upload, or a missing field, is the empty one. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/comments/routes.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/comments/routes.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { PostComment } from '../admin/store.ts';
|
|
1
|
+
import type { CommentAuthor, PostComment } from '../admin/store.ts';
|
|
2
2
|
import type { Document } from '../content/document.ts';
|
|
3
3
|
import type { CommentNotices, CommentRecords } from './records.ts';
|
|
4
4
|
/**
|
|
@@ -43,6 +43,13 @@ export declare const COMMENT_FIELDS: {
|
|
|
43
43
|
readonly trap: "website";
|
|
44
44
|
/** When the form was rendered, in epoch milliseconds. */
|
|
45
45
|
readonly loaded: "loaded";
|
|
46
|
+
/**
|
|
47
|
+
* The CSRF token, which only the signed-in form carries (TASK-103).
|
|
48
|
+
*
|
|
49
|
+
* Spelled exactly as every admin form spells it, because it is the same
|
|
50
|
+
* per-session token and is checked by the same comparison.
|
|
51
|
+
*/
|
|
52
|
+
readonly csrf: "csrf_token";
|
|
46
53
|
/**
|
|
47
54
|
* "Tell me when somebody answers this."
|
|
48
55
|
*
|
|
@@ -53,7 +60,7 @@ export declare const COMMENT_FIELDS: {
|
|
|
53
60
|
readonly notify: 'notify';
|
|
54
61
|
};
|
|
55
62
|
/** A submitted comment form, as strings, which is what a form has. */
|
|
56
|
-
export type CommentForm = Record<'post' | 'name' | 'email' | 'url' | 'body' | 'inReplyTo' | 'trap' | 'loaded' | 'notify', string>;
|
|
63
|
+
export type CommentForm = Record<'post' | 'name' | 'email' | 'url' | 'body' | 'inReplyTo' | 'trap' | 'loaded' | 'notify' | 'csrf', string>;
|
|
57
64
|
/** How many comments one address may post before it has to wait. */
|
|
58
65
|
export declare const COMMENT_RATE_LIMIT = 5;
|
|
59
66
|
/** How long that window is, and how long the first wait after it lasts. */
|
|
@@ -72,8 +79,12 @@ export type CommentProblems = Partial<Record<'name' | 'email' | 'url' | 'body',
|
|
|
72
79
|
* Only the things a person can fix. The honeypot, the form's age and the rate
|
|
73
80
|
* limit are not here: none of them is the commenter's mistake, and two of them
|
|
74
81
|
* should not be explained to whoever tripped them.
|
|
82
|
+
*
|
|
83
|
+
* A signed-in commenter is asked for nothing but the comment (TASK-103), so
|
|
84
|
+
* only the comment is checked: the name, the email and the website come off
|
|
85
|
+
* the account and there are no boxes on the form to put anything right in.
|
|
75
86
|
*/
|
|
76
|
-
export declare function commentProblems(form: CommentForm): CommentProblems;
|
|
87
|
+
export declare function commentProblems(form: CommentForm, signedIn?: boolean): CommentProblems;
|
|
77
88
|
/**
|
|
78
89
|
* What a checker is told a submission is.
|
|
79
90
|
*
|
|
@@ -197,6 +208,16 @@ export type CommentOutcome = {
|
|
|
197
208
|
kind: 'refused';
|
|
198
209
|
refusal: CommentRefusal;
|
|
199
210
|
};
|
|
211
|
+
/**
|
|
212
|
+
* A comment's author as somebody other than the form says it.
|
|
213
|
+
*
|
|
214
|
+
* What a signed-in submission is attributed from: the account's name, its
|
|
215
|
+
* author archive as the website, and its email — which is stored and never
|
|
216
|
+
* shown, exactly as a stranger's is never shown. It is the stored author minus
|
|
217
|
+
* the one field no account can supply: a picture only ever arrives with a
|
|
218
|
+
* webmention (TASK-51).
|
|
219
|
+
*/
|
|
220
|
+
export type SignedInAuthor = Omit<CommentAuthor, 'avatar'>;
|
|
200
221
|
/** What {@link submitComment} needs around it. */
|
|
201
222
|
export interface SubmitCommentOptions {
|
|
202
223
|
/** The files and the index a stored comment goes into. */
|
|
@@ -211,6 +232,19 @@ export interface SubmitCommentOptions {
|
|
|
211
232
|
baseUrl: string;
|
|
212
233
|
/** The checker, when the site named one. */
|
|
213
234
|
checker?: CommentChecker | undefined;
|
|
235
|
+
/**
|
|
236
|
+
* Who the session says is commenting, when one does (TASK-103).
|
|
237
|
+
*
|
|
238
|
+
* Set, it is the whole of the comment's attribution: what was typed in a
|
|
239
|
+
* name, email or website field is ignored, because the signed-in form has no
|
|
240
|
+
* such fields and anything arriving in them was not put there by the person
|
|
241
|
+
* the session names. It also settles the three cheap defences — the honeypot
|
|
242
|
+
* and the form's age are there to catch a robot filling a public form, and a
|
|
243
|
+
* session is better evidence than either, so neither is checked — and it
|
|
244
|
+
* makes this a comment the site's own author is writing, which the intake
|
|
245
|
+
* approves on arrival and never offers to a checker.
|
|
246
|
+
*/
|
|
247
|
+
author?: SignedInAuthor | undefined;
|
|
214
248
|
/** Who to tell about what lands, handed straight to the intake (TASK-55). */
|
|
215
249
|
notices?: CommentNotices | undefined;
|
|
216
250
|
/** Where the request came from, as far as the site can tell. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"submission.d.ts","sourceRoot":"","sources":["../../src/comments/submission.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"submission.d.ts","sourceRoot":"","sources":["../../src/comments/submission.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CSRF_FIELD } from '../admin/session.js';
|
|
1
2
|
import { ADDRESS_SALT_FILE, FORM_LOADED_FIELD, FORM_TRAP_FIELD, formTimingRefusal, trapped, } from '../forms/protection.js';
|
|
2
3
|
import { renderCommentMarkdown } from './markdown.js';
|
|
3
4
|
import { intakeComment } from './records.js';
|
|
@@ -45,6 +46,13 @@ export const COMMENT_FIELDS = {
|
|
|
45
46
|
trap: FORM_TRAP_FIELD,
|
|
46
47
|
/** When the form was rendered, in epoch milliseconds. */
|
|
47
48
|
loaded: FORM_LOADED_FIELD,
|
|
49
|
+
/**
|
|
50
|
+
* The CSRF token, which only the signed-in form carries (TASK-103).
|
|
51
|
+
*
|
|
52
|
+
* Spelled exactly as every admin form spells it, because it is the same
|
|
53
|
+
* per-session token and is checked by the same comparison.
|
|
54
|
+
*/
|
|
55
|
+
csrf: CSRF_FIELD,
|
|
48
56
|
/**
|
|
49
57
|
* "Tell me when somebody answers this."
|
|
50
58
|
*
|
|
@@ -70,21 +78,27 @@ export const MAXIMUM_BODY_LENGTH = 10_000;
|
|
|
70
78
|
* Only the things a person can fix. The honeypot, the form's age and the rate
|
|
71
79
|
* limit are not here: none of them is the commenter's mistake, and two of them
|
|
72
80
|
* should not be explained to whoever tripped them.
|
|
81
|
+
*
|
|
82
|
+
* A signed-in commenter is asked for nothing but the comment (TASK-103), so
|
|
83
|
+
* only the comment is checked: the name, the email and the website come off
|
|
84
|
+
* the account and there are no boxes on the form to put anything right in.
|
|
73
85
|
*/
|
|
74
|
-
export function commentProblems(form) {
|
|
86
|
+
export function commentProblems(form, signedIn = false) {
|
|
75
87
|
const problems = {};
|
|
76
|
-
const name = form.name.trim();
|
|
77
|
-
if (name === '')
|
|
78
|
-
problems.name = 'A comment needs a name to go under.';
|
|
79
|
-
else if (name.length > MAXIMUM_NAME_LENGTH) {
|
|
80
|
-
problems.name = `That name is longer than ${String(MAXIMUM_NAME_LENGTH)} characters.`;
|
|
81
|
-
}
|
|
82
88
|
const body = form.body.trim();
|
|
83
89
|
if (body === '')
|
|
84
90
|
problems.body = 'A comment needs something in it.';
|
|
85
91
|
else if (body.length > MAXIMUM_BODY_LENGTH) {
|
|
86
92
|
problems.body = `That comment is longer than ${String(MAXIMUM_BODY_LENGTH)} characters.`;
|
|
87
93
|
}
|
|
94
|
+
if (signedIn)
|
|
95
|
+
return problems;
|
|
96
|
+
const name = form.name.trim();
|
|
97
|
+
if (name === '')
|
|
98
|
+
problems.name = 'A comment needs a name to go under.';
|
|
99
|
+
else if (name.length > MAXIMUM_NAME_LENGTH) {
|
|
100
|
+
problems.name = `That name is longer than ${String(MAXIMUM_NAME_LENGTH)} characters.`;
|
|
101
|
+
}
|
|
88
102
|
const email = form.email.trim();
|
|
89
103
|
if (email !== '' && !isEmail(email)) {
|
|
90
104
|
problems.email =
|
|
@@ -106,28 +120,47 @@ export function commentProblems(form) {
|
|
|
106
120
|
export async function submitComment(options) {
|
|
107
121
|
const { records, document, form, throttle } = options;
|
|
108
122
|
const now = options.now ?? new Date();
|
|
123
|
+
// Whether the site knows who this is. It decides the attribution, the two
|
|
124
|
+
// cheap defences and where the comment lands, so it is read once.
|
|
125
|
+
const signedIn = options.author;
|
|
109
126
|
// The honeypot first, because it costs one comparison and because a
|
|
110
127
|
// submission that tripped it should not reach anything that could tell it so.
|
|
111
|
-
|
|
128
|
+
// Not for a signed-in commenter: their form carries no honeypot, and a
|
|
129
|
+
// session is better evidence than an empty box.
|
|
130
|
+
if (signedIn === undefined && trapped(form.trap))
|
|
112
131
|
return refused({ kind: 'discarded' });
|
|
113
|
-
const problems = commentProblems(form);
|
|
132
|
+
const problems = commentProblems(form, signedIn !== undefined);
|
|
114
133
|
if (Object.keys(problems).length > 0)
|
|
115
134
|
return refused({ kind: 'invalid', problems });
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
135
|
+
// The form's age, for the same reason and with the same exception: a
|
|
136
|
+
// signed-in form carries no loaded-at stamp to measure.
|
|
137
|
+
if (signedIn === undefined) {
|
|
138
|
+
const timing = formTimingRefusal(form.loaded, now);
|
|
139
|
+
if (timing !== undefined)
|
|
140
|
+
return refused({ kind: timing });
|
|
141
|
+
}
|
|
142
|
+
// The rate limit stays either way. It is not about proving somebody is a
|
|
143
|
+
// person; it is about what one address may do in ten minutes, and a stolen
|
|
144
|
+
// session is exactly the case it would be wanted for.
|
|
119
145
|
const keys = commentKeys(options.address);
|
|
120
146
|
const wait = throttle.retryAfter(keys);
|
|
121
147
|
if (wait !== undefined)
|
|
122
148
|
return refused({ kind: 'rate-limited', retryAfter: wait });
|
|
123
149
|
const markdown = form.body.trim();
|
|
124
|
-
const author =
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
150
|
+
const author = signedIn === undefined
|
|
151
|
+
? {
|
|
152
|
+
name: form.name.trim(),
|
|
153
|
+
url: normalizeWebsite(form.url.trim()) ?? null,
|
|
154
|
+
email: form.email.trim() === '' ? null : form.email.trim(),
|
|
155
|
+
// A form asks for no picture: only a webmention brings one (TASK-51).
|
|
156
|
+
avatar: null,
|
|
157
|
+
}
|
|
158
|
+
: {
|
|
159
|
+
name: signedIn.name,
|
|
160
|
+
url: signedIn.url,
|
|
161
|
+
email: signedIn.email,
|
|
162
|
+
avatar: null,
|
|
163
|
+
};
|
|
131
164
|
const proposed = {
|
|
132
165
|
slug: document.slug,
|
|
133
166
|
permalink: document.permalink,
|
|
@@ -146,7 +179,13 @@ export async function submitComment(options) {
|
|
|
146
179
|
};
|
|
147
180
|
const outcome = await intakeComment({
|
|
148
181
|
records,
|
|
149
|
-
|
|
182
|
+
// Geekity has one role, so anybody who can sign in can already publish a
|
|
183
|
+
// post and approve any comment. A comment of theirs waiting in a queue for
|
|
184
|
+
// them to approve would be theatre, and a spam service has no say in what
|
|
185
|
+
// the owner of the site says — so a signed-in comment arrives at the
|
|
186
|
+
// intake as exactly what it is, the site's own author writing, and is
|
|
187
|
+
// approved on arrival with no call to the checker (TASK-103).
|
|
188
|
+
origin: signedIn === undefined ? 'form' : 'moderator',
|
|
150
189
|
comment: proposed,
|
|
151
190
|
post: {
|
|
152
191
|
title: document.title,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"submission.js","sourceRoot":"","sources":["../../src/comments/submission.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"submission.js","sourceRoot":"","sources":["../../src/comments/submission.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Context } from 'hono';
|
|
2
|
+
import type { GeekityEnv } from '../env.ts';
|
|
3
|
+
import type { CommentViewer } from './form.ts';
|
|
4
|
+
/**
|
|
5
|
+
* Who the public site knows is reading it, when the request carries a login.
|
|
6
|
+
*
|
|
7
|
+
* The one place outside `/admin` that turns a session cookie into a person.
|
|
8
|
+
* Everything a comment needs about them is answered here — the name it goes
|
|
9
|
+
* under, the archive it links to, the email it is stored with and the token
|
|
10
|
+
* the form has to carry — so the page that draws the form and the endpoint
|
|
11
|
+
* that takes the submission are looking at one reading of one session.
|
|
12
|
+
*
|
|
13
|
+
* Deliberately total about the ways a cookie can be worth nothing. A forged or
|
|
14
|
+
* expired id, a session belonging to a user who has since been deleted, and
|
|
15
|
+
* the anonymous session that holds a CSRF token before anybody has logged in
|
|
16
|
+
* all answer `undefined`, which is the stranger's form: the only thing that
|
|
17
|
+
* gets the short form is a live session naming a user `users.json` still
|
|
18
|
+
* holds, which is the same test the admin guard applies at its own door.
|
|
19
|
+
*/
|
|
20
|
+
export declare function signedInCommenter(c: Context<GeekityEnv>): CommentViewer | undefined;
|
|
21
|
+
//# sourceMappingURL=viewer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"viewer.d.ts","sourceRoot":"","sources":["../../src/comments/viewer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAIpC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE5C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,aAAa,GAAG,SAAS,CAwBnF"}
|