@geekity/cms 0.8.0 → 0.10.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.
Files changed (236) hide show
  1. package/README.md +344 -47
  2. package/admin/components/admin-bar.njk +26 -0
  3. package/admin/components/public-admin-bar.njk +41 -0
  4. package/admin/layouts/base.njk +1 -0
  5. package/admin/layouts/shell.njk +8 -19
  6. package/admin/pages/comments/all.njk +3 -0
  7. package/admin/pages/settings/discussion.njk +53 -0
  8. package/admin/pages/settings/email.njk +20 -0
  9. package/admin/pages/tools/personal-data.njk +67 -0
  10. package/admin/pages/users/edit.njk +1 -1
  11. package/admin/static/admin-bar.css +137 -0
  12. package/admin/static/admin.css +1 -102
  13. package/dist/admin/comments.d.ts +5 -0
  14. package/dist/admin/comments.d.ts.map +1 -1
  15. package/dist/admin/comments.js +15 -1
  16. package/dist/admin/comments.js.map +1 -1
  17. package/dist/admin/headers.d.ts +14 -5
  18. package/dist/admin/headers.d.ts.map +1 -1
  19. package/dist/admin/headers.js +18 -6
  20. package/dist/admin/headers.js.map +1 -1
  21. package/dist/admin/index.d.ts +2 -2
  22. package/dist/admin/index.d.ts.map +1 -1
  23. package/dist/admin/index.js +1 -1
  24. package/dist/admin/index.js.map +1 -1
  25. package/dist/admin/menu.d.ts.map +1 -1
  26. package/dist/admin/menu.js +5 -1
  27. package/dist/admin/menu.js.map +1 -1
  28. package/dist/admin/personal-data.d.ts +35 -0
  29. package/dist/admin/personal-data.d.ts.map +1 -0
  30. package/dist/admin/personal-data.js +94 -0
  31. package/dist/admin/personal-data.js.map +1 -0
  32. package/dist/admin/preview.d.ts.map +1 -1
  33. package/dist/admin/preview.js +1 -1
  34. package/dist/admin/preview.js.map +1 -1
  35. package/dist/admin/routes.d.ts.map +1 -1
  36. package/dist/admin/routes.js +20 -3
  37. package/dist/admin/routes.js.map +1 -1
  38. package/dist/admin/session.d.ts +42 -1
  39. package/dist/admin/session.d.ts.map +1 -1
  40. package/dist/admin/session.js +74 -4
  41. package/dist/admin/session.js.map +1 -1
  42. package/dist/admin/settings-discussion.d.ts.map +1 -1
  43. package/dist/admin/settings-discussion.js +9 -1
  44. package/dist/admin/settings-discussion.js.map +1 -1
  45. package/dist/admin/settings-email.d.ts.map +1 -1
  46. package/dist/admin/settings-email.js +10 -1
  47. package/dist/admin/settings-email.js.map +1 -1
  48. package/dist/admin/settings.d.ts +39 -0
  49. package/dist/admin/settings.d.ts.map +1 -1
  50. package/dist/admin/settings.js +144 -0
  51. package/dist/admin/settings.js.map +1 -1
  52. package/dist/admin/store.d.ts +65 -0
  53. package/dist/admin/store.d.ts.map +1 -1
  54. package/dist/admin/store.js +130 -5
  55. package/dist/admin/store.js.map +1 -1
  56. package/dist/admin/templates.d.ts +2 -0
  57. package/dist/admin/templates.d.ts.map +1 -1
  58. package/dist/admin/templates.js +2 -0
  59. package/dist/admin/templates.js.map +1 -1
  60. package/dist/admin/tools.d.ts +2 -0
  61. package/dist/admin/tools.d.ts.map +1 -1
  62. package/dist/admin/tools.js +3 -2
  63. package/dist/admin/tools.js.map +1 -1
  64. package/dist/avatars/avatars.d.ts +112 -0
  65. package/dist/avatars/avatars.d.ts.map +1 -0
  66. package/dist/avatars/avatars.js +259 -0
  67. package/dist/avatars/avatars.js.map +1 -0
  68. package/dist/avatars/index.d.ts +4 -0
  69. package/dist/avatars/index.d.ts.map +1 -0
  70. package/dist/avatars/index.js +3 -0
  71. package/dist/avatars/index.js.map +1 -0
  72. package/dist/avatars/routes.d.ts +11 -0
  73. package/dist/avatars/routes.d.ts.map +1 -0
  74. package/dist/avatars/routes.js +33 -0
  75. package/dist/avatars/routes.js.map +1 -0
  76. package/dist/comments/index.d.ts +2 -2
  77. package/dist/comments/index.d.ts.map +1 -1
  78. package/dist/comments/index.js +1 -1
  79. package/dist/comments/index.js.map +1 -1
  80. package/dist/comments/records.d.ts +58 -2
  81. package/dist/comments/records.d.ts.map +1 -1
  82. package/dist/comments/records.js +244 -47
  83. package/dist/comments/records.js.map +1 -1
  84. package/dist/comments/routes.d.ts.map +1 -1
  85. package/dist/comments/routes.js +8 -2
  86. package/dist/comments/routes.js.map +1 -1
  87. package/dist/comments/viewer.d.ts +13 -0
  88. package/dist/comments/viewer.d.ts.map +1 -1
  89. package/dist/comments/viewer.js +13 -1
  90. package/dist/comments/viewer.js.map +1 -1
  91. package/dist/config.d.ts +35 -0
  92. package/dist/config.d.ts.map +1 -1
  93. package/dist/config.js +58 -0
  94. package/dist/config.js.map +1 -1
  95. package/dist/contact/index.d.ts +1 -1
  96. package/dist/contact/index.d.ts.map +1 -1
  97. package/dist/contact/index.js +1 -1
  98. package/dist/contact/index.js.map +1 -1
  99. package/dist/contact/records.d.ts +8 -2
  100. package/dist/contact/records.d.ts.map +1 -1
  101. package/dist/contact/records.js +13 -6
  102. package/dist/contact/records.js.map +1 -1
  103. package/dist/env.d.ts +25 -0
  104. package/dist/env.d.ts.map +1 -1
  105. package/dist/federation/delivery.d.ts +3 -1
  106. package/dist/federation/delivery.d.ts.map +1 -1
  107. package/dist/federation/delivery.js +6 -1
  108. package/dist/federation/delivery.js.map +1 -1
  109. package/dist/federation/federation.d.ts +3 -0
  110. package/dist/federation/federation.d.ts.map +1 -1
  111. package/dist/federation/federation.js.map +1 -1
  112. package/dist/federation/inbox.d.ts +7 -5
  113. package/dist/federation/inbox.d.ts.map +1 -1
  114. package/dist/federation/inbox.js +15 -32
  115. package/dist/federation/inbox.js.map +1 -1
  116. package/dist/federation/index.d.ts +2 -0
  117. package/dist/federation/index.d.ts.map +1 -1
  118. package/dist/federation/index.js +1 -0
  119. package/dist/federation/index.js.map +1 -1
  120. package/dist/federation/mount.js +6 -1
  121. package/dist/federation/mount.js.map +1 -1
  122. package/dist/federation/profiles.d.ts +95 -0
  123. package/dist/federation/profiles.d.ts.map +1 -0
  124. package/dist/federation/profiles.js +171 -0
  125. package/dist/federation/profiles.js.map +1 -0
  126. package/dist/federation/quotes.d.ts +2 -0
  127. package/dist/federation/quotes.d.ts.map +1 -1
  128. package/dist/federation/quotes.js +4 -0
  129. package/dist/federation/quotes.js.map +1 -1
  130. package/dist/federation/relays.d.ts +3 -1
  131. package/dist/federation/relays.d.ts.map +1 -1
  132. package/dist/federation/relays.js +6 -1
  133. package/dist/federation/relays.js.map +1 -1
  134. package/dist/federation/replies.d.ts +36 -4
  135. package/dist/federation/replies.d.ts.map +1 -1
  136. package/dist/federation/replies.js +71 -15
  137. package/dist/federation/replies.js.map +1 -1
  138. package/dist/images/icons.d.ts.map +1 -1
  139. package/dist/images/icons.js +3 -2
  140. package/dist/images/icons.js.map +1 -1
  141. package/dist/images/index.d.ts +2 -2
  142. package/dist/images/index.d.ts.map +1 -1
  143. package/dist/images/markup.d.ts +15 -4
  144. package/dist/images/markup.d.ts.map +1 -1
  145. package/dist/images/markup.js +24 -15
  146. package/dist/images/markup.js.map +1 -1
  147. package/dist/images/paths.d.ts +11 -0
  148. package/dist/images/paths.d.ts.map +1 -1
  149. package/dist/images/paths.js +17 -1
  150. package/dist/images/paths.js.map +1 -1
  151. package/dist/images/variants.d.ts +13 -3
  152. package/dist/images/variants.d.ts.map +1 -1
  153. package/dist/images/variants.js +13 -11
  154. package/dist/images/variants.js.map +1 -1
  155. package/dist/index.d.ts +34 -7
  156. package/dist/index.d.ts.map +1 -1
  157. package/dist/index.js +91 -18
  158. package/dist/index.js.map +1 -1
  159. package/dist/notifications/index.d.ts +1 -1
  160. package/dist/notifications/index.d.ts.map +1 -1
  161. package/dist/notifications/index.js +1 -1
  162. package/dist/notifications/index.js.map +1 -1
  163. package/dist/notifications/optouts.d.ts +6 -0
  164. package/dist/notifications/optouts.d.ts.map +1 -1
  165. package/dist/notifications/optouts.js +17 -0
  166. package/dist/notifications/optouts.js.map +1 -1
  167. package/dist/notifications/routes.js +1 -1
  168. package/dist/notifications/routes.js.map +1 -1
  169. package/dist/privacy/erase.d.ts +45 -0
  170. package/dist/privacy/erase.d.ts.map +1 -0
  171. package/dist/privacy/erase.js +76 -0
  172. package/dist/privacy/erase.js.map +1 -0
  173. package/dist/privacy/policy.d.ts +32 -0
  174. package/dist/privacy/policy.d.ts.map +1 -0
  175. package/dist/privacy/policy.js +37 -0
  176. package/dist/privacy/policy.js.map +1 -0
  177. package/dist/privacy/retention.d.ts +79 -0
  178. package/dist/privacy/retention.d.ts.map +1 -0
  179. package/dist/privacy/retention.js +133 -0
  180. package/dist/privacy/retention.js.map +1 -0
  181. package/dist/web/admin-bar.d.ts +21 -0
  182. package/dist/web/admin-bar.d.ts.map +1 -0
  183. package/dist/web/admin-bar.js +145 -0
  184. package/dist/web/admin-bar.js.map +1 -0
  185. package/dist/web/assets.d.ts +29 -1
  186. package/dist/web/assets.d.ts.map +1 -1
  187. package/dist/web/assets.js +48 -3
  188. package/dist/web/assets.js.map +1 -1
  189. package/dist/web/compression.d.ts +19 -0
  190. package/dist/web/compression.d.ts.map +1 -0
  191. package/dist/web/compression.js +160 -0
  192. package/dist/web/compression.js.map +1 -0
  193. package/dist/web/context.d.ts +5 -1
  194. package/dist/web/context.d.ts.map +1 -1
  195. package/dist/web/context.js +5 -2
  196. package/dist/web/context.js.map +1 -1
  197. package/dist/web/conversation.d.ts +9 -1
  198. package/dist/web/conversation.d.ts.map +1 -1
  199. package/dist/web/conversation.js +79 -17
  200. package/dist/web/conversation.js.map +1 -1
  201. package/dist/web/index.d.ts +1 -0
  202. package/dist/web/index.d.ts.map +1 -1
  203. package/dist/web/index.js +1 -0
  204. package/dist/web/index.js.map +1 -1
  205. package/dist/web/maintenance.d.ts.map +1 -1
  206. package/dist/web/maintenance.js +7 -2
  207. package/dist/web/maintenance.js.map +1 -1
  208. package/dist/web/render.d.ts +27 -0
  209. package/dist/web/render.d.ts.map +1 -1
  210. package/dist/web/render.js +77 -38
  211. package/dist/web/render.js.map +1 -1
  212. package/dist/web/routes.d.ts.map +1 -1
  213. package/dist/web/routes.js +67 -28
  214. package/dist/web/routes.js.map +1 -1
  215. package/dist/web/templates.d.ts.map +1 -1
  216. package/dist/web/templates.js +9 -2
  217. package/dist/web/templates.js.map +1 -1
  218. package/dist/web/well-known.d.ts +21 -0
  219. package/dist/web/well-known.d.ts.map +1 -0
  220. package/dist/web/well-known.js +66 -0
  221. package/dist/web/well-known.js.map +1 -0
  222. package/dist/webmention/fetch-public.d.ts +34 -0
  223. package/dist/webmention/fetch-public.d.ts.map +1 -0
  224. package/dist/webmention/fetch-public.js +101 -0
  225. package/dist/webmention/fetch-public.js.map +1 -0
  226. package/dist/webmention/reply-context.d.ts.map +1 -1
  227. package/dist/webmention/reply-context.js +12 -89
  228. package/dist/webmention/reply-context.js.map +1 -1
  229. package/dist/webmention/service.d.ts.map +1 -1
  230. package/dist/webmention/service.js +5 -1
  231. package/dist/webmention/service.js.map +1 -1
  232. package/package.json +1 -1
  233. package/templates/site/content/_data/site.json +7 -1
  234. package/templates/site/content/pages/privacy.md +127 -0
  235. package/themes/default/README.md +165 -22
  236. package/themes/default/layouts/base.njk +51 -10
@@ -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,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"}
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,wBAAwB,EACxB,wBAAwB,EACxB,iBAAiB,EACjB,uBAAuB,EACvB,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,YAAY,EACZ,qBAAqB,EACrB,aAAa,GACd,MAAM,cAAc,CAAC;AAYtB,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"}
@@ -21,6 +21,14 @@ import type { CommentChecker } from './submission.ts';
21
21
  * {@link commentFrom} whether it is being written for the first time or
22
22
  * rebuilt at boot.
23
23
  *
24
+ * **The email is not in the file.** Everything under `content/` is published
25
+ * and goes into git, where a removed line stays in history until somebody
26
+ * rewrites it, so a commenter's `author.email` and the `notify` that only
27
+ * means anything beside it live in `data/comments/{slug}.json` instead (mode
28
+ * `0600`), keyed by comment id. A record read here has both merged back in, and
29
+ * a record written here is split again, so nothing outside this module knows
30
+ * there are two files (TASK-182).
31
+ *
24
32
  * The entry shape is deliberately wider than a form submission. A webmention
25
33
  * (TASK-51) is somebody else's post pointing at this one: it has a `url` and no
26
34
  * email, it may be a like rather than a reply, and it belongs in the same file
@@ -50,6 +58,16 @@ export declare function commentsDirectory(contentDir: string): string;
50
58
  * sanitised to one name would silently share a thread.
51
59
  */
52
60
  export declare function commentsFile(contentDir: string, slug: string): string;
61
+ /** Where commenters' emails live, relative to the data directory. */
62
+ export declare const COMMENT_EMAILS_DIRECTORY = "comments";
63
+ /** Nobody but the site's own user reads a commenter's email. */
64
+ export declare const COMMENT_EMAILS_FILE_MODE = 384;
65
+ /**
66
+ * The absolute path of the private file holding one post's commenters' emails:
67
+ * `data/comments/{slug}.json`, beside the post's own file in `content/` but
68
+ * never published with it.
69
+ */
70
+ export declare function commentEmailsFile(dataDir: string, slug: string): string;
53
71
  /** A {@link CommentRecord} on its way in, before the store has named it. */
54
72
  export type NewComment = Omit<CommentRecord, 'id'> & {
55
73
  /** The post it is on. */
@@ -65,9 +83,11 @@ export interface CommentRecords {
65
83
  readonly admin: AdminStore;
66
84
  /** The content directory the files live under. */
67
85
  readonly contentDir: string;
86
+ /** The data directory the commenters' emails live under. */
87
+ readonly dataDir: string;
68
88
  }
69
89
  /**
70
- * One post's comments, as its file says them, oldest first.
90
+ * One post's comments, as its files say them, oldest first.
71
91
  *
72
92
  * A missing file is no comments, which is what almost every post has. Unlike
73
93
  * `followers.json`, an entry that will not parse is dropped rather than
@@ -76,7 +96,7 @@ export interface CommentRecords {
76
96
  * down on the next boot. Nothing irreplaceable is at stake — a comment that
77
97
  * cannot be read is one nobody could have shown either way.
78
98
  */
79
- export declare function readComments(contentDir: string, slug: string): CommentRecord[];
99
+ export declare function readComments(records: Pick<CommentRecords, 'contentDir' | 'dataDir'>, slug: string): CommentRecord[];
80
100
  /**
81
101
  * Record a comment: append it to its post's file and index it.
82
102
  *
@@ -245,6 +265,21 @@ export declare function updateComment(records: CommentRecords, id: string, chang
245
265
  * edited by hand cannot go on being shown.
246
266
  */
247
267
  export declare function deleteComment(records: CommentRecords, id: string): Promise<boolean>;
268
+ /**
269
+ * Rewrite one post's comments in place: `change` is shown each entry as the
270
+ * file holds it and answers with the entry it should become, or `undefined`
271
+ * to leave it alone.
272
+ *
273
+ * What the retention sweep and an erasure on request are built on (TASK-135).
274
+ * The read, the change and the write happen inside the file's lock, so a
275
+ * comment arriving or a moderator approving one in the same moment is never
276
+ * written over, and the file is only written when something changed, so a
277
+ * sweep that has nothing to do leaves it untouched. The ids of the entries
278
+ * that changed come back, each already put into the index.
279
+ */
280
+ export declare function rewriteComments(records: CommentRecords, slug: string, change: (comment: CommentRecord) => CommentRecord | undefined): Promise<string[]>;
281
+ /** The slug of every post that has a comment file, in a stable order. */
282
+ export declare function commentSlugs(contentDir: string): string[];
248
283
  /** What a rebuild put in the index. */
249
284
  export interface CommentIndexReport {
250
285
  /** How many comments the files held. */
@@ -263,4 +298,25 @@ export interface CommentIndexReport {
263
298
  * synchronous because both callers are.
264
299
  */
265
300
  export declare function rebuildCommentIndexes(records: CommentRecords): CommentIndexReport;
301
+ /** What moving the emails out of `content/` changed. */
302
+ export interface CommentEmailMigrationReport {
303
+ /** How many comment files were rewritten. */
304
+ files: number;
305
+ }
306
+ /**
307
+ * Move every email still in a comment file into `data/` (TASK-182).
308
+ *
309
+ * A site that kept comments before the emails moved has them in
310
+ * `content/_data/comments/`, and a comment file somebody edits by hand may
311
+ * gain one again. Boot calls this before {@link rebuildCommentIndexes}, so
312
+ * both end up in the private file and out of the published one. It edits each
313
+ * file's JSON as it finds it, taking off `author.email` and `notify` and
314
+ * nothing else, so a key this version does not know and an entry it cannot
315
+ * read survive it. An email `data/` already holds for that comment wins. A file
316
+ * with nothing to take off is not written, so a second boot writes nothing.
317
+ *
318
+ * Synchronous, like the other boot migrations, and run before anything else
319
+ * can be writing a comment.
320
+ */
321
+ export declare function migrateCommentEmails(records: Pick<CommentRecords, 'contentDir' | 'dataDir'>): CommentEmailMigrationReport;
266
322
  //# sourceMappingURL=records.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"records.d.ts","sourceRoot":"","sources":["../../src/comments/records.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAiB,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAG/F,OAAO,KAAK,EAAE,cAAc,EAAqC,MAAM,iBAAiB,CAAC;AAEzF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,uEAAuE;AACvE,eAAO,MAAM,uBAAuB,mBAAmB,CAAC;AAExD,gEAAgE;AAChE,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAKrE;AAKD,4EAA4E;AAC5E,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,GAAG;IACnD,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,2EAA2E;IAC3E,SAAS,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACzB,CAAC;AAEF,gFAAgF;AAChF,MAAM,WAAW,cAAc;IAC7B,4CAA4C;IAC5C,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,kDAAkD;IAClD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,aAAa,EAAE,CAK9E;AAyED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,WAAW,CAAC,CAetB;AAED,8EAA8E;AAC9E,MAAM,MAAM,aAAa;AACvB,wDAAwD;AACtD,MAAM;AACR,oEAAoE;GAClE,YAAY;AACd,kDAAkD;GAChD,WAAW,CAAC;AAEhB;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,WAAW,EAAE,IAAI,GAAG,QAAQ,GAAG,aAAa,CAAC,CAAC;AAEjF;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,4CAA4C;IAC5C,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IACpC,sEAAsE;IACtE,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;CACzC;AAED,kEAAkE;AAClE,MAAM,WAAW,oBAAoB;IACnC,6DAA6D;IAC7D,OAAO,EAAE,cAAc,CAAC;IACxB,2BAA2B;IAC3B,MAAM,EAAE,aAAa,CAAC;IACtB,qDAAqD;IACrD,OAAO,EAAE,eAAe,CAAC;IACzB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IAClD,oCAAoC;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IACrC,4DAA4D;IAC5D,OAAO,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IACrC,8EAA8E;IAC9E,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,+EAA+E;IAC/E,MAAM,CAAC,EAAE;QAAE,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,SAAS,CAAC;CACtD;AAED,2CAA2C;AAC3C,MAAM,MAAM,oBAAoB;AAC9B;;;GAGG;AACD;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAAE;AACvF;;;GAGG;GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAAE;AAC3D,sEAAsE;GACpE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA0ChG;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GAAG,IAAI,GACpB,WAAW,GAAG,SAAS,CAMzB;AAoFD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,cAAc,EACvB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC,CAAC,GAC3F,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAiBlC;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAiBzF;AAED,uCAAuC;AACvC,MAAM,WAAW,kBAAkB;IACjC,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,cAAc,GAAG,kBAAkB,CAiBjF"}
1
+ {"version":3,"file":"records.d.ts","sourceRoot":"","sources":["../../src/comments/records.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { randomUUID } from 'node:crypto';
2
- import { readdirSync } from 'node:fs';
2
+ import { readdirSync, rmSync } from 'node:fs';
3
3
  import path from 'node:path';
4
- import { COMMENT_KINDS, COMMENT_SOURCES, COMMENT_STATUSES } from '../admin/store.js';
4
+ import { COMMENT_KINDS, COMMENT_SOURCES, COMMENT_STATUSES, REDACTED_FIELDS, } from '../admin/store.js';
5
5
  import { readFileIfPresentSync, withFileLock, writeFileAtomicallySync } from '../files/atomic.js';
6
6
  import { hashClientAddress } from '../forms/protection.js';
7
7
  /**
@@ -25,6 +25,14 @@ import { hashClientAddress } from '../forms/protection.js';
25
25
  * {@link commentFrom} whether it is being written for the first time or
26
26
  * rebuilt at boot.
27
27
  *
28
+ * **The email is not in the file.** Everything under `content/` is published
29
+ * and goes into git, where a removed line stays in history until somebody
30
+ * rewrites it, so a commenter's `author.email` and the `notify` that only
31
+ * means anything beside it live in `data/comments/{slug}.json` instead (mode
32
+ * `0600`), keyed by comment id. A record read here has both merged back in, and
33
+ * a record written here is split again, so nothing outside this module knows
34
+ * there are two files (TASK-182).
35
+ *
28
36
  * The entry shape is deliberately wider than a form submission. A webmention
29
37
  * (TASK-51) is somebody else's post pointing at this one: it has a `url` and no
30
38
  * email, it may be a like rather than a reply, and it belongs in the same file
@@ -63,8 +71,23 @@ export function commentsFile(contentDir, slug) {
63
71
  }
64
72
  /** Slugs a file may be named after: what {@link slugify} produces, and no more. */
65
73
  const SAFE_SLUG = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
74
+ /** Where commenters' emails live, relative to the data directory. */
75
+ export const COMMENT_EMAILS_DIRECTORY = 'comments';
76
+ /** Nobody but the site's own user reads a commenter's email. */
77
+ export const COMMENT_EMAILS_FILE_MODE = 0o600;
66
78
  /**
67
- * One post's comments, as its file says them, oldest first.
79
+ * The absolute path of the private file holding one post's commenters' emails:
80
+ * `data/comments/{slug}.json`, beside the post's own file in `content/` but
81
+ * never published with it.
82
+ */
83
+ export function commentEmailsFile(dataDir, slug) {
84
+ if (!SAFE_SLUG.test(slug)) {
85
+ throw new Error(`"${slug}" is not a slug a comment file can be named after.`);
86
+ }
87
+ return path.join(dataDir, COMMENT_EMAILS_DIRECTORY, `${slug}.json`);
88
+ }
89
+ /**
90
+ * One post's comments, as its files say them, oldest first.
68
91
  *
69
92
  * A missing file is no comments, which is what almost every post has. Unlike
70
93
  * `followers.json`, an entry that will not parse is dropped rather than
@@ -73,14 +96,90 @@ const SAFE_SLUG = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
73
96
  * down on the next boot. Nothing irreplaceable is at stake — a comment that
74
97
  * cannot be read is one nobody could have shown either way.
75
98
  */
76
- export function readComments(contentDir, slug) {
77
- const source = readFileIfPresentSync(commentsFile(contentDir, slug));
99
+ export function readComments(records, slug) {
100
+ return readPost(records, slug).comments;
101
+ }
102
+ /**
103
+ * One post's comments with their emails merged back in.
104
+ *
105
+ * `data/` wins over `content/`. An email still in a comment file is read too,
106
+ * so a site that has not booted since upgrading loses nothing before
107
+ * {@link migrateCommentEmails} moves it.
108
+ */
109
+ function readPost(records, slug) {
110
+ const held = fileContents(readFileIfPresentSync(commentsFile(records.contentDir, slug)));
111
+ const contacts = contactsIn(readFileIfPresentSync(commentEmailsFile(records.dataDir, slug)));
112
+ return {
113
+ post: held.post,
114
+ comments: held.comments.map((comment) => {
115
+ const contact = contacts.get(comment.id);
116
+ if (contact === undefined)
117
+ return comment;
118
+ return {
119
+ ...comment,
120
+ author: { ...comment.author, email: contact.email },
121
+ notify: contact.notify,
122
+ };
123
+ }),
124
+ };
125
+ }
126
+ /**
127
+ * Write one post's comments: the emails to `data/`, everything else to
128
+ * `content/`. Called inside the lock on the post's comment file, which is the
129
+ * lock on both, because nothing writes the private file but this.
130
+ *
131
+ * `data/` goes first, so a crash between the two writes leaves an email in
132
+ * both places or in `data/` alone, and never in neither.
133
+ */
134
+ function writePost(records, slug, permalink, comments) {
135
+ const contacts = new Map();
136
+ for (const comment of comments) {
137
+ if (comment.author.email !== null) {
138
+ contacts.set(comment.id, { email: comment.author.email, notify: comment.notify });
139
+ }
140
+ }
141
+ const privateFile = commentEmailsFile(records.dataDir, slug);
142
+ if (contacts.size > 0) {
143
+ writeFileAtomicallySync(privateFile, contactsJson(contacts), {
144
+ mode: COMMENT_EMAILS_FILE_MODE,
145
+ });
146
+ }
147
+ else {
148
+ rmSync(privateFile, { force: true });
149
+ }
150
+ writeFileAtomicallySync(commentsFile(records.contentDir, slug), commentsJson(permalink, comments.map(publishedEntryOf)));
151
+ }
152
+ /** The emails a private file holds, by comment id. A damaged file holds none. */
153
+ function contactsIn(source) {
154
+ const contacts = new Map();
78
155
  if (source === undefined)
79
- return [];
80
- return commentsIn(source);
156
+ return contacts;
157
+ let parsed;
158
+ try {
159
+ parsed = JSON.parse(source);
160
+ }
161
+ catch {
162
+ return contacts;
163
+ }
164
+ if (!isRecord(parsed) || !isRecord(parsed['comments']))
165
+ return contacts;
166
+ for (const [id, value] of Object.entries(parsed['comments'])) {
167
+ if (!isRecord(value))
168
+ continue;
169
+ const email = optionalText(value['email']);
170
+ if (email !== null)
171
+ contacts.set(id, { email, notify: value['notify'] === true });
172
+ }
173
+ return contacts;
174
+ }
175
+ /** A private file's contents: indented, newline ended. */
176
+ function contactsJson(contacts) {
177
+ return `${JSON.stringify({ comments: Object.fromEntries(contacts) }, null, 2)}\n`;
81
178
  }
82
179
  /** One post's comment file as the post it names and the comments it holds. */
83
180
  function fileContents(source) {
181
+ if (source === undefined)
182
+ return { post: '', comments: [] };
84
183
  let parsed;
85
184
  try {
86
185
  parsed = JSON.parse(source);
@@ -98,10 +197,6 @@ function fileContents(source) {
98
197
  : [],
99
198
  };
100
199
  }
101
- /** Just the comments, for the readers that have the post already. */
102
- function commentsIn(source) {
103
- return fileContents(source).comments;
104
- }
105
200
  /**
106
201
  * One file entry as the record it is, or `undefined` when it is not one.
107
202
  *
@@ -146,8 +241,16 @@ function commentFrom(value) {
146
241
  // written before TASK-55 shipped, or edited by hand, has nobody waiting on
147
242
  // it, and defaulting the other way would email people who never opted in.
148
243
  notify: value['notify'] === true,
244
+ ...redactedIn(value['redacted']),
149
245
  };
150
246
  }
247
+ /** An entry's `redacted` list, kept only when it names something this version knows. */
248
+ function redactedIn(value) {
249
+ if (!Array.isArray(value))
250
+ return {};
251
+ const fields = REDACTED_FIELDS.filter((field) => value.includes(field));
252
+ return fields.length === 0 ? {} : { redacted: fields };
253
+ }
151
254
  /**
152
255
  * Record a comment: append it to its post's file and index it.
153
256
  *
@@ -156,17 +259,16 @@ function commentFrom(value) {
156
259
  * same content directory can never be given the same name.
157
260
  */
158
261
  export async function addComment(records, comment) {
159
- const { admin, contentDir } = records;
160
- const file = commentsFile(contentDir, comment.slug);
262
+ const file = commentsFile(records.contentDir, comment.slug);
161
263
  const stored = {
162
264
  ...commentRecordOf(comment),
163
265
  slug: comment.slug,
164
266
  permalink: comment.permalink,
165
267
  };
166
268
  return await withFileLock(file, () => {
167
- const held = readCommentFile(file);
168
- writeFileAtomicallySync(file, commentsJson(comment.permalink, [...held, entryOf(stored)]));
169
- admin.putComment(stored);
269
+ const held = readPost(records, comment.slug).comments;
270
+ writePost(records, comment.slug, comment.permalink, [...held, stored]);
271
+ records.admin.putComment(stored);
170
272
  return stored;
171
273
  });
172
274
  }
@@ -349,19 +451,18 @@ function messageOf(error) {
349
451
  * one thing an id alone does not carry.
350
452
  */
351
453
  export async function updateComment(records, id, change) {
352
- const { admin, contentDir } = records;
353
- const known = admin.getComment(id);
454
+ const known = records.admin.getComment(id);
354
455
  if (known === undefined)
355
456
  return undefined;
356
- const file = commentsFile(contentDir, known.slug);
457
+ const file = commentsFile(records.contentDir, known.slug);
357
458
  return await withFileLock(file, () => {
358
- const held = readCommentFile(file);
459
+ const held = readPost(records, known.slug).comments;
359
460
  const at = held.findIndex((entry) => entry.id === id);
360
461
  if (at === -1)
361
462
  return undefined;
362
463
  const moved = { ...known, ...held[at], ...change };
363
- writeFileAtomicallySync(file, commentsJson(known.permalink, held.with(at, entryOf(moved))));
364
- admin.putComment(moved);
464
+ writePost(records, known.slug, known.permalink, held.with(at, moved));
465
+ records.admin.putComment(moved);
365
466
  return moved;
366
467
  });
367
468
  }
@@ -373,21 +474,55 @@ export async function updateComment(records, id, change) {
373
474
  * edited by hand cannot go on being shown.
374
475
  */
375
476
  export async function deleteComment(records, id) {
376
- const { admin, contentDir } = records;
377
- const known = admin.getComment(id);
477
+ const known = records.admin.getComment(id);
378
478
  if (known === undefined)
379
479
  return false;
380
- const file = commentsFile(contentDir, known.slug);
480
+ const file = commentsFile(records.contentDir, known.slug);
381
481
  return await withFileLock(file, () => {
382
- const held = readCommentFile(file);
482
+ const held = readPost(records, known.slug).comments;
383
483
  const next = held.filter((entry) => entry.id !== id);
384
- if (next.length !== held.length) {
385
- writeFileAtomicallySync(file, commentsJson(known.permalink, next));
386
- }
387
- const indexed = admin.deleteComment(id);
484
+ if (next.length !== held.length)
485
+ writePost(records, known.slug, known.permalink, next);
486
+ const indexed = records.admin.deleteComment(id);
388
487
  return next.length !== held.length || indexed;
389
488
  });
390
489
  }
490
+ /**
491
+ * Rewrite one post's comments in place: `change` is shown each entry as the
492
+ * file holds it and answers with the entry it should become, or `undefined`
493
+ * to leave it alone.
494
+ *
495
+ * What the retention sweep and an erasure on request are built on (TASK-135).
496
+ * The read, the change and the write happen inside the file's lock, so a
497
+ * comment arriving or a moderator approving one in the same moment is never
498
+ * written over, and the file is only written when something changed, so a
499
+ * sweep that has nothing to do leaves it untouched. The ids of the entries
500
+ * that changed come back, each already put into the index.
501
+ */
502
+ export async function rewriteComments(records, slug, change) {
503
+ const file = commentsFile(records.contentDir, slug);
504
+ return await withFileLock(file, () => {
505
+ const held = readPost(records, slug);
506
+ const changed = [];
507
+ const next = held.comments.map((entry) => {
508
+ const moved = change(entry);
509
+ if (moved === undefined)
510
+ return entry;
511
+ changed.push({ ...moved, slug, permalink: held.post });
512
+ return moved;
513
+ });
514
+ if (changed.length === 0)
515
+ return [];
516
+ writePost(records, slug, held.post, next);
517
+ for (const comment of changed)
518
+ records.admin.putComment(comment);
519
+ return changed.map((comment) => comment.id);
520
+ });
521
+ }
522
+ /** The slug of every post that has a comment file, in a stable order. */
523
+ export function commentSlugs(contentDir) {
524
+ return commentFiles(contentDir).map((file) => path.basename(file, '.json'));
525
+ }
391
526
  /**
392
527
  * Rebuild the comment index from the files.
393
528
  *
@@ -401,21 +536,84 @@ export async function deleteComment(records, id) {
401
536
  * synchronous because both callers are.
402
537
  */
403
538
  export function rebuildCommentIndexes(records) {
404
- const { admin, contentDir } = records;
405
539
  const comments = [];
406
- for (const file of commentFiles(contentDir)) {
407
- const source = readFileIfPresentSync(file);
408
- if (source === undefined)
409
- continue;
410
- const slug = path.basename(file, '.json');
411
- const held = fileContents(source);
540
+ for (const slug of commentSlugs(records.contentDir)) {
541
+ const held = readPost(records, slug);
412
542
  for (const entry of held.comments) {
413
543
  comments.push({ ...entry, slug, permalink: held.post });
414
544
  }
415
545
  }
416
- admin.replaceComments(comments);
546
+ records.admin.replaceComments(comments);
417
547
  return { comments: comments.length };
418
548
  }
549
+ /**
550
+ * Move every email still in a comment file into `data/` (TASK-182).
551
+ *
552
+ * A site that kept comments before the emails moved has them in
553
+ * `content/_data/comments/`, and a comment file somebody edits by hand may
554
+ * gain one again. Boot calls this before {@link rebuildCommentIndexes}, so
555
+ * both end up in the private file and out of the published one. It edits each
556
+ * file's JSON as it finds it, taking off `author.email` and `notify` and
557
+ * nothing else, so a key this version does not know and an entry it cannot
558
+ * read survive it. An email `data/` already holds for that comment wins. A file
559
+ * with nothing to take off is not written, so a second boot writes nothing.
560
+ *
561
+ * Synchronous, like the other boot migrations, and run before anything else
562
+ * can be writing a comment.
563
+ */
564
+ export function migrateCommentEmails(records) {
565
+ let files = 0;
566
+ for (const slug of commentSlugs(records.contentDir)) {
567
+ const file = commentsFile(records.contentDir, slug);
568
+ let parsed;
569
+ try {
570
+ parsed = JSON.parse(readFileIfPresentSync(file) ?? '');
571
+ }
572
+ catch {
573
+ continue;
574
+ }
575
+ if (!isRecord(parsed) || !Array.isArray(parsed['comments']))
576
+ continue;
577
+ const found = new Map();
578
+ let stripped = false;
579
+ const entries = parsed['comments'].map((entry) => {
580
+ if (!isRecord(entry))
581
+ return entry;
582
+ const author = isRecord(entry['author']) ? entry['author'] : undefined;
583
+ if (!('notify' in entry) && !(author !== undefined && 'email' in author))
584
+ return entry;
585
+ stripped = true;
586
+ const email = optionalText(author?.['email']);
587
+ const id = entry['id'];
588
+ if (typeof id === 'string' && id !== '' && email !== null) {
589
+ found.set(id, { email, notify: entry['notify'] === true });
590
+ }
591
+ const kept = without(entry, 'notify');
592
+ if (author !== undefined)
593
+ kept['author'] = without(author, 'email');
594
+ return kept;
595
+ });
596
+ if (!stripped)
597
+ continue;
598
+ const privateFile = commentEmailsFile(records.dataDir, slug);
599
+ const contacts = contactsIn(readFileIfPresentSync(privateFile));
600
+ for (const [id, contact] of found)
601
+ if (!contacts.has(id))
602
+ contacts.set(id, contact);
603
+ if (contacts.size > 0) {
604
+ writeFileAtomicallySync(privateFile, contactsJson(contacts), {
605
+ mode: COMMENT_EMAILS_FILE_MODE,
606
+ });
607
+ }
608
+ writeFileAtomicallySync(file, `${JSON.stringify({ ...parsed, comments: entries }, null, 2)}\n`);
609
+ files += 1;
610
+ }
611
+ return { files };
612
+ }
613
+ /** A copy of a record without one key, every other key where it was. */
614
+ function without(record, key) {
615
+ return Object.fromEntries(Object.entries(record).filter(([name]) => name !== key));
616
+ }
419
617
  /** Every comment file a site has, in a stable order. */
420
618
  function commentFiles(contentDir) {
421
619
  let entries;
@@ -432,11 +630,6 @@ function commentFiles(contentDir) {
432
630
  .sort()
433
631
  .map((name) => path.join(commentsDirectory(contentDir), name));
434
632
  }
435
- /** One file's comments, read inside a lock the caller already holds. */
436
- function readCommentFile(file) {
437
- const source = readFileIfPresentSync(file);
438
- return source === undefined ? [] : commentsIn(source);
439
- }
440
633
  /** A new comment as the record it becomes, id and all. */
441
634
  function commentRecordOf(comment) {
442
635
  return {
@@ -451,22 +644,26 @@ function commentRecordOf(comment) {
451
644
  inReplyTo: comment.inReplyTo,
452
645
  url: comment.url,
453
646
  notify: comment.notify,
647
+ ...(comment.redacted === undefined ? {} : { redacted: [...comment.redacted] }),
454
648
  };
455
649
  }
456
- /** A row as the file spells it: the post it is on is the file's, not the entry's. */
457
- function entryOf(comment) {
650
+ /**
651
+ * A row as `content/` spells it: the post it is on is the file's, not the
652
+ * entry's, and the email and `notify` are `data/`'s.
653
+ */
654
+ function publishedEntryOf(comment) {
458
655
  return {
459
656
  id: comment.id,
460
657
  source: comment.source,
461
658
  kind: comment.kind,
462
659
  status: comment.status,
463
- author: { ...comment.author },
660
+ author: { name: comment.author.name, url: comment.author.url, avatar: comment.author.avatar },
464
661
  content: { ...comment.content },
465
662
  submitted: comment.submitted,
466
663
  addressHash: comment.addressHash,
467
664
  inReplyTo: comment.inReplyTo,
468
665
  url: comment.url,
469
- notify: comment.notify,
666
+ ...(comment.redacted === undefined ? {} : { redacted: [...comment.redacted] }),
470
667
  };
471
668
  }
472
669
  /** One post's comments as the file spells them: indented, newline ended. */
@@ -1 +1 @@
1
- {"version":3,"file":"records.js","sourceRoot":"","sources":["../../src/comments/records.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"records.js","sourceRoot":"","sources":["../../src/comments/records.ts"],"names":[],"mappings":"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"}
@@ -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;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"}
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,CAsHzD;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"}
@@ -1,4 +1,4 @@
1
- import { csrfTokenMatches } from '../admin/session.js';
1
+ import { CROSS_SITE_REFUSAL, crossSiteWrite, csrfTokenMatches } from '../admin/session.js';
2
2
  import { clientAddress, createLoginThrottle } from '../admin/throttle.js';
3
3
  import { isPublicDocument } from '../web/documents.js';
4
4
  import { PRIVATE_CACHE_CONTROL } from '../web/negotiate.js';
@@ -48,6 +48,12 @@ export function mountComments(app) {
48
48
  // matching token a page on another site could make them say something they
49
49
  // never typed. Refused in the words and with the status the admin guard
50
50
  // uses, because it is the same check on the same token.
51
+ //
52
+ // Fetch Metadata first, as in the admin: a browser that says the form was
53
+ // on another site is refused whatever token it carries. A stranger's form
54
+ // is left alone, because it acts on nobody's behalf.
55
+ if (viewer !== undefined && crossSiteWrite(c))
56
+ return c.text(CROSS_SITE_REFUSAL, 403);
51
57
  if (viewer !== undefined && !csrfTokenMatches(viewer.csrfToken, form.csrf)) {
52
58
  return c.text('That form was stale or came from somewhere else. Reload and try again.', 403);
53
59
  }
@@ -66,7 +72,7 @@ export function mountComments(app) {
66
72
  });
67
73
  }
68
74
  const outcome = await submitComment({
69
- records: { admin, contentDir: config.contentDir },
75
+ records: { admin, contentDir: config.contentDir, dataDir: config.dataDir },
70
76
  document,
71
77
  form,
72
78
  dataDir: config.dataDir,