@atproto/ozone 0.1.155 → 0.1.157

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 (90) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/api/moderation/emitEvent.d.ts.map +1 -1
  3. package/dist/api/moderation/emitEvent.js +20 -7
  4. package/dist/api/moderation/emitEvent.js.map +1 -1
  5. package/dist/api/util.d.ts +1 -1
  6. package/dist/api/util.d.ts.map +1 -1
  7. package/dist/api/util.js +6 -1
  8. package/dist/api/util.js.map +1 -1
  9. package/dist/daemon/event-pusher.d.ts +1 -1
  10. package/dist/daemon/event-pusher.d.ts.map +1 -1
  11. package/dist/daemon/event-pusher.js +17 -5
  12. package/dist/daemon/event-pusher.js.map +1 -1
  13. package/dist/daemon/scheduled-action-processor.d.ts +5 -1
  14. package/dist/daemon/scheduled-action-processor.d.ts.map +1 -1
  15. package/dist/daemon/scheduled-action-processor.js +44 -2
  16. package/dist/daemon/scheduled-action-processor.js.map +1 -1
  17. package/dist/jetstream/service.d.ts +1 -1
  18. package/dist/jetstream/service.d.ts.map +1 -1
  19. package/dist/jetstream/service.js +2 -2
  20. package/dist/jetstream/service.js.map +1 -1
  21. package/dist/lexicon/index.d.ts +11 -0
  22. package/dist/lexicon/index.d.ts.map +1 -1
  23. package/dist/lexicon/index.js +32 -1
  24. package/dist/lexicon/index.js.map +1 -1
  25. package/dist/lexicon/lexicons.d.ts +806 -6
  26. package/dist/lexicon/lexicons.d.ts.map +1 -1
  27. package/dist/lexicon/lexicons.js +425 -3
  28. package/dist/lexicon/lexicons.js.map +1 -1
  29. package/dist/lexicon/types/app/bsky/ageassurance/begin.d.ts +31 -0
  30. package/dist/lexicon/types/app/bsky/ageassurance/begin.d.ts.map +1 -0
  31. package/dist/lexicon/types/app/bsky/ageassurance/begin.js +7 -0
  32. package/dist/lexicon/types/app/bsky/ageassurance/begin.js.map +1 -0
  33. package/dist/lexicon/types/app/bsky/ageassurance/defs.d.ts +138 -0
  34. package/dist/lexicon/types/app/bsky/ageassurance/defs.d.ts.map +1 -0
  35. package/dist/lexicon/types/app/bsky/ageassurance/defs.js +115 -0
  36. package/dist/lexicon/types/app/bsky/ageassurance/defs.js.map +1 -0
  37. package/dist/lexicon/types/app/bsky/ageassurance/getConfig.d.ts +18 -0
  38. package/dist/lexicon/types/app/bsky/ageassurance/getConfig.d.ts.map +1 -0
  39. package/dist/lexicon/types/app/bsky/ageassurance/getConfig.js +7 -0
  40. package/dist/lexicon/types/app/bsky/ageassurance/getConfig.js.map +1 -0
  41. package/dist/lexicon/types/app/bsky/ageassurance/getState.d.ts +24 -0
  42. package/dist/lexicon/types/app/bsky/ageassurance/getState.d.ts.map +1 -0
  43. package/dist/lexicon/types/app/bsky/ageassurance/getState.js +7 -0
  44. package/dist/lexicon/types/app/bsky/ageassurance/getState.js.map +1 -0
  45. package/dist/lexicon/types/tools/ozone/moderation/defs.d.ts +13 -2
  46. package/dist/lexicon/types/tools/ozone/moderation/defs.d.ts.map +1 -1
  47. package/dist/lexicon/types/tools/ozone/moderation/defs.js.map +1 -1
  48. package/dist/lexicon/types/tools/ozone/moderation/queryStatuses.d.ts +1 -1
  49. package/dist/lexicon/types/tools/ozone/moderation/queryStatuses.d.ts.map +1 -1
  50. package/dist/lexicon/types/tools/ozone/moderation/queryStatuses.js.map +1 -1
  51. package/dist/lexicon/types/tools/ozone/moderation/scheduleAction.d.ts +10 -0
  52. package/dist/lexicon/types/tools/ozone/moderation/scheduleAction.d.ts.map +1 -1
  53. package/dist/lexicon/types/tools/ozone/moderation/scheduleAction.js.map +1 -1
  54. package/dist/mod-service/index.d.ts +3 -3
  55. package/dist/mod-service/index.d.ts.map +1 -1
  56. package/dist/mod-service/index.js +10 -4
  57. package/dist/mod-service/index.js.map +1 -1
  58. package/dist/mod-service/status.d.ts +1 -1
  59. package/dist/mod-service/util.d.ts.map +1 -1
  60. package/dist/mod-service/util.js +1 -0
  61. package/dist/mod-service/util.js.map +1 -1
  62. package/dist/mod-service/views.d.ts.map +1 -1
  63. package/dist/mod-service/views.js +7 -0
  64. package/dist/mod-service/views.js.map +1 -1
  65. package/dist/setting/validators.d.ts.map +1 -1
  66. package/dist/setting/validators.js +10 -0
  67. package/dist/setting/validators.js.map +1 -1
  68. package/package.json +10 -9
  69. package/src/api/moderation/emitEvent.ts +34 -9
  70. package/src/api/util.ts +7 -1
  71. package/src/daemon/event-pusher.ts +22 -5
  72. package/src/daemon/scheduled-action-processor.ts +59 -1
  73. package/src/jetstream/service.ts +1 -1
  74. package/src/lexicon/index.ts +49 -0
  75. package/src/lexicon/lexicons.ts +458 -3
  76. package/src/lexicon/types/app/bsky/ageassurance/begin.ts +54 -0
  77. package/src/lexicon/types/app/bsky/ageassurance/defs.ts +301 -0
  78. package/src/lexicon/types/app/bsky/ageassurance/getConfig.ts +34 -0
  79. package/src/lexicon/types/app/bsky/ageassurance/getState.ts +42 -0
  80. package/src/lexicon/types/tools/ozone/moderation/defs.ts +13 -2
  81. package/src/lexicon/types/tools/ozone/moderation/queryStatuses.ts +6 -1
  82. package/src/lexicon/types/tools/ozone/moderation/scheduleAction.ts +10 -0
  83. package/src/mod-service/index.ts +21 -7
  84. package/src/mod-service/util.ts +2 -0
  85. package/src/mod-service/views.ts +10 -0
  86. package/src/setting/validators.ts +15 -0
  87. package/tests/query-labels.test.ts +4 -1
  88. package/tests/scheduled-action-processor.test.ts +30 -6
  89. package/tests/takedown.test.ts +43 -1
  90. package/tsconfig.build.tsbuildinfo +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,32 @@
1
1
  # @atproto/ozone
2
2
 
3
+ ## 0.1.157
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [[`261968fd6`](https://github.com/bluesky-social/atproto/commit/261968fd65014ded613e2bf085d61a7864b8fba7), [`261968fd6`](https://github.com/bluesky-social/atproto/commit/261968fd65014ded613e2bf085d61a7864b8fba7), [`261968fd6`](https://github.com/bluesky-social/atproto/commit/261968fd65014ded613e2bf085d61a7864b8fba7), [`261968fd6`](https://github.com/bluesky-social/atproto/commit/261968fd65014ded613e2bf085d61a7864b8fba7), [`261968fd6`](https://github.com/bluesky-social/atproto/commit/261968fd65014ded613e2bf085d61a7864b8fba7)]:
8
+ - @atproto/xrpc-server@0.10.0
9
+ - @atproto/common@0.5.0
10
+ - @atproto/api@0.18.2
11
+ - @atproto/identity@0.4.10
12
+ - @atproto/lexicon@0.5.2
13
+ - @atproto/crypto@0.4.4
14
+ - @atproto/ws-client@0.0.3
15
+ - @atproto/xrpc@0.7.6
16
+
17
+ ## 0.1.156
18
+
19
+ ### Patch Changes
20
+
21
+ - [#4340](https://github.com/bluesky-social/atproto/pull/4340) [`032abf6b5`](https://github.com/bluesky-social/atproto/commit/032abf6b500fd36f3c0fc1af83bf62caae44fa6e) Thanks [@foysalit](https://github.com/foysalit)! - Add optional email data to scheduled action api in ozone
22
+
23
+ - [#4344](https://github.com/bluesky-social/atproto/pull/4344) [`9115325c7`](https://github.com/bluesky-social/atproto/commit/9115325c7b36f0293f87f79bb8edb49f72fec2bc) Thanks [@foysalit](https://github.com/foysalit)! - Add targetServices param to takedown events allowing mods to specify which service to apply takedown on
24
+
25
+ - Updated dependencies [[`032abf6b5`](https://github.com/bluesky-social/atproto/commit/032abf6b500fd36f3c0fc1af83bf62caae44fa6e), [`9115325c7`](https://github.com/bluesky-social/atproto/commit/9115325c7b36f0293f87f79bb8edb49f72fec2bc), [`1dd20d3a8`](https://github.com/bluesky-social/atproto/commit/1dd20d3a81cda29392d8d63d13082254ec5f68a8)]:
26
+ - @atproto/api@0.18.1
27
+ - @atproto/xrpc-server@0.9.6
28
+ - @atproto/ws-client@0.0.2
29
+
3
30
  ## 0.1.155
4
31
 
5
32
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"emitEvent.d.ts","sourceRoot":"","sources":["../../../src/api/moderation/emitEvent.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AA4RtC,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,QAqCvD"}
1
+ {"version":3,"file":"emitEvent.d.ts","sourceRoot":"","sources":["../../../src/api/moderation/emitEvent.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAqTtC,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,QAqCvD"}
@@ -5,6 +5,7 @@ const defs_1 = require("@atproto/api/dist/client/types/tools/ozone/moderation/de
5
5
  const xrpc_server_1 = require("@atproto/xrpc-server");
6
6
  const lexicons_1 = require("../../lexicon/lexicons");
7
7
  const defs_2 = require("../../lexicon/types/tools/ozone/moderation/defs");
8
+ const logger_1 = require("../../logger");
8
9
  const subject_1 = require("../../mod-service/subject");
9
10
  const tag_service_1 = require("../../tag-service");
10
11
  const util_1 = require("../../tag-service/util");
@@ -103,11 +104,19 @@ const handleModerationEvent = async ({ ctx, input, auth, }) => {
103
104
  throw new xrpc_server_1.InvalidRequestError('Email can only be sent to a repo subject');
104
105
  }
105
106
  const { content, subjectLine } = event;
106
- await (0, util_2.retryHttp)(() => ctx.modService(db).sendEmail({
107
- subject: subjectLine,
108
- content,
109
- recipientDid: subject.did,
110
- }));
107
+ // on error, don't fail the whole event. instead, log the event data with isDelivered false
108
+ try {
109
+ await (0, util_2.retryHttp)(() => ctx.modService(db).sendEmail({
110
+ subject: subjectLine,
111
+ content,
112
+ recipientDid: subject.did,
113
+ }));
114
+ event.isDelivered = true;
115
+ }
116
+ catch (err) {
117
+ event.isDelivered = false;
118
+ logger_1.httpLogger.error({ err, event }, 'failed to send mod event email');
119
+ }
111
120
  }
112
121
  if ((0, defs_1.isModEventDivert)(event) && subject.isRecord()) {
113
122
  if (!ctx.blobDiverter) {
@@ -148,7 +157,9 @@ const handleModerationEvent = async ({ ctx, input, auth, }) => {
148
157
  if (subject.isRepo()) {
149
158
  if (isTakedownEvent) {
150
159
  const isSuspend = !!result.event.durationInHours;
151
- await moderationTxn.takedownRepo(subject, result.event.id, isSuspend);
160
+ await moderationTxn.takedownRepo(subject, result.event.id, new Set(result.event.meta?.targetServices
161
+ ? `${result.event.meta.targetServices}`.split(',')
162
+ : undefined), isSuspend);
152
163
  }
153
164
  else if (isReverseTakedownEvent) {
154
165
  await moderationTxn.reverseTakedownRepo(subject);
@@ -156,7 +167,9 @@ const handleModerationEvent = async ({ ctx, input, auth, }) => {
156
167
  }
157
168
  if (subject.isRecord()) {
158
169
  if (isTakedownEvent) {
159
- await moderationTxn.takedownRecord(subject, result.event.id);
170
+ await moderationTxn.takedownRecord(subject, result.event.id, new Set(result.event.meta?.targetServices
171
+ ? `${result.event.meta.targetServices}`.split(',')
172
+ : undefined));
160
173
  }
161
174
  else if (isReverseTakedownEvent) {
162
175
  await moderationTxn.reverseTakedownRecord(subject);
@@ -1 +1 @@
1
- {"version":3,"file":"emitEvent.js","sourceRoot":"","sources":["../../../src/api/moderation/emitEvent.ts"],"names":[],"mappings":"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","sourcesContent":["import { isModEventDivert } from '@atproto/api/dist/client/types/tools/ozone/moderation/defs'\nimport { AuthRequiredError, InvalidRequestError } from '@atproto/xrpc-server'\nimport { AdminTokenOutput, ModeratorOutput } from '../../auth-verifier'\nimport { AppContext } from '../../context'\nimport { Server } from '../../lexicon'\nimport { ids } from '../../lexicon/lexicons'\nimport {\n ModEventTag,\n isAgeAssuranceEvent,\n isAgeAssuranceOverrideEvent,\n isModEventAcknowledge,\n isModEventEmail,\n isModEventLabel,\n isModEventMuteReporter,\n isModEventReport,\n isModEventReverseTakedown,\n isModEventTag,\n isModEventTakedown,\n isModEventUnmuteReporter,\n isRevokeAccountCredentialsEvent,\n} from '../../lexicon/types/tools/ozone/moderation/defs'\nimport { HandlerInput } from '../../lexicon/types/tools/ozone/moderation/emitEvent'\nimport { subjectFromInput } from '../../mod-service/subject'\nimport { SettingService } from '../../setting/service'\nimport { TagService } from '../../tag-service'\nimport { getTagForReport } from '../../tag-service/util'\nimport { retryHttp } from '../../util'\nimport { getEventType } from '../util'\nimport { assertProtectedTagAction, getProtectedTags } from './util'\n\nconst handleModerationEvent = async ({\n ctx,\n input,\n auth,\n}: {\n ctx: AppContext\n input: HandlerInput\n auth: ModeratorOutput | AdminTokenOutput\n}) => {\n const access = auth.credentials\n const createdBy =\n auth.credentials.type === 'moderator'\n ? auth.credentials.iss\n : input.body.createdBy\n const db = ctx.db\n const moderationService = ctx.modService(db)\n const settingService = ctx.settingService(db)\n const { event, externalId } = input.body\n const isAcknowledgeEvent = isModEventAcknowledge(event)\n const isTakedownEvent = isModEventTakedown(event)\n const isReverseTakedownEvent = isModEventReverseTakedown(event)\n const isLabelEvent = isModEventLabel(event)\n const subject = subjectFromInput(\n input.body.subject,\n input.body.subjectBlobCids,\n )\n\n if (isAgeAssuranceEvent(event) && !subject.isRepo()) {\n throw new InvalidRequestError('Invalid subject type')\n }\n\n if (isAgeAssuranceOverrideEvent(event)) {\n if (!subject.isRepo()) {\n throw new InvalidRequestError('Invalid subject type')\n }\n if (!auth.credentials.isModerator) {\n throw new AuthRequiredError(\n 'Must be a full moderator to override age assurance',\n )\n }\n }\n\n if (isRevokeAccountCredentialsEvent(event)) {\n if (!subject.isRepo()) {\n throw new InvalidRequestError('Invalid subject type')\n }\n\n if (!auth.credentials.isAdmin) {\n throw new AuthRequiredError(\n 'Must be an admin to revoke account credentials',\n )\n }\n\n if (!ctx.pdsAgent) {\n throw new InvalidRequestError('PDS not configured')\n }\n\n await ctx.pdsAgent.com.atproto.temp.revokeAccountCredentials(\n { account: subject.did },\n await ctx.pdsAuth(ids.ComAtprotoTempRevokeAccountCredentials),\n )\n }\n\n // if less than moderator access then can only take ack and escalation actions\n if (isTakedownEvent || isReverseTakedownEvent) {\n if (!access.isModerator) {\n throw new AuthRequiredError(\n 'Must be a full moderator to take this type of action',\n )\n }\n\n // Non admins should not be able to take down feed generators\n if (\n !access.isAdmin &&\n subject.recordPath?.includes('app.bsky.feed.generator/')\n ) {\n throw new AuthRequiredError(\n 'Must be a full admin to take this type of action on feed generators',\n )\n }\n }\n // if less than moderator access then can not apply labels\n if (!access.isModerator && isLabelEvent) {\n throw new AuthRequiredError('Must be a full moderator to label content')\n }\n\n if (isLabelEvent) {\n validateLabels([\n ...(event.createLabelVals ?? []),\n ...(event.negateLabelVals ?? []),\n ])\n }\n\n const isTakedownOrReverseTakedownEvent =\n isTakedownEvent || isReverseTakedownEvent\n if (isTakedownOrReverseTakedownEvent || isLabelEvent) {\n const status = await moderationService.getStatus(subject)\n\n if (status?.takendown && isTakedownEvent) {\n throw new InvalidRequestError(`Subject is already taken down`)\n }\n\n if (!status?.takendown && isReverseTakedownEvent) {\n throw new InvalidRequestError(`Subject is not taken down`)\n }\n\n if (status?.tags?.length) {\n const protectedTags = await getProtectedTags(\n settingService,\n ctx.cfg.service.did,\n )\n\n if (protectedTags) {\n assertProtectedTagAction({\n protectedTags,\n subjectTags: status.tags,\n actionAuthor: createdBy,\n isAdmin: auth.credentials.isAdmin,\n isModerator: auth.credentials.isModerator,\n isTriage: auth.credentials.isTriage,\n })\n }\n }\n\n if (status?.takendown && isReverseTakedownEvent && subject.isRecord()) {\n // due to the way blob status is modeled, we should reverse takedown on all\n // blobs for the record being restored, which aren't taken down on another record.\n subject.blobCids = status.blobCids ?? []\n }\n }\n\n if (isModEventEmail(event) && event.content) {\n // sending email prior to logging the event to avoid a long transaction below\n if (!subject.isRepo()) {\n throw new InvalidRequestError('Email can only be sent to a repo subject')\n }\n const { content, subjectLine } = event\n await retryHttp(() =>\n ctx.modService(db).sendEmail({\n subject: subjectLine,\n content,\n recipientDid: subject.did,\n }),\n )\n }\n\n if (isModEventDivert(event) && subject.isRecord()) {\n if (!ctx.blobDiverter) {\n throw new InvalidRequestError(\n 'BlobDiverter not configured for this service',\n )\n }\n await ctx.blobDiverter.uploadBlobOnService(subject.info())\n }\n\n if (\n (isModEventMuteReporter(event) || isModEventUnmuteReporter(event)) &&\n !subject.isRepo()\n ) {\n throw new InvalidRequestError('Subject must be a repo when muting reporter')\n }\n\n if (isModEventTag(event)) {\n await assertTagAuth(settingService, ctx.cfg.service.did, event, auth)\n }\n\n if (isModEventReport(event)) {\n await ctx.moderationServiceProfile().validateReasonType(event.reportType)\n }\n\n const moderationEvent = await db.transaction(async (dbTxn) => {\n const moderationTxn = ctx.modService(dbTxn)\n\n if (externalId) {\n const existingEvent = await moderationTxn.getEventByExternalId(\n getEventType(event.$type),\n externalId,\n subject,\n )\n\n if (existingEvent) {\n throw new InvalidRequestError(\n `An event with the same external ID already exists for the subject.`,\n 'DuplicateExternalId',\n )\n }\n }\n\n const result = await moderationTxn.logEvent({\n event,\n subject,\n createdBy,\n modTool: input.body.modTool,\n externalId,\n })\n\n const tagService = new TagService(\n subject,\n result.subjectStatus,\n ctx.cfg.service.did,\n moderationTxn,\n )\n\n const initialTags = isModEventReport(event)\n ? [getTagForReport(event.reportType)]\n : undefined\n await tagService.evaluateForSubject(initialTags)\n\n if (subject.isRepo()) {\n if (isTakedownEvent) {\n const isSuspend = !!result.event.durationInHours\n await moderationTxn.takedownRepo(subject, result.event.id, isSuspend)\n } else if (isReverseTakedownEvent) {\n await moderationTxn.reverseTakedownRepo(subject)\n }\n }\n\n if (subject.isRecord()) {\n if (isTakedownEvent) {\n await moderationTxn.takedownRecord(subject, result.event.id)\n } else if (isReverseTakedownEvent) {\n await moderationTxn.reverseTakedownRecord(subject)\n }\n }\n\n if (\n (isTakedownEvent || isAcknowledgeEvent) &&\n result.event.meta?.acknowledgeAccountSubjects\n ) {\n await moderationTxn.resolveSubjectsForAccount(\n subject.did,\n createdBy,\n result.event,\n )\n }\n\n if (isLabelEvent) {\n await moderationTxn.formatAndCreateLabels(\n result.event.subjectUri ?? result.event.subjectDid,\n result.event.subjectCid,\n {\n create: result.event.createLabelVals?.length\n ? result.event.createLabelVals.split(' ')\n : undefined,\n negate: result.event.negateLabelVals?.length\n ? result.event.negateLabelVals.split(' ')\n : undefined,\n },\n result.event.durationInHours ?? undefined,\n )\n }\n\n return result.event\n })\n\n return moderationService.views.formatEvent(moderationEvent)\n}\n\nexport default function (server: Server, ctx: AppContext) {\n server.tools.ozone.moderation.emitEvent({\n auth: ctx.authVerifier.modOrAdminToken,\n handler: async ({ input, auth }) => {\n const moderationEvent = await handleModerationEvent({\n input,\n auth,\n ctx,\n })\n\n // On divert events, we need to automatically take down the blobs\n if (isModEventDivert(input.body.event)) {\n await handleModerationEvent({\n auth,\n ctx,\n input: {\n ...input,\n body: {\n ...input.body,\n event: {\n ...input.body.event,\n $type: 'tools.ozone.moderation.defs#modEventTakedown',\n comment:\n '[DIVERT_SIDE_EFFECT]: Automatically taking down after divert event',\n },\n modTool: input.body.modTool,\n },\n },\n })\n }\n\n return {\n encoding: 'application/json',\n body: moderationEvent,\n }\n },\n })\n}\n\nconst assertTagAuth = async (\n settingService: SettingService,\n serviceDid: string,\n event: ModEventTag,\n auth: ModeratorOutput | AdminTokenOutput,\n) => {\n // admins can add/remove any tag\n if (auth.credentials.isAdmin) return\n\n const protectedTags = await getProtectedTags(settingService, serviceDid)\n\n if (!protectedTags) {\n return\n }\n\n for (const tag of Object.keys(protectedTags)) {\n if (event.add.includes(tag) || event.remove.includes(tag)) {\n // if specific moderators are configured to manage this tag but the current user\n // is not one of them, then throw an error\n const configuredModerators = protectedTags[tag]?.['moderators']\n if (\n configuredModerators &&\n !configuredModerators.includes(auth.credentials.iss)\n ) {\n throw new InvalidRequestError(`Not allowed to manage tag: ${tag}`)\n }\n\n const configuredRoles = protectedTags[tag]?.['roles']\n if (configuredRoles) {\n // admins can already do everything so we only check for moderator and triage role config\n if (\n auth.credentials.isModerator &&\n !configuredRoles.includes('tools.ozone.team.defs#roleModerator')\n ) {\n throw new InvalidRequestError(\n `Can not manage tag ${tag} with moderator role`,\n )\n } else if (\n auth.credentials.isTriage &&\n !configuredRoles.includes('tools.ozone.team.defs#roleTriage')\n ) {\n throw new InvalidRequestError(\n `Can not manage tag ${tag} with triage role`,\n )\n }\n }\n }\n }\n}\n\nconst validateLabels = (labels: string[]) => {\n for (const label of labels) {\n for (const char of badChars) {\n if (label.includes(char)) {\n throw new InvalidRequestError(`Invalid label: ${label}`)\n }\n }\n }\n}\n\nconst badChars = [' ', ',', ';', `'`, `\"`]\n"]}
1
+ {"version":3,"file":"emitEvent.js","sourceRoot":"","sources":["../../../src/api/moderation/emitEvent.ts"],"names":[],"mappings":";;AAyTA,4BAqCC;AA9VD,qFAA6F;AAC7F,sDAA6E;AAI7E,qDAA4C;AAC5C,0EAcwD;AAExD,yCAAyC;AACzC,uDAA4D;AAE5D,mDAA8C;AAC9C,iDAAwD;AACxD,qCAAsC;AACtC,kCAAsC;AACtC,iCAAmE;AAEnE,MAAM,qBAAqB,GAAG,KAAK,EAAE,EACnC,GAAG,EACH,KAAK,EACL,IAAI,GAKL,EAAE,EAAE;IACH,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAA;IAC/B,MAAM,SAAS,GACb,IAAI,CAAC,WAAW,CAAC,IAAI,KAAK,WAAW;QACnC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG;QACtB,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAA;IAC1B,MAAM,EAAE,GAAG,GAAG,CAAC,EAAE,CAAA;IACjB,MAAM,iBAAiB,GAAG,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAA;IAC5C,MAAM,cAAc,GAAG,GAAG,CAAC,cAAc,CAAC,EAAE,CAAC,CAAA;IAC7C,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC,IAAI,CAAA;IACxC,MAAM,kBAAkB,GAAG,IAAA,4BAAqB,EAAC,KAAK,CAAC,CAAA;IACvD,MAAM,eAAe,GAAG,IAAA,yBAAkB,EAAC,KAAK,CAAC,CAAA;IACjD,MAAM,sBAAsB,GAAG,IAAA,gCAAyB,EAAC,KAAK,CAAC,CAAA;IAC/D,MAAM,YAAY,GAAG,IAAA,sBAAe,EAAC,KAAK,CAAC,CAAA;IAC3C,MAAM,OAAO,GAAG,IAAA,0BAAgB,EAC9B,KAAK,CAAC,IAAI,CAAC,OAAO,EAClB,KAAK,CAAC,IAAI,CAAC,eAAe,CAC3B,CAAA;IAED,IAAI,IAAA,0BAAmB,EAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QACpD,MAAM,IAAI,iCAAmB,CAAC,sBAAsB,CAAC,CAAA;IACvD,CAAC;IAED,IAAI,IAAA,kCAA2B,EAAC,KAAK,CAAC,EAAE,CAAC;QACvC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YACtB,MAAM,IAAI,iCAAmB,CAAC,sBAAsB,CAAC,CAAA;QACvD,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC;YAClC,MAAM,IAAI,+BAAiB,CACzB,oDAAoD,CACrD,CAAA;QACH,CAAC;IACH,CAAC;IAED,IAAI,IAAA,sCAA+B,EAAC,KAAK,CAAC,EAAE,CAAC;QAC3C,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YACtB,MAAM,IAAI,iCAAmB,CAAC,sBAAsB,CAAC,CAAA;QACvD,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;YAC9B,MAAM,IAAI,+BAAiB,CACzB,gDAAgD,CACjD,CAAA;QACH,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;YAClB,MAAM,IAAI,iCAAmB,CAAC,oBAAoB,CAAC,CAAA;QACrD,CAAC;QAED,MAAM,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,wBAAwB,CAC1D,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,EAAE,EACxB,MAAM,GAAG,CAAC,OAAO,CAAC,cAAG,CAAC,sCAAsC,CAAC,CAC9D,CAAA;IACH,CAAC;IAED,8EAA8E;IAC9E,IAAI,eAAe,IAAI,sBAAsB,EAAE,CAAC;QAC9C,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YACxB,MAAM,IAAI,+BAAiB,CACzB,sDAAsD,CACvD,CAAA;QACH,CAAC;QAED,6DAA6D;QAC7D,IACE,CAAC,MAAM,CAAC,OAAO;YACf,OAAO,CAAC,UAAU,EAAE,QAAQ,CAAC,0BAA0B,CAAC,EACxD,CAAC;YACD,MAAM,IAAI,+BAAiB,CACzB,qEAAqE,CACtE,CAAA;QACH,CAAC;IACH,CAAC;IACD,0DAA0D;IAC1D,IAAI,CAAC,MAAM,CAAC,WAAW,IAAI,YAAY,EAAE,CAAC;QACxC,MAAM,IAAI,+BAAiB,CAAC,2CAA2C,CAAC,CAAA;IAC1E,CAAC;IAED,IAAI,YAAY,EAAE,CAAC;QACjB,cAAc,CAAC;YACb,GAAG,CAAC,KAAK,CAAC,eAAe,IAAI,EAAE,CAAC;YAChC,GAAG,CAAC,KAAK,CAAC,eAAe,IAAI,EAAE,CAAC;SACjC,CAAC,CAAA;IACJ,CAAC;IAED,MAAM,gCAAgC,GACpC,eAAe,IAAI,sBAAsB,CAAA;IAC3C,IAAI,gCAAgC,IAAI,YAAY,EAAE,CAAC;QACrD,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;QAEzD,IAAI,MAAM,EAAE,SAAS,IAAI,eAAe,EAAE,CAAC;YACzC,MAAM,IAAI,iCAAmB,CAAC,+BAA+B,CAAC,CAAA;QAChE,CAAC;QAED,IAAI,CAAC,MAAM,EAAE,SAAS,IAAI,sBAAsB,EAAE,CAAC;YACjD,MAAM,IAAI,iCAAmB,CAAC,2BAA2B,CAAC,CAAA;QAC5D,CAAC;QAED,IAAI,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;YACzB,MAAM,aAAa,GAAG,MAAM,IAAA,uBAAgB,EAC1C,cAAc,EACd,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CACpB,CAAA;YAED,IAAI,aAAa,EAAE,CAAC;gBAClB,IAAA,+BAAwB,EAAC;oBACvB,aAAa;oBACb,WAAW,EAAE,MAAM,CAAC,IAAI;oBACxB,YAAY,EAAE,SAAS;oBACvB,OAAO,EAAE,IAAI,CAAC,WAAW,CAAC,OAAO;oBACjC,WAAW,EAAE,IAAI,CAAC,WAAW,CAAC,WAAW;oBACzC,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,QAAQ;iBACpC,CAAC,CAAA;YACJ,CAAC;QACH,CAAC;QAED,IAAI,MAAM,EAAE,SAAS,IAAI,sBAAsB,IAAI,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;YACtE,2EAA2E;YAC3E,kFAAkF;YAClF,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAA;QAC1C,CAAC;IACH,CAAC;IAED,IAAI,IAAA,sBAAe,EAAC,KAAK,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAC5C,6EAA6E;QAC7E,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YACtB,MAAM,IAAI,iCAAmB,CAAC,0CAA0C,CAAC,CAAA;QAC3E,CAAC;QACD,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,KAAK,CAAA;QACtC,2FAA2F;QAC3F,IAAI,CAAC;YACH,MAAM,IAAA,gBAAS,EAAC,GAAG,EAAE,CACnB,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC;gBAC3B,OAAO,EAAE,WAAW;gBACpB,OAAO;gBACP,YAAY,EAAE,OAAO,CAAC,GAAG;aAC1B,CAAC,CACH,CAAA;YACD,KAAK,CAAC,WAAW,GAAG,IAAI,CAAA;QAC1B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,KAAK,CAAC,WAAW,GAAG,KAAK,CAAA;YACzB,mBAAU,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,gCAAgC,CAAC,CAAA;QACpE,CAAC;IACH,CAAC;IAED,IAAI,IAAA,uBAAgB,EAAC,KAAK,CAAC,IAAI,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;QAClD,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;YACtB,MAAM,IAAI,iCAAmB,CAC3B,8CAA8C,CAC/C,CAAA;QACH,CAAC;QACD,MAAM,GAAG,CAAC,YAAY,CAAC,mBAAmB,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;IAC5D,CAAC;IAED,IACE,CAAC,IAAA,6BAAsB,EAAC,KAAK,CAAC,IAAI,IAAA,+BAAwB,EAAC,KAAK,CAAC,CAAC;QAClE,CAAC,OAAO,CAAC,MAAM,EAAE,EACjB,CAAC;QACD,MAAM,IAAI,iCAAmB,CAAC,6CAA6C,CAAC,CAAA;IAC9E,CAAC;IAED,IAAI,IAAA,oBAAa,EAAC,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,aAAa,CAAC,cAAc,EAAE,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,CAAA;IACvE,CAAC;IAED,IAAI,IAAA,uBAAgB,EAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,GAAG,CAAC,wBAAwB,EAAE,CAAC,kBAAkB,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;IAC3E,CAAC;IAED,MAAM,eAAe,GAAG,MAAM,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QAC3D,MAAM,aAAa,GAAG,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;QAE3C,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,aAAa,GAAG,MAAM,aAAa,CAAC,oBAAoB,CAC5D,IAAA,mBAAY,EAAC,KAAK,CAAC,KAAK,CAAC,EACzB,UAAU,EACV,OAAO,CACR,CAAA;YAED,IAAI,aAAa,EAAE,CAAC;gBAClB,MAAM,IAAI,iCAAmB,CAC3B,oEAAoE,EACpE,qBAAqB,CACtB,CAAA;YACH,CAAC;QACH,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,QAAQ,CAAC;YAC1C,KAAK;YACL,OAAO;YACP,SAAS;YACT,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,OAAO;YAC3B,UAAU;SACX,CAAC,CAAA;QAEF,MAAM,UAAU,GAAG,IAAI,wBAAU,CAC/B,OAAO,EACP,MAAM,CAAC,aAAa,EACpB,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,EACnB,aAAa,CACd,CAAA;QAED,MAAM,WAAW,GAAG,IAAA,uBAAgB,EAAC,KAAK,CAAC;YACzC,CAAC,CAAC,CAAC,IAAA,sBAAe,EAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YACrC,CAAC,CAAC,SAAS,CAAA;QACb,MAAM,UAAU,CAAC,kBAAkB,CAAC,WAAW,CAAC,CAAA;QAEhD,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YACrB,IAAI,eAAe,EAAE,CAAC;gBACpB,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,CAAA;gBAChD,MAAM,aAAa,CAAC,YAAY,CAC9B,OAAO,EACP,MAAM,CAAC,KAAK,CAAC,EAAE,EACf,IAAI,GAAG,CACL,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,cAAc;oBAC/B,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC;oBAClD,CAAC,CAAC,SAAS,CACd,EACD,SAAS,CACV,CAAA;YACH,CAAC;iBAAM,IAAI,sBAAsB,EAAE,CAAC;gBAClC,MAAM,aAAa,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAA;YAClD,CAAC;QACH,CAAC;QAED,IAAI,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;YACvB,IAAI,eAAe,EAAE,CAAC;gBACpB,MAAM,aAAa,CAAC,cAAc,CAChC,OAAO,EACP,MAAM,CAAC,KAAK,CAAC,EAAE,EACf,IAAI,GAAG,CACL,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,cAAc;oBAC/B,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC;oBAClD,CAAC,CAAC,SAAS,CACd,CACF,CAAA;YACH,CAAC;iBAAM,IAAI,sBAAsB,EAAE,CAAC;gBAClC,MAAM,aAAa,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAA;YACpD,CAAC;QACH,CAAC;QAED,IACE,CAAC,eAAe,IAAI,kBAAkB,CAAC;YACvC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,0BAA0B,EAC7C,CAAC;YACD,MAAM,aAAa,CAAC,yBAAyB,CAC3C,OAAO,CAAC,GAAG,EACX,SAAS,EACT,MAAM,CAAC,KAAK,CACb,CAAA;QACH,CAAC;QAED,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,aAAa,CAAC,qBAAqB,CACvC,MAAM,CAAC,KAAK,CAAC,UAAU,IAAI,MAAM,CAAC,KAAK,CAAC,UAAU,EAClD,MAAM,CAAC,KAAK,CAAC,UAAU,EACvB;gBACE,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,eAAe,EAAE,MAAM;oBAC1C,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC;oBACzC,CAAC,CAAC,SAAS;gBACb,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,eAAe,EAAE,MAAM;oBAC1C,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC;oBACzC,CAAC,CAAC,SAAS;aACd,EACD,MAAM,CAAC,KAAK,CAAC,eAAe,IAAI,SAAS,CAC1C,CAAA;QACH,CAAC;QAED,OAAO,MAAM,CAAC,KAAK,CAAA;IACrB,CAAC,CAAC,CAAA;IAEF,OAAO,iBAAiB,CAAC,KAAK,CAAC,WAAW,CAAC,eAAe,CAAC,CAAA;AAC7D,CAAC,CAAA;AAED,mBAAyB,MAAc,EAAE,GAAe;IACtD,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC;QACtC,IAAI,EAAE,GAAG,CAAC,YAAY,CAAC,eAAe;QACtC,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE;YACjC,MAAM,eAAe,GAAG,MAAM,qBAAqB,CAAC;gBAClD,KAAK;gBACL,IAAI;gBACJ,GAAG;aACJ,CAAC,CAAA;YAEF,iEAAiE;YACjE,IAAI,IAAA,uBAAgB,EAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBACvC,MAAM,qBAAqB,CAAC;oBAC1B,IAAI;oBACJ,GAAG;oBACH,KAAK,EAAE;wBACL,GAAG,KAAK;wBACR,IAAI,EAAE;4BACJ,GAAG,KAAK,CAAC,IAAI;4BACb,KAAK,EAAE;gCACL,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK;gCACnB,KAAK,EAAE,8CAA8C;gCACrD,OAAO,EACL,oEAAoE;6BACvE;4BACD,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,OAAO;yBAC5B;qBACF;iBACF,CAAC,CAAA;YACJ,CAAC;YAED,OAAO;gBACL,QAAQ,EAAE,kBAAkB;gBAC5B,IAAI,EAAE,eAAe;aACtB,CAAA;QACH,CAAC;KACF,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,aAAa,GAAG,KAAK,EACzB,cAA8B,EAC9B,UAAkB,EAClB,KAAkB,EAClB,IAAwC,EACxC,EAAE;IACF,gCAAgC;IAChC,IAAI,IAAI,CAAC,WAAW,CAAC,OAAO;QAAE,OAAM;IAEpC,MAAM,aAAa,GAAG,MAAM,IAAA,uBAAgB,EAAC,cAAc,EAAE,UAAU,CAAC,CAAA;IAExE,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAM;IACR,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;QAC7C,IAAI,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1D,gFAAgF;YAChF,0CAA0C;YAC1C,MAAM,oBAAoB,GAAG,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,YAAY,CAAC,CAAA;YAC/D,IACE,oBAAoB;gBACpB,CAAC,oBAAoB,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EACpD,CAAC;gBACD,MAAM,IAAI,iCAAmB,CAAC,8BAA8B,GAAG,EAAE,CAAC,CAAA;YACpE,CAAC;YAED,MAAM,eAAe,GAAG,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,CAAA;YACrD,IAAI,eAAe,EAAE,CAAC;gBACpB,yFAAyF;gBACzF,IACE,IAAI,CAAC,WAAW,CAAC,WAAW;oBAC5B,CAAC,eAAe,CAAC,QAAQ,CAAC,qCAAqC,CAAC,EAChE,CAAC;oBACD,MAAM,IAAI,iCAAmB,CAC3B,sBAAsB,GAAG,sBAAsB,CAChD,CAAA;gBACH,CAAC;qBAAM,IACL,IAAI,CAAC,WAAW,CAAC,QAAQ;oBACzB,CAAC,eAAe,CAAC,QAAQ,CAAC,kCAAkC,CAAC,EAC7D,CAAC;oBACD,MAAM,IAAI,iCAAmB,CAC3B,sBAAsB,GAAG,mBAAmB,CAC7C,CAAA;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC,CAAA;AAED,MAAM,cAAc,GAAG,CAAC,MAAgB,EAAE,EAAE;IAC1C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC5B,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBACzB,MAAM,IAAI,iCAAmB,CAAC,kBAAkB,KAAK,EAAE,CAAC,CAAA;YAC1D,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC,CAAA;AAED,MAAM,QAAQ,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA","sourcesContent":["import { isModEventDivert } from '@atproto/api/dist/client/types/tools/ozone/moderation/defs'\nimport { AuthRequiredError, InvalidRequestError } from '@atproto/xrpc-server'\nimport { AdminTokenOutput, ModeratorOutput } from '../../auth-verifier'\nimport { AppContext } from '../../context'\nimport { Server } from '../../lexicon'\nimport { ids } from '../../lexicon/lexicons'\nimport {\n ModEventTag,\n isAgeAssuranceEvent,\n isAgeAssuranceOverrideEvent,\n isModEventAcknowledge,\n isModEventEmail,\n isModEventLabel,\n isModEventMuteReporter,\n isModEventReport,\n isModEventReverseTakedown,\n isModEventTag,\n isModEventTakedown,\n isModEventUnmuteReporter,\n isRevokeAccountCredentialsEvent,\n} from '../../lexicon/types/tools/ozone/moderation/defs'\nimport { HandlerInput } from '../../lexicon/types/tools/ozone/moderation/emitEvent'\nimport { httpLogger } from '../../logger'\nimport { subjectFromInput } from '../../mod-service/subject'\nimport { SettingService } from '../../setting/service'\nimport { TagService } from '../../tag-service'\nimport { getTagForReport } from '../../tag-service/util'\nimport { retryHttp } from '../../util'\nimport { getEventType } from '../util'\nimport { assertProtectedTagAction, getProtectedTags } from './util'\n\nconst handleModerationEvent = async ({\n ctx,\n input,\n auth,\n}: {\n ctx: AppContext\n input: HandlerInput\n auth: ModeratorOutput | AdminTokenOutput\n}) => {\n const access = auth.credentials\n const createdBy =\n auth.credentials.type === 'moderator'\n ? auth.credentials.iss\n : input.body.createdBy\n const db = ctx.db\n const moderationService = ctx.modService(db)\n const settingService = ctx.settingService(db)\n const { event, externalId } = input.body\n const isAcknowledgeEvent = isModEventAcknowledge(event)\n const isTakedownEvent = isModEventTakedown(event)\n const isReverseTakedownEvent = isModEventReverseTakedown(event)\n const isLabelEvent = isModEventLabel(event)\n const subject = subjectFromInput(\n input.body.subject,\n input.body.subjectBlobCids,\n )\n\n if (isAgeAssuranceEvent(event) && !subject.isRepo()) {\n throw new InvalidRequestError('Invalid subject type')\n }\n\n if (isAgeAssuranceOverrideEvent(event)) {\n if (!subject.isRepo()) {\n throw new InvalidRequestError('Invalid subject type')\n }\n if (!auth.credentials.isModerator) {\n throw new AuthRequiredError(\n 'Must be a full moderator to override age assurance',\n )\n }\n }\n\n if (isRevokeAccountCredentialsEvent(event)) {\n if (!subject.isRepo()) {\n throw new InvalidRequestError('Invalid subject type')\n }\n\n if (!auth.credentials.isAdmin) {\n throw new AuthRequiredError(\n 'Must be an admin to revoke account credentials',\n )\n }\n\n if (!ctx.pdsAgent) {\n throw new InvalidRequestError('PDS not configured')\n }\n\n await ctx.pdsAgent.com.atproto.temp.revokeAccountCredentials(\n { account: subject.did },\n await ctx.pdsAuth(ids.ComAtprotoTempRevokeAccountCredentials),\n )\n }\n\n // if less than moderator access then can only take ack and escalation actions\n if (isTakedownEvent || isReverseTakedownEvent) {\n if (!access.isModerator) {\n throw new AuthRequiredError(\n 'Must be a full moderator to take this type of action',\n )\n }\n\n // Non admins should not be able to take down feed generators\n if (\n !access.isAdmin &&\n subject.recordPath?.includes('app.bsky.feed.generator/')\n ) {\n throw new AuthRequiredError(\n 'Must be a full admin to take this type of action on feed generators',\n )\n }\n }\n // if less than moderator access then can not apply labels\n if (!access.isModerator && isLabelEvent) {\n throw new AuthRequiredError('Must be a full moderator to label content')\n }\n\n if (isLabelEvent) {\n validateLabels([\n ...(event.createLabelVals ?? []),\n ...(event.negateLabelVals ?? []),\n ])\n }\n\n const isTakedownOrReverseTakedownEvent =\n isTakedownEvent || isReverseTakedownEvent\n if (isTakedownOrReverseTakedownEvent || isLabelEvent) {\n const status = await moderationService.getStatus(subject)\n\n if (status?.takendown && isTakedownEvent) {\n throw new InvalidRequestError(`Subject is already taken down`)\n }\n\n if (!status?.takendown && isReverseTakedownEvent) {\n throw new InvalidRequestError(`Subject is not taken down`)\n }\n\n if (status?.tags?.length) {\n const protectedTags = await getProtectedTags(\n settingService,\n ctx.cfg.service.did,\n )\n\n if (protectedTags) {\n assertProtectedTagAction({\n protectedTags,\n subjectTags: status.tags,\n actionAuthor: createdBy,\n isAdmin: auth.credentials.isAdmin,\n isModerator: auth.credentials.isModerator,\n isTriage: auth.credentials.isTriage,\n })\n }\n }\n\n if (status?.takendown && isReverseTakedownEvent && subject.isRecord()) {\n // due to the way blob status is modeled, we should reverse takedown on all\n // blobs for the record being restored, which aren't taken down on another record.\n subject.blobCids = status.blobCids ?? []\n }\n }\n\n if (isModEventEmail(event) && event.content) {\n // sending email prior to logging the event to avoid a long transaction below\n if (!subject.isRepo()) {\n throw new InvalidRequestError('Email can only be sent to a repo subject')\n }\n const { content, subjectLine } = event\n // on error, don't fail the whole event. instead, log the event data with isDelivered false\n try {\n await retryHttp(() =>\n ctx.modService(db).sendEmail({\n subject: subjectLine,\n content,\n recipientDid: subject.did,\n }),\n )\n event.isDelivered = true\n } catch (err) {\n event.isDelivered = false\n httpLogger.error({ err, event }, 'failed to send mod event email')\n }\n }\n\n if (isModEventDivert(event) && subject.isRecord()) {\n if (!ctx.blobDiverter) {\n throw new InvalidRequestError(\n 'BlobDiverter not configured for this service',\n )\n }\n await ctx.blobDiverter.uploadBlobOnService(subject.info())\n }\n\n if (\n (isModEventMuteReporter(event) || isModEventUnmuteReporter(event)) &&\n !subject.isRepo()\n ) {\n throw new InvalidRequestError('Subject must be a repo when muting reporter')\n }\n\n if (isModEventTag(event)) {\n await assertTagAuth(settingService, ctx.cfg.service.did, event, auth)\n }\n\n if (isModEventReport(event)) {\n await ctx.moderationServiceProfile().validateReasonType(event.reportType)\n }\n\n const moderationEvent = await db.transaction(async (dbTxn) => {\n const moderationTxn = ctx.modService(dbTxn)\n\n if (externalId) {\n const existingEvent = await moderationTxn.getEventByExternalId(\n getEventType(event.$type),\n externalId,\n subject,\n )\n\n if (existingEvent) {\n throw new InvalidRequestError(\n `An event with the same external ID already exists for the subject.`,\n 'DuplicateExternalId',\n )\n }\n }\n\n const result = await moderationTxn.logEvent({\n event,\n subject,\n createdBy,\n modTool: input.body.modTool,\n externalId,\n })\n\n const tagService = new TagService(\n subject,\n result.subjectStatus,\n ctx.cfg.service.did,\n moderationTxn,\n )\n\n const initialTags = isModEventReport(event)\n ? [getTagForReport(event.reportType)]\n : undefined\n await tagService.evaluateForSubject(initialTags)\n\n if (subject.isRepo()) {\n if (isTakedownEvent) {\n const isSuspend = !!result.event.durationInHours\n await moderationTxn.takedownRepo(\n subject,\n result.event.id,\n new Set(\n result.event.meta?.targetServices\n ? `${result.event.meta.targetServices}`.split(',')\n : undefined,\n ),\n isSuspend,\n )\n } else if (isReverseTakedownEvent) {\n await moderationTxn.reverseTakedownRepo(subject)\n }\n }\n\n if (subject.isRecord()) {\n if (isTakedownEvent) {\n await moderationTxn.takedownRecord(\n subject,\n result.event.id,\n new Set(\n result.event.meta?.targetServices\n ? `${result.event.meta.targetServices}`.split(',')\n : undefined,\n ),\n )\n } else if (isReverseTakedownEvent) {\n await moderationTxn.reverseTakedownRecord(subject)\n }\n }\n\n if (\n (isTakedownEvent || isAcknowledgeEvent) &&\n result.event.meta?.acknowledgeAccountSubjects\n ) {\n await moderationTxn.resolveSubjectsForAccount(\n subject.did,\n createdBy,\n result.event,\n )\n }\n\n if (isLabelEvent) {\n await moderationTxn.formatAndCreateLabels(\n result.event.subjectUri ?? result.event.subjectDid,\n result.event.subjectCid,\n {\n create: result.event.createLabelVals?.length\n ? result.event.createLabelVals.split(' ')\n : undefined,\n negate: result.event.negateLabelVals?.length\n ? result.event.negateLabelVals.split(' ')\n : undefined,\n },\n result.event.durationInHours ?? undefined,\n )\n }\n\n return result.event\n })\n\n return moderationService.views.formatEvent(moderationEvent)\n}\n\nexport default function (server: Server, ctx: AppContext) {\n server.tools.ozone.moderation.emitEvent({\n auth: ctx.authVerifier.modOrAdminToken,\n handler: async ({ input, auth }) => {\n const moderationEvent = await handleModerationEvent({\n input,\n auth,\n ctx,\n })\n\n // On divert events, we need to automatically take down the blobs\n if (isModEventDivert(input.body.event)) {\n await handleModerationEvent({\n auth,\n ctx,\n input: {\n ...input,\n body: {\n ...input.body,\n event: {\n ...input.body.event,\n $type: 'tools.ozone.moderation.defs#modEventTakedown',\n comment:\n '[DIVERT_SIDE_EFFECT]: Automatically taking down after divert event',\n },\n modTool: input.body.modTool,\n },\n },\n })\n }\n\n return {\n encoding: 'application/json',\n body: moderationEvent,\n }\n },\n })\n}\n\nconst assertTagAuth = async (\n settingService: SettingService,\n serviceDid: string,\n event: ModEventTag,\n auth: ModeratorOutput | AdminTokenOutput,\n) => {\n // admins can add/remove any tag\n if (auth.credentials.isAdmin) return\n\n const protectedTags = await getProtectedTags(settingService, serviceDid)\n\n if (!protectedTags) {\n return\n }\n\n for (const tag of Object.keys(protectedTags)) {\n if (event.add.includes(tag) || event.remove.includes(tag)) {\n // if specific moderators are configured to manage this tag but the current user\n // is not one of them, then throw an error\n const configuredModerators = protectedTags[tag]?.['moderators']\n if (\n configuredModerators &&\n !configuredModerators.includes(auth.credentials.iss)\n ) {\n throw new InvalidRequestError(`Not allowed to manage tag: ${tag}`)\n }\n\n const configuredRoles = protectedTags[tag]?.['roles']\n if (configuredRoles) {\n // admins can already do everything so we only check for moderator and triage role config\n if (\n auth.credentials.isModerator &&\n !configuredRoles.includes('tools.ozone.team.defs#roleModerator')\n ) {\n throw new InvalidRequestError(\n `Can not manage tag ${tag} with moderator role`,\n )\n } else if (\n auth.credentials.isTriage &&\n !configuredRoles.includes('tools.ozone.team.defs#roleTriage')\n ) {\n throw new InvalidRequestError(\n `Can not manage tag ${tag} with triage role`,\n )\n }\n }\n }\n }\n}\n\nconst validateLabels = (labels: string[]) => {\n for (const label of labels) {\n for (const char of badChars) {\n if (label.includes(char)) {\n throw new InvalidRequestError(`Invalid label: ${label}`)\n }\n }\n }\n}\n\nconst badChars = [' ', ',', ';', `'`, `\"`]\n"]}
@@ -5,7 +5,7 @@ export declare const getPdsAccountInfos: (ctx: AppContext, dids: string[]) => Pr
5
5
  export declare const addAccountInfoToRepoViewDetail: (repoView: RepoView | RepoViewDetail, accountInfo: AccountView | null, includeEmail?: boolean) => RepoViewDetail;
6
6
  export declare const addAccountInfoToRepoView: (repoView: RepoView, accountInfo: AccountView | null, includeEmail?: boolean) => RepoView;
7
7
  export declare const getEventType: (type: string) => "tools.ozone.moderation.defs#modEventTakedown" | "tools.ozone.moderation.defs#modEventReverseTakedown" | "tools.ozone.moderation.defs#modEventComment" | "tools.ozone.moderation.defs#modEventReport" | "tools.ozone.moderation.defs#modEventLabel" | "tools.ozone.moderation.defs#modEventAcknowledge" | "tools.ozone.moderation.defs#modEventEscalate" | "tools.ozone.moderation.defs#modEventMute" | "tools.ozone.moderation.defs#modEventUnmute" | "tools.ozone.moderation.defs#modEventMuteReporter" | "tools.ozone.moderation.defs#modEventUnmuteReporter" | "tools.ozone.moderation.defs#modEventEmail" | "tools.ozone.moderation.defs#modEventResolveAppeal" | "tools.ozone.moderation.defs#modEventTag" | "tools.ozone.moderation.defs#accountEvent" | "tools.ozone.moderation.defs#identityEvent" | "tools.ozone.moderation.defs#recordEvent" | "tools.ozone.moderation.defs#modEventPriorityScore" | "tools.ozone.moderation.defs#revokeAccountCredentialsEvent" | "tools.ozone.moderation.defs#ageAssuranceEvent" | "tools.ozone.moderation.defs#ageAssuranceOverrideEvent";
8
- export declare const getReviewState: (reviewState?: string) => "tools.ozone.moderation.defs#reviewOpen" | "tools.ozone.moderation.defs#reviewEscalated" | "tools.ozone.moderation.defs#reviewClosed" | "tools.ozone.moderation.defs#reviewNone" | undefined;
8
+ export declare const getReviewState: (reviewState?: string) => "tools.ozone.moderation.defs#reviewOpen" | "tools.ozone.moderation.defs#reviewClosed" | "tools.ozone.moderation.defs#reviewEscalated" | "tools.ozone.moderation.defs#reviewNone" | undefined;
9
9
  export declare const getMemberRole: (role: string) => "tools.ozone.team.defs#roleAdmin" | "tools.ozone.team.defs#roleModerator" | "tools.ozone.team.defs#roleTriage" | "tools.ozone.team.defs#roleVerifier";
10
10
  export declare const OZONE_APPEAL_REASON_TYPE = "tools.ozone.report.defs#reasonAppeal";
11
11
  export declare const isAppealReport: (reasonType?: string) => boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/api/util.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAIvC,OAAO,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAA;AAErE,OAAO,EAIL,QAAQ,EACR,cAAc,EACf,MAAM,8CAA8C,CAAA;AASrD,eAAO,MAAM,kBAAkB,GAC7B,KAAK,UAAU,EACf,MAAM,MAAM,EAAE,KACb,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC,CAkBzC,CAAA;AAUD,eAAO,MAAM,8BAA8B,GACzC,UAAU,QAAQ,GAAG,cAAc,EACnC,aAAa,WAAW,GAAG,IAAI,EAC/B,sBAAoB,KACnB,cAsCF,CAAA;AAED,eAAO,MAAM,wBAAwB,GACnC,UAAU,QAAQ,EAClB,aAAa,WAAW,GAAG,IAAI,EAC/B,sBAAoB,KACnB,QAWF,CAAA;AAED,eAAO,MAAM,YAAY,GAAI,MAAM,MAAM,4hCAKxC,CAAA;AAED,eAAO,MAAM,cAAc,GAAI,cAAc,MAAM,iMAMlD,CAAA;AA+BD,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,0JAKzC,CAAA;AASD,eAAO,MAAM,wBAAwB,yCAAyC,CAAA;AAE9E,eAAO,MAAM,cAAc,GAAI,aAAa,MAAM,KAAG,OAEpD,CAAA;AAED,eAAO,MAAM,kBAAkB,GAAI,SAAS,MAAM,KAAG,mBAKpD,CAAA;AAED,eAAO,MAAM,iBAAiB,GAAI,QAAQ,MAAM,KAAG,kBAKlD,CAAA;AAED,eAAO,MAAM,iBAAiB,GAAI,QAAQ,MAAM,KAAG,kBAKlD,CAAA;AAED,eAAO,MAAM,oBAAoB,GAAI,WAAW,MAAM,KAAG,iBAKxD,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,YAAY,GAAG,YAAY,CAAA;AACvE,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,KAAK,CAAA;AAClD,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,MAAM,GAAG,WAAW,CAAA;AAC/D,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,CAAA;AAOtE,eAAO,MAAM,sBAAsB,GAAI,QAAQ,MAAM,KAAG,mBAKvD,CAAA;AAED,eAAO,MAAM,wBAAwB,GACnC,QAAQ,MAAM,KACb,qBAKF,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG,UAAU,CAAA;AAC5C,MAAM,MAAM,qBAAqB,GAC7B,SAAS,GACT,UAAU,GACV,WAAW,GACX,QAAQ,CAAA"}
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/api/util.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAIvC,OAAO,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAA;AAErE,OAAO,EAKL,QAAQ,EACR,cAAc,EACf,MAAM,8CAA8C,CAAA;AASrD,eAAO,MAAM,kBAAkB,GAC7B,KAAK,UAAU,EACf,MAAM,MAAM,EAAE,KACb,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC,CAkBzC,CAAA;AAUD,eAAO,MAAM,8BAA8B,GACzC,UAAU,QAAQ,GAAG,cAAc,EACnC,aAAa,WAAW,GAAG,IAAI,EAC/B,sBAAoB,KACnB,cAsCF,CAAA;AAED,eAAO,MAAM,wBAAwB,GACnC,UAAU,QAAQ,EAClB,aAAa,WAAW,GAAG,IAAI,EAC/B,sBAAoB,KACnB,QAWF,CAAA;AAED,eAAO,MAAM,YAAY,GAAI,MAAM,MAAM,4hCAKxC,CAAA;AAED,eAAO,MAAM,cAAc,GAAI,cAAc,MAAM,iMAMlD,CAAA;AAoCD,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,0JAKzC,CAAA;AASD,eAAO,MAAM,wBAAwB,yCAAyC,CAAA;AAE9E,eAAO,MAAM,cAAc,GAAI,aAAa,MAAM,KAAG,OAEpD,CAAA;AAED,eAAO,MAAM,kBAAkB,GAAI,SAAS,MAAM,KAAG,mBAKpD,CAAA;AAED,eAAO,MAAM,iBAAiB,GAAI,QAAQ,MAAM,KAAG,kBAKlD,CAAA;AAED,eAAO,MAAM,iBAAiB,GAAI,QAAQ,MAAM,KAAG,kBAKlD,CAAA;AAED,eAAO,MAAM,oBAAoB,GAAI,WAAW,MAAM,KAAG,iBAKxD,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,YAAY,GAAG,YAAY,CAAA;AACvE,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,KAAK,CAAA;AAClD,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,MAAM,GAAG,WAAW,CAAA;AAC/D,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,CAAA;AAOtE,eAAO,MAAM,sBAAsB,GAAI,QAAQ,MAAM,KAAG,mBAKvD,CAAA;AAED,eAAO,MAAM,wBAAwB,GACnC,QAAQ,MAAM,KACb,qBAKF,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG,UAAU,CAAA;AAC5C,MAAM,MAAM,qBAAqB,GAC7B,SAAS,GACT,UAAU,GACV,WAAW,GACX,QAAQ,CAAA"}
package/dist/api/util.js CHANGED
@@ -88,7 +88,12 @@ const getReviewState = (reviewState) => {
88
88
  throw new xrpc_server_1.InvalidRequestError('Invalid review state');
89
89
  };
90
90
  exports.getReviewState = getReviewState;
91
- const reviewStates = new Set([defs_2.REVIEWCLOSED, defs_2.REVIEWESCALATED, defs_2.REVIEWOPEN]);
91
+ const reviewStates = new Set([
92
+ defs_2.REVIEWCLOSED,
93
+ defs_2.REVIEWESCALATED,
94
+ defs_2.REVIEWOPEN,
95
+ defs_2.REVIEWNONE,
96
+ ]);
92
97
  const eventTypes = new Set([
93
98
  'tools.ozone.moderation.defs#modEventTakedown',
94
99
  'tools.ozone.moderation.defs#modEventAcknowledge',
@@ -1 +1 @@
1
- {"version":3,"file":"util.js","sourceRoot":"","sources":["../../src/api/util.ts"],"names":[],"mappings":"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","sourcesContent":["import { InvalidRequestError } from '@atproto/xrpc-server'\nimport { AppContext } from '../context'\nimport { Member } from '../db/schema/member'\nimport { ModerationEvent } from '../db/schema/moderation_event'\nimport { ids } from '../lexicon/lexicons'\nimport { AccountView } from '../lexicon/types/com/atproto/admin/defs'\nimport { REASONAPPEAL } from '../lexicon/types/com/atproto/moderation/defs'\nimport {\n REVIEWCLOSED,\n REVIEWESCALATED,\n REVIEWOPEN,\n RepoView,\n RepoViewDetail,\n} from '../lexicon/types/tools/ozone/moderation/defs'\nimport {\n ROLEADMIN,\n ROLEMODERATOR,\n ROLETRIAGE,\n ROLEVERIFIER,\n} from '../lexicon/types/tools/ozone/team/defs'\nimport { ModerationSubjectStatusRow } from '../mod-service/types'\n\nexport const getPdsAccountInfos = async (\n ctx: AppContext,\n dids: string[],\n): Promise<Map<string, AccountView | null>> => {\n const results = new Map<string, AccountView | null>()\n\n const agent = ctx.pdsAgent\n if (!agent || !dids.length) return results\n\n const auth = await ctx.pdsAuth(ids.ComAtprotoAdminGetAccountInfos)\n if (!auth) return results\n\n try {\n const res = await agent.com.atproto.admin.getAccountInfos({ dids }, auth)\n res.data.infos.forEach((info) => {\n results.set(info.did, info)\n })\n return results\n } catch {\n return results\n }\n}\n\nfunction un$type<T extends object>(obj: T): Omit<T, '$type'> {\n if ('$type' in obj) {\n const { $type: _, ...rest } = obj\n return rest\n }\n return obj\n}\n\nexport const addAccountInfoToRepoViewDetail = (\n repoView: RepoView | RepoViewDetail,\n accountInfo: AccountView | null,\n includeEmail = false,\n): RepoViewDetail => {\n if (!accountInfo) {\n return un$type({\n ...repoView,\n moderation: un$type(repoView.moderation),\n })\n }\n\n const {\n email,\n deactivatedAt,\n emailConfirmedAt,\n inviteNote,\n invitedBy,\n invites,\n invitesDisabled,\n threatSignatures,\n // pick some duplicate/unwanted details out\n $type: _accountType,\n did: _did,\n handle: _handle,\n indexedAt: _indexedAt,\n relatedRecords: _relatedRecords,\n ...otherAccountInfo\n } = accountInfo\n return {\n ...otherAccountInfo,\n ...un$type(repoView),\n moderation: un$type(repoView.moderation),\n email: includeEmail ? email : undefined,\n invitedBy,\n invitesDisabled,\n inviteNote,\n invites,\n emailConfirmedAt,\n deactivatedAt,\n threatSignatures,\n }\n}\n\nexport const addAccountInfoToRepoView = (\n repoView: RepoView,\n accountInfo: AccountView | null,\n includeEmail = false,\n): RepoView => {\n if (!accountInfo) return repoView\n return {\n ...repoView,\n email: includeEmail ? accountInfo.email : undefined,\n invitedBy: accountInfo.invitedBy,\n invitesDisabled: accountInfo.invitesDisabled,\n inviteNote: accountInfo.inviteNote,\n deactivatedAt: accountInfo.deactivatedAt,\n threatSignatures: accountInfo.threatSignatures,\n }\n}\n\nexport const getEventType = (type: string) => {\n if (eventTypes.has(type)) {\n return type as ModerationEvent['action']\n }\n throw new InvalidRequestError('Invalid event type')\n}\n\nexport const getReviewState = (reviewState?: string) => {\n if (!reviewState) return undefined\n if (reviewStates.has(reviewState)) {\n return reviewState as ModerationSubjectStatusRow['reviewState']\n }\n throw new InvalidRequestError('Invalid review state')\n}\n\nconst reviewStates = new Set([REVIEWCLOSED, REVIEWESCALATED, REVIEWOPEN])\n\nconst eventTypes = new Set([\n 'tools.ozone.moderation.defs#modEventTakedown',\n 'tools.ozone.moderation.defs#modEventAcknowledge',\n 'tools.ozone.moderation.defs#modEventEscalate',\n 'tools.ozone.moderation.defs#modEventComment',\n 'tools.ozone.moderation.defs#modEventLabel',\n 'tools.ozone.moderation.defs#modEventReport',\n 'tools.ozone.moderation.defs#modEventMute',\n 'tools.ozone.moderation.defs#modEventUnmute',\n 'tools.ozone.moderation.defs#modEventMuteReporter',\n 'tools.ozone.moderation.defs#modEventUnmuteReporter',\n 'tools.ozone.moderation.defs#modEventReverseTakedown',\n 'tools.ozone.moderation.defs#modEventEmail',\n 'tools.ozone.moderation.defs#modEventResolveAppeal',\n 'tools.ozone.moderation.defs#modEventTag',\n 'tools.ozone.moderation.defs#modEventDivert',\n 'tools.ozone.moderation.defs#accountEvent',\n 'tools.ozone.moderation.defs#identityEvent',\n 'tools.ozone.moderation.defs#recordEvent',\n 'tools.ozone.moderation.defs#modEventPriorityScore',\n 'tools.ozone.moderation.defs#ageAssuranceEvent',\n 'tools.ozone.moderation.defs#ageAssuranceOverrideEvent',\n 'tools.ozone.moderation.defs#revokeAccountCredentialsEvent',\n 'tools.ozone.moderation.defs#scheduleTakedownEvent',\n 'tools.ozone.moderation.defs#cancelScheduledTakedownEvent',\n])\n\nexport const getMemberRole = (role: string) => {\n if (memberRoles.has(role)) {\n return role as Member['role']\n }\n throw new InvalidRequestError('Invalid member role')\n}\n\nconst memberRoles = new Set([\n ROLEADMIN,\n ROLEMODERATOR,\n ROLETRIAGE,\n ROLEVERIFIER,\n])\n\nexport const OZONE_APPEAL_REASON_TYPE = 'tools.ozone.report.defs#reasonAppeal'\nconst APPEAL_REASON_TYPES = [REASONAPPEAL, OZONE_APPEAL_REASON_TYPE]\nexport const isAppealReport = (reasonType?: string): boolean => {\n return !!reasonType && APPEAL_REASON_TYPES.includes(reasonType)\n}\n\nexport const getSafelinkPattern = (pattern: string): SafelinkPatternType => {\n if (safelinkPatterns.has(pattern)) {\n return pattern as SafelinkPatternType\n }\n throw new InvalidRequestError('Invalid safelink pattern type')\n}\n\nexport const getSafelinkAction = (action: string): SafelinkActionType => {\n if (safelinkActions.has(action)) {\n return action as SafelinkActionType\n }\n throw new InvalidRequestError('Invalid safelink action type')\n}\n\nexport const getSafelinkReason = (reason: string): SafelinkReasonType => {\n if (safelinkReasons.has(reason)) {\n return reason as SafelinkReasonType\n }\n throw new InvalidRequestError('Invalid safelink reason type')\n}\n\nexport const getSafelinkEventType = (eventType: string): SafelinkEventType => {\n if (safelinkEventTypes.has(eventType)) {\n return eventType as SafelinkEventType\n }\n throw new InvalidRequestError('Invalid safelink event type')\n}\n\nexport type SafelinkEventType = 'addRule' | 'updateRule' | 'removeRule'\nexport type SafelinkPatternType = 'domain' | 'url'\nexport type SafelinkActionType = 'block' | 'warn' | 'whitelist'\nexport type SafelinkReasonType = 'csam' | 'spam' | 'phishing' | 'none'\n\nconst safelinkPatterns = new Set(['domain', 'url'])\nconst safelinkActions = new Set(['block', 'warn', 'whitelist'])\nconst safelinkReasons = new Set(['csam', 'spam', 'phishing', 'none'])\nconst safelinkEventTypes = new Set(['addRule', 'updateRule', 'removeRule'])\n\nexport const getScheduledActionType = (action: string): ScheduledActionType => {\n if (scheduledActionTypes.has(action)) {\n return action as ScheduledActionType\n }\n throw new InvalidRequestError('Invalid scheduled action type')\n}\n\nexport const getScheduledActionStatus = (\n status: string,\n): ScheduledActionStatus => {\n if (scheduledActionStatuses.has(status)) {\n return status as ScheduledActionStatus\n }\n throw new InvalidRequestError('Invalid scheduled action status')\n}\n\nexport type ScheduledActionType = 'takedown'\nexport type ScheduledActionStatus =\n | 'pending'\n | 'executed'\n | 'cancelled'\n | 'failed'\n\nconst scheduledActionTypes = new Set(['takedown'])\nconst scheduledActionStatuses = new Set([\n 'pending',\n 'executed',\n 'cancelled',\n 'failed',\n])\n"]}
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["../../src/api/util.ts"],"names":[],"mappings":"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","sourcesContent":["import { InvalidRequestError } from '@atproto/xrpc-server'\nimport { AppContext } from '../context'\nimport { Member } from '../db/schema/member'\nimport { ModerationEvent } from '../db/schema/moderation_event'\nimport { ids } from '../lexicon/lexicons'\nimport { AccountView } from '../lexicon/types/com/atproto/admin/defs'\nimport { REASONAPPEAL } from '../lexicon/types/com/atproto/moderation/defs'\nimport {\n REVIEWCLOSED,\n REVIEWESCALATED,\n REVIEWNONE,\n REVIEWOPEN,\n RepoView,\n RepoViewDetail,\n} from '../lexicon/types/tools/ozone/moderation/defs'\nimport {\n ROLEADMIN,\n ROLEMODERATOR,\n ROLETRIAGE,\n ROLEVERIFIER,\n} from '../lexicon/types/tools/ozone/team/defs'\nimport { ModerationSubjectStatusRow } from '../mod-service/types'\n\nexport const getPdsAccountInfos = async (\n ctx: AppContext,\n dids: string[],\n): Promise<Map<string, AccountView | null>> => {\n const results = new Map<string, AccountView | null>()\n\n const agent = ctx.pdsAgent\n if (!agent || !dids.length) return results\n\n const auth = await ctx.pdsAuth(ids.ComAtprotoAdminGetAccountInfos)\n if (!auth) return results\n\n try {\n const res = await agent.com.atproto.admin.getAccountInfos({ dids }, auth)\n res.data.infos.forEach((info) => {\n results.set(info.did, info)\n })\n return results\n } catch {\n return results\n }\n}\n\nfunction un$type<T extends object>(obj: T): Omit<T, '$type'> {\n if ('$type' in obj) {\n const { $type: _, ...rest } = obj\n return rest\n }\n return obj\n}\n\nexport const addAccountInfoToRepoViewDetail = (\n repoView: RepoView | RepoViewDetail,\n accountInfo: AccountView | null,\n includeEmail = false,\n): RepoViewDetail => {\n if (!accountInfo) {\n return un$type({\n ...repoView,\n moderation: un$type(repoView.moderation),\n })\n }\n\n const {\n email,\n deactivatedAt,\n emailConfirmedAt,\n inviteNote,\n invitedBy,\n invites,\n invitesDisabled,\n threatSignatures,\n // pick some duplicate/unwanted details out\n $type: _accountType,\n did: _did,\n handle: _handle,\n indexedAt: _indexedAt,\n relatedRecords: _relatedRecords,\n ...otherAccountInfo\n } = accountInfo\n return {\n ...otherAccountInfo,\n ...un$type(repoView),\n moderation: un$type(repoView.moderation),\n email: includeEmail ? email : undefined,\n invitedBy,\n invitesDisabled,\n inviteNote,\n invites,\n emailConfirmedAt,\n deactivatedAt,\n threatSignatures,\n }\n}\n\nexport const addAccountInfoToRepoView = (\n repoView: RepoView,\n accountInfo: AccountView | null,\n includeEmail = false,\n): RepoView => {\n if (!accountInfo) return repoView\n return {\n ...repoView,\n email: includeEmail ? accountInfo.email : undefined,\n invitedBy: accountInfo.invitedBy,\n invitesDisabled: accountInfo.invitesDisabled,\n inviteNote: accountInfo.inviteNote,\n deactivatedAt: accountInfo.deactivatedAt,\n threatSignatures: accountInfo.threatSignatures,\n }\n}\n\nexport const getEventType = (type: string) => {\n if (eventTypes.has(type)) {\n return type as ModerationEvent['action']\n }\n throw new InvalidRequestError('Invalid event type')\n}\n\nexport const getReviewState = (reviewState?: string) => {\n if (!reviewState) return undefined\n if (reviewStates.has(reviewState)) {\n return reviewState as ModerationSubjectStatusRow['reviewState']\n }\n throw new InvalidRequestError('Invalid review state')\n}\n\nconst reviewStates = new Set([\n REVIEWCLOSED,\n REVIEWESCALATED,\n REVIEWOPEN,\n REVIEWNONE,\n])\n\nconst eventTypes = new Set([\n 'tools.ozone.moderation.defs#modEventTakedown',\n 'tools.ozone.moderation.defs#modEventAcknowledge',\n 'tools.ozone.moderation.defs#modEventEscalate',\n 'tools.ozone.moderation.defs#modEventComment',\n 'tools.ozone.moderation.defs#modEventLabel',\n 'tools.ozone.moderation.defs#modEventReport',\n 'tools.ozone.moderation.defs#modEventMute',\n 'tools.ozone.moderation.defs#modEventUnmute',\n 'tools.ozone.moderation.defs#modEventMuteReporter',\n 'tools.ozone.moderation.defs#modEventUnmuteReporter',\n 'tools.ozone.moderation.defs#modEventReverseTakedown',\n 'tools.ozone.moderation.defs#modEventEmail',\n 'tools.ozone.moderation.defs#modEventResolveAppeal',\n 'tools.ozone.moderation.defs#modEventTag',\n 'tools.ozone.moderation.defs#modEventDivert',\n 'tools.ozone.moderation.defs#accountEvent',\n 'tools.ozone.moderation.defs#identityEvent',\n 'tools.ozone.moderation.defs#recordEvent',\n 'tools.ozone.moderation.defs#modEventPriorityScore',\n 'tools.ozone.moderation.defs#ageAssuranceEvent',\n 'tools.ozone.moderation.defs#ageAssuranceOverrideEvent',\n 'tools.ozone.moderation.defs#revokeAccountCredentialsEvent',\n 'tools.ozone.moderation.defs#scheduleTakedownEvent',\n 'tools.ozone.moderation.defs#cancelScheduledTakedownEvent',\n])\n\nexport const getMemberRole = (role: string) => {\n if (memberRoles.has(role)) {\n return role as Member['role']\n }\n throw new InvalidRequestError('Invalid member role')\n}\n\nconst memberRoles = new Set([\n ROLEADMIN,\n ROLEMODERATOR,\n ROLETRIAGE,\n ROLEVERIFIER,\n])\n\nexport const OZONE_APPEAL_REASON_TYPE = 'tools.ozone.report.defs#reasonAppeal'\nconst APPEAL_REASON_TYPES = [REASONAPPEAL, OZONE_APPEAL_REASON_TYPE]\nexport const isAppealReport = (reasonType?: string): boolean => {\n return !!reasonType && APPEAL_REASON_TYPES.includes(reasonType)\n}\n\nexport const getSafelinkPattern = (pattern: string): SafelinkPatternType => {\n if (safelinkPatterns.has(pattern)) {\n return pattern as SafelinkPatternType\n }\n throw new InvalidRequestError('Invalid safelink pattern type')\n}\n\nexport const getSafelinkAction = (action: string): SafelinkActionType => {\n if (safelinkActions.has(action)) {\n return action as SafelinkActionType\n }\n throw new InvalidRequestError('Invalid safelink action type')\n}\n\nexport const getSafelinkReason = (reason: string): SafelinkReasonType => {\n if (safelinkReasons.has(reason)) {\n return reason as SafelinkReasonType\n }\n throw new InvalidRequestError('Invalid safelink reason type')\n}\n\nexport const getSafelinkEventType = (eventType: string): SafelinkEventType => {\n if (safelinkEventTypes.has(eventType)) {\n return eventType as SafelinkEventType\n }\n throw new InvalidRequestError('Invalid safelink event type')\n}\n\nexport type SafelinkEventType = 'addRule' | 'updateRule' | 'removeRule'\nexport type SafelinkPatternType = 'domain' | 'url'\nexport type SafelinkActionType = 'block' | 'warn' | 'whitelist'\nexport type SafelinkReasonType = 'csam' | 'spam' | 'phishing' | 'none'\n\nconst safelinkPatterns = new Set(['domain', 'url'])\nconst safelinkActions = new Set(['block', 'warn', 'whitelist'])\nconst safelinkReasons = new Set(['csam', 'spam', 'phishing', 'none'])\nconst safelinkEventTypes = new Set(['addRule', 'updateRule', 'removeRule'])\n\nexport const getScheduledActionType = (action: string): ScheduledActionType => {\n if (scheduledActionTypes.has(action)) {\n return action as ScheduledActionType\n }\n throw new InvalidRequestError('Invalid scheduled action type')\n}\n\nexport const getScheduledActionStatus = (\n status: string,\n): ScheduledActionStatus => {\n if (scheduledActionStatuses.has(status)) {\n return status as ScheduledActionStatus\n }\n throw new InvalidRequestError('Invalid scheduled action status')\n}\n\nexport type ScheduledActionType = 'takedown'\nexport type ScheduledActionStatus =\n | 'pending'\n | 'executed'\n | 'cancelled'\n | 'failed'\n\nconst scheduledActionTypes = new Set(['takedown'])\nconst scheduledActionStatuses = new Set([\n 'pending',\n 'executed',\n 'cancelled',\n 'failed',\n])\n"]}
@@ -36,7 +36,7 @@ export declare class EventPusher {
36
36
  };
37
37
  });
38
38
  start(): void;
39
- get takedowns(): RepoPushEventType[];
39
+ getTakedownServices(targetServices: Set<string>): RepoPushEventType[];
40
40
  poll(state: PollState, fn: () => Promise<void>): void;
41
41
  processAll(): Promise<void>;
42
42
  destroy(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"event-pusher.d.ts","sourceRoot":"","sources":["../../src/daemon/event-pusher.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAEvC,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAChC,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAA;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAA;AAQhE,KAAK,SAAS,GAAG;IACf,KAAK,CAAC,EAAE,MAAM,CAAC,OAAO,CAAA;IACtB,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB,CAAA;AAED,KAAK,WAAW,GAAG;IACjB,OAAO,EAAE;QACP,aAAa,EAAE,MAAM,CAAA;KACtB,CAAA;CACF,CAAA;AAED,KAAK,OAAO,GAAG;IACb,KAAK,EAAE,QAAQ,CAAA;IACf,GAAG,EAAE,MAAM,CAAA;CACZ,CAAA;AAED,qBAAa,WAAW;IAiBb,EAAE,EAAE,QAAQ;IACZ,iBAAiB,EAAE,CACxB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,KACX,OAAO,CAAC,WAAW,CAAC;IApB3B,SAAS,UAAQ;IAEjB,aAAa,EAAE,SAAS,CAEvB;IACD,eAAe,EAAE,SAAS,CAEzB;IACD,aAAa,EAAE,SAAS,CAEvB;IAED,OAAO,EAAE,OAAO,GAAG,SAAS,CAAA;IAC5B,GAAG,EAAE,OAAO,GAAG,SAAS,CAAA;gBAGf,EAAE,EAAE,QAAQ,EACZ,iBAAiB,EAAE,CACxB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,KACX,OAAO,CAAC,WAAW,CAAC,EACzB,QAAQ,EAAE;QACR,OAAO,CAAC,EAAE;YACR,GAAG,EAAE,MAAM,CAAA;YACX,GAAG,EAAE,MAAM,CAAA;SACZ,CAAA;QACD,GAAG,CAAC,EAAE;YACJ,GAAG,EAAE,MAAM,CAAA;YACX,GAAG,EAAE,MAAM,CAAA;SACZ,CAAA;KACF;IAgBH,KAAK;IAML,IAAI,SAAS,IAAI,iBAAiB,EAAE,CAKnC;IAED,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC;IAWxC,UAAU;IAWV,OAAO;IAeP,cAAc;IAYd,gBAAgB;IAYhB,cAAc;YAYN,sBAAsB;IAgC9B,gBAAgB,CAAC,EAAE,EAAE,MAAM;IAsC3B,kBAAkB,CAAC,EAAE,EAAE,MAAM;IAuC7B,gBAAgB,CAAC,EAAE,EAAE,MAAM;IA4B3B,oBAAoB,CACxB,KAAK,EAAE,QAAQ,EACf,KAAK,EAAE,UAAU,CAAC,aAAa,CAAC,EAChC,SAAS,EAAE,OAAO;IAkBd,gBAAgB,CACpB,UAAU,EAAE,UAAU,CAAC,aAAa,CAAC,EAAE,EACvC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI;CAsB9B"}
1
+ {"version":3,"file":"event-pusher.d.ts","sourceRoot":"","sources":["../../src/daemon/event-pusher.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAEvC,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAChC,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAA;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAA;AAQhE,KAAK,SAAS,GAAG;IACf,KAAK,CAAC,EAAE,MAAM,CAAC,OAAO,CAAA;IACtB,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB,CAAA;AAED,KAAK,WAAW,GAAG;IACjB,OAAO,EAAE;QACP,aAAa,EAAE,MAAM,CAAA;KACtB,CAAA;CACF,CAAA;AAED,KAAK,OAAO,GAAG;IACb,KAAK,EAAE,QAAQ,CAAA;IACf,GAAG,EAAE,MAAM,CAAA;CACZ,CAAA;AAED,qBAAa,WAAW;IAiBb,EAAE,EAAE,QAAQ;IACZ,iBAAiB,EAAE,CACxB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,KACX,OAAO,CAAC,WAAW,CAAC;IApB3B,SAAS,UAAQ;IAEjB,aAAa,EAAE,SAAS,CAEvB;IACD,eAAe,EAAE,SAAS,CAEzB;IACD,aAAa,EAAE,SAAS,CAEvB;IAED,OAAO,EAAE,OAAO,GAAG,SAAS,CAAA;IAC5B,GAAG,EAAE,OAAO,GAAG,SAAS,CAAA;gBAGf,EAAE,EAAE,QAAQ,EACZ,iBAAiB,EAAE,CACxB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,KACX,OAAO,CAAC,WAAW,CAAC,EACzB,QAAQ,EAAE;QACR,OAAO,CAAC,EAAE;YACR,GAAG,EAAE,MAAM,CAAA;YACX,GAAG,EAAE,MAAM,CAAA;SACZ,CAAA;QACD,GAAG,CAAC,EAAE;YACJ,GAAG,EAAE,MAAM,CAAA;YACX,GAAG,EAAE,MAAM,CAAA;SACZ,CAAA;KACF;IAgBH,KAAK;IASL,mBAAmB,CAAC,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,iBAAiB,EAAE;IAqBrE,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC;IAWxC,UAAU;IAWV,OAAO;IAeP,cAAc;IAYd,gBAAgB;IAYhB,cAAc;YAYN,sBAAsB;IAgC9B,gBAAgB,CAAC,EAAE,EAAE,MAAM;IAsC3B,kBAAkB,CAAC,EAAE,EAAE,MAAM;IAuC7B,gBAAgB,CAAC,EAAE,EAAE,MAAM;IA4B3B,oBAAoB,CACxB,KAAK,EAAE,QAAQ,EACf,KAAK,EAAE,UAAU,CAAC,aAAa,CAAC,EAChC,SAAS,EAAE,OAAO;IAkBd,gBAAgB,CACpB,UAAU,EAAE,UAAU,CAAC,aAAa,CAAC,EAAE,EACvC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI;CAsB9B"}
@@ -84,13 +84,25 @@ class EventPusher {
84
84
  this.poll(this.recordPollState, () => this.pushRecordEvents());
85
85
  this.poll(this.blobPollState, () => this.pushBlobEvents());
86
86
  }
87
- get takedowns() {
88
- const takedowns = [];
87
+ // event pusher may be configured with both appview and pds
88
+ // but the takedown may particularly want only one of them
89
+ // unless the target services are specified, we will push to all configured services
90
+ getTakedownServices(targetServices) {
91
+ let configured = [];
89
92
  if (this.pds)
90
- takedowns.push('pds_takedown');
93
+ configured.push('pds_takedown');
91
94
  if (this.appview)
92
- takedowns.push('appview_takedown');
93
- return takedowns;
95
+ configured.push('appview_takedown');
96
+ if (!targetServices.size) {
97
+ return configured;
98
+ }
99
+ if (!targetServices.has('appview')) {
100
+ configured = configured.filter((service) => service !== 'appview_takedown');
101
+ }
102
+ if (!targetServices.has('pds')) {
103
+ configured = configured.filter((service) => service !== 'pds_takedown');
104
+ }
105
+ return configured;
94
106
  }
95
107
  poll(state, fn) {
96
108
  if (this.destroyed)
@@ -1 +1 @@
1
- {"version":3,"file":"event-pusher.js","sourceRoot":"","sources":["../../src/daemon/event-pusher.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from 'node:assert'\nimport { Insertable, Selectable } from 'kysely'\nimport { AtpAgent } from '@atproto/api'\nimport { SECOND } from '@atproto/common'\nimport { Database } from '../db'\nimport { BlobPushEvent } from '../db/schema/blob_push_event'\nimport { RepoPushEventType } from '../db/schema/repo_push_event'\nimport { ids } from '../lexicon/lexicons'\nimport { InputSchema } from '../lexicon/types/com/atproto/admin/updateSubjectStatus'\nimport { dbLogger } from '../logger'\nimport { retryHttp } from '../util'\n\ntype EventSubject = InputSchema['subject']\n\ntype PollState = {\n timer?: NodeJS.Timeout\n promise: Promise<void>\n}\n\ntype AuthHeaders = {\n headers: {\n authorization: string\n }\n}\n\ntype Service = {\n agent: AtpAgent\n did: string\n}\n\nexport class EventPusher {\n destroyed = false\n\n repoPollState: PollState = {\n promise: Promise.resolve(),\n }\n recordPollState: PollState = {\n promise: Promise.resolve(),\n }\n blobPollState: PollState = {\n promise: Promise.resolve(),\n }\n\n appview: Service | undefined\n pds: Service | undefined\n\n constructor(\n public db: Database,\n public createAuthHeaders: (\n aud: string,\n method: string,\n ) => Promise<AuthHeaders>,\n services: {\n appview?: {\n url: string\n did: string\n }\n pds?: {\n url: string\n did: string\n }\n },\n ) {\n if (services.appview) {\n this.appview = {\n agent: new AtpAgent({ service: services.appview.url }),\n did: services.appview.did,\n }\n }\n if (services.pds) {\n this.pds = {\n agent: new AtpAgent({ service: services.pds.url }),\n did: services.pds.did,\n }\n }\n }\n\n start() {\n this.poll(this.repoPollState, () => this.pushRepoEvents())\n this.poll(this.recordPollState, () => this.pushRecordEvents())\n this.poll(this.blobPollState, () => this.pushBlobEvents())\n }\n\n get takedowns(): RepoPushEventType[] {\n const takedowns: RepoPushEventType[] = []\n if (this.pds) takedowns.push('pds_takedown')\n if (this.appview) takedowns.push('appview_takedown')\n return takedowns\n }\n\n poll(state: PollState, fn: () => Promise<void>) {\n if (this.destroyed) return\n state.promise = fn()\n .catch((err) => {\n dbLogger.error({ err }, 'event push failed')\n })\n .finally(() => {\n state.timer = setTimeout(() => this.poll(state, fn), 30 * SECOND)\n })\n }\n\n async processAll() {\n await Promise.all([\n this.pushRepoEvents(),\n this.pushRecordEvents(),\n this.pushBlobEvents(),\n this.repoPollState.promise,\n this.recordPollState.promise,\n this.blobPollState.promise,\n ])\n }\n\n async destroy() {\n this.destroyed = true\n const destroyState = (state: PollState) => {\n if (state.timer) {\n clearTimeout(state.timer)\n }\n return state.promise\n }\n await Promise.all([\n destroyState(this.repoPollState),\n destroyState(this.recordPollState),\n destroyState(this.blobPollState),\n ])\n }\n\n async pushRepoEvents() {\n const toPush = await this.db.db\n .selectFrom('repo_push_event')\n .select('id')\n .forUpdate()\n .skipLocked()\n .where('confirmedAt', 'is', null)\n .where('attempts', '<', 10)\n .execute()\n await Promise.all(toPush.map((evt) => this.attemptRepoEvent(evt.id)))\n }\n\n async pushRecordEvents() {\n const toPush = await this.db.db\n .selectFrom('record_push_event')\n .select('id')\n .forUpdate()\n .skipLocked()\n .where('confirmedAt', 'is', null)\n .where('attempts', '<', 10)\n .execute()\n await Promise.all(toPush.map((evt) => this.attemptRecordEvent(evt.id)))\n }\n\n async pushBlobEvents() {\n const toPush = await this.db.db\n .selectFrom('blob_push_event')\n .select('id')\n .forUpdate()\n .skipLocked()\n .where('confirmedAt', 'is', null)\n .where('attempts', '<', 10)\n .execute()\n await Promise.all(toPush.map((evt) => this.attemptBlobEvent(evt.id)))\n }\n\n private async updateSubjectOnService(\n service: Service,\n subject: EventSubject,\n takedownRef: string | null,\n ): Promise<boolean> {\n const auth = await this.createAuthHeaders(\n service.did,\n ids.ComAtprotoAdminUpdateSubjectStatus,\n )\n try {\n await retryHttp(() =>\n service.agent.com.atproto.admin.updateSubjectStatus(\n {\n subject,\n takedown: {\n applied: !!takedownRef,\n ref: takedownRef ?? undefined,\n },\n },\n {\n ...auth,\n encoding: 'application/json',\n },\n ),\n )\n return true\n } catch (err) {\n dbLogger.error({ err, subject, takedownRef }, 'failed to push out event')\n return false\n }\n }\n\n async attemptRepoEvent(id: number) {\n await this.db.transaction(async (dbTxn) => {\n const evt = await dbTxn.db\n .selectFrom('repo_push_event')\n .selectAll()\n .forUpdate()\n .skipLocked()\n .where('id', '=', id)\n .where('confirmedAt', 'is', null)\n .executeTakeFirst()\n if (!evt) return\n const service = evt.eventType === 'pds_takedown' ? this.pds : this.appview\n assert(service)\n const subject = {\n $type: 'com.atproto.admin.defs#repoRef',\n did: evt.subjectDid,\n }\n const succeeded = await this.updateSubjectOnService(\n service,\n subject,\n evt.takedownRef,\n )\n await dbTxn.db\n .updateTable('repo_push_event')\n .set(\n succeeded\n ? { confirmedAt: new Date() }\n : {\n lastAttempted: new Date(),\n attempts: (evt.attempts ?? 0) + 1,\n },\n )\n .where('subjectDid', '=', evt.subjectDid)\n .where('eventType', '=', evt.eventType)\n .execute()\n })\n }\n\n async attemptRecordEvent(id: number) {\n await this.db.transaction(async (dbTxn) => {\n const evt = await dbTxn.db\n .selectFrom('record_push_event')\n .selectAll()\n .forUpdate()\n .skipLocked()\n .where('id', '=', id)\n .where('confirmedAt', 'is', null)\n .executeTakeFirst()\n if (!evt) return\n const service = evt.eventType === 'pds_takedown' ? this.pds : this.appview\n assert(service)\n const subject = {\n $type: 'com.atproto.repo.strongRef',\n uri: evt.subjectUri,\n cid: evt.subjectCid,\n }\n const succeeded = await this.updateSubjectOnService(\n service,\n subject,\n evt.takedownRef,\n )\n await dbTxn.db\n .updateTable('record_push_event')\n .set(\n succeeded\n ? { confirmedAt: new Date() }\n : {\n lastAttempted: new Date(),\n attempts: (evt.attempts ?? 0) + 1,\n },\n )\n .where('subjectUri', '=', evt.subjectUri)\n .where('eventType', '=', evt.eventType)\n .execute()\n })\n }\n\n async attemptBlobEvent(id: number) {\n await this.db.transaction(async (dbTxn) => {\n const evt = await dbTxn.db\n .selectFrom('blob_push_event')\n .selectAll()\n .forUpdate()\n .skipLocked()\n .where('id', '=', id)\n .where('confirmedAt', 'is', null)\n .executeTakeFirst()\n if (!evt) return\n\n const service = evt.eventType === 'pds_takedown' ? this.pds : this.appview\n assert(service)\n const subject = {\n $type: 'com.atproto.admin.defs#repoBlobRef',\n did: evt.subjectDid,\n cid: evt.subjectBlobCid,\n }\n const succeeded = await this.updateSubjectOnService(\n service,\n subject,\n evt.takedownRef,\n )\n await this.markBlobEventAttempt(dbTxn, evt, succeeded)\n })\n }\n\n async markBlobEventAttempt(\n dbTxn: Database,\n event: Selectable<BlobPushEvent>,\n succeeded: boolean,\n ) {\n await dbTxn.db\n .updateTable('blob_push_event')\n .set(\n succeeded\n ? { confirmedAt: new Date() }\n : {\n lastAttempted: new Date(),\n attempts: (event.attempts ?? 0) + 1,\n },\n )\n .where('subjectDid', '=', event.subjectDid)\n .where('subjectBlobCid', '=', event.subjectBlobCid)\n .where('eventType', '=', event.eventType)\n .execute()\n }\n\n async logBlobPushEvent(\n blobValues: Insertable<BlobPushEvent>[],\n takedownRef?: string | null,\n ) {\n return this.db.db\n .insertInto('blob_push_event')\n .values(blobValues)\n .onConflict((oc) =>\n oc.columns(['subjectDid', 'subjectBlobCid', 'eventType']).doUpdateSet({\n takedownRef,\n confirmedAt: null,\n attempts: 0,\n lastAttempted: null,\n }),\n )\n .returning([\n 'id',\n 'subjectDid',\n 'subjectUri',\n 'subjectBlobCid',\n 'eventType',\n ])\n .execute()\n }\n}\n"]}
1
+ {"version":3,"file":"event-pusher.js","sourceRoot":"","sources":["../../src/daemon/event-pusher.ts"],"names":[],"mappings":";;;;;;AAAA,8DAAgC;AAEhC,sCAAuC;AACvC,4CAAwC;AAIxC,kDAAyC;AAEzC,sCAAoC;AACpC,kCAAmC;AAoBnC,MAAa,WAAW;IAgBtB,YACS,EAAY,EACZ,iBAGkB,EACzB,QASC;QAdD;;;;mBAAO,EAAE;WAAU;QACnB;;;;mBAAO,iBAAiB;WAGC;QApB3B;;;;mBAAY,KAAK;WAAA;QAEjB;;;;mBAA2B;gBACzB,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE;aAC3B;WAAA;QACD;;;;mBAA6B;gBAC3B,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE;aAC3B;WAAA;QACD;;;;mBAA2B;gBACzB,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE;aAC3B;WAAA;QAED;;;;;WAA4B;QAC5B;;;;;WAAwB;QAmBtB,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;YACrB,IAAI,CAAC,OAAO,GAAG;gBACb,KAAK,EAAE,IAAI,cAAQ,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;gBACtD,GAAG,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG;aAC1B,CAAA;QACH,CAAC;QACD,IAAI,QAAQ,CAAC,GAAG,EAAE,CAAC;YACjB,IAAI,CAAC,GAAG,GAAG;gBACT,KAAK,EAAE,IAAI,cAAQ,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;gBAClD,GAAG,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG;aACtB,CAAA;QACH,CAAC;IACH,CAAC;IAED,KAAK;QACH,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,CAAA;QAC1D,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAA;QAC9D,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,CAAA;IAC5D,CAAC;IAED,2DAA2D;IAC3D,0DAA0D;IAC1D,oFAAoF;IACpF,mBAAmB,CAAC,cAA2B;QAC7C,IAAI,UAAU,GAAwB,EAAE,CAAA;QACxC,IAAI,IAAI,CAAC,GAAG;YAAE,UAAU,CAAC,IAAI,CAAC,cAAc,CAAC,CAAA;QAC7C,IAAI,IAAI,CAAC,OAAO;YAAE,UAAU,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAA;QAErD,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;YACzB,OAAO,UAAU,CAAA;QACnB,CAAC;QAED,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YACnC,UAAU,GAAG,UAAU,CAAC,MAAM,CAC5B,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,KAAK,kBAAkB,CAC5C,CAAA;QACH,CAAC;QACD,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/B,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,KAAK,cAAc,CAAC,CAAA;QACzE,CAAC;QAED,OAAO,UAAU,CAAA;IACnB,CAAC;IAED,IAAI,CAAC,KAAgB,EAAE,EAAuB;QAC5C,IAAI,IAAI,CAAC,SAAS;YAAE,OAAM;QAC1B,KAAK,CAAC,OAAO,GAAG,EAAE,EAAE;aACjB,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACb,iBAAQ,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,mBAAmB,CAAC,CAAA;QAC9C,CAAC,CAAC;aACD,OAAO,CAAC,GAAG,EAAE;YACZ,KAAK,CAAC,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE,GAAG,eAAM,CAAC,CAAA;QACnE,CAAC,CAAC,CAAA;IACN,CAAC;IAED,KAAK,CAAC,UAAU;QACd,MAAM,OAAO,CAAC,GAAG,CAAC;YAChB,IAAI,CAAC,cAAc,EAAE;YACrB,IAAI,CAAC,gBAAgB,EAAE;YACvB,IAAI,CAAC,cAAc,EAAE;YACrB,IAAI,CAAC,aAAa,CAAC,OAAO;YAC1B,IAAI,CAAC,eAAe,CAAC,OAAO;YAC5B,IAAI,CAAC,aAAa,CAAC,OAAO;SAC3B,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,OAAO;QACX,IAAI,CAAC,SAAS,GAAG,IAAI,CAAA;QACrB,MAAM,YAAY,GAAG,CAAC,KAAgB,EAAE,EAAE;YACxC,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;gBAChB,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;YAC3B,CAAC;YACD,OAAO,KAAK,CAAC,OAAO,CAAA;QACtB,CAAC,CAAA;QACD,MAAM,OAAO,CAAC,GAAG,CAAC;YAChB,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC;YAChC,YAAY,CAAC,IAAI,CAAC,eAAe,CAAC;YAClC,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC;SACjC,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,cAAc;QAClB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,EAAE;aAC5B,UAAU,CAAC,iBAAiB,CAAC;aAC7B,MAAM,CAAC,IAAI,CAAC;aACZ,SAAS,EAAE;aACX,UAAU,EAAE;aACZ,KAAK,CAAC,aAAa,EAAE,IAAI,EAAE,IAAI,CAAC;aAChC,KAAK,CAAC,UAAU,EAAE,GAAG,EAAE,EAAE,CAAC;aAC1B,OAAO,EAAE,CAAA;QACZ,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IACvE,CAAC;IAED,KAAK,CAAC,gBAAgB;QACpB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,EAAE;aAC5B,UAAU,CAAC,mBAAmB,CAAC;aAC/B,MAAM,CAAC,IAAI,CAAC;aACZ,SAAS,EAAE;aACX,UAAU,EAAE;aACZ,KAAK,CAAC,aAAa,EAAE,IAAI,EAAE,IAAI,CAAC;aAChC,KAAK,CAAC,UAAU,EAAE,GAAG,EAAE,EAAE,CAAC;aAC1B,OAAO,EAAE,CAAA;QACZ,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IACzE,CAAC;IAED,KAAK,CAAC,cAAc;QAClB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,EAAE;aAC5B,UAAU,CAAC,iBAAiB,CAAC;aAC7B,MAAM,CAAC,IAAI,CAAC;aACZ,SAAS,EAAE;aACX,UAAU,EAAE;aACZ,KAAK,CAAC,aAAa,EAAE,IAAI,EAAE,IAAI,CAAC;aAChC,KAAK,CAAC,UAAU,EAAE,GAAG,EAAE,EAAE,CAAC;aAC1B,OAAO,EAAE,CAAA;QACZ,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IACvE,CAAC;IAEO,KAAK,CAAC,sBAAsB,CAClC,OAAgB,EAChB,OAAqB,EACrB,WAA0B;QAE1B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,iBAAiB,CACvC,OAAO,CAAC,GAAG,EACX,cAAG,CAAC,kCAAkC,CACvC,CAAA;QACD,IAAI,CAAC;YACH,MAAM,IAAA,gBAAS,EAAC,GAAG,EAAE,CACnB,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,mBAAmB,CACjD;gBACE,OAAO;gBACP,QAAQ,EAAE;oBACR,OAAO,EAAE,CAAC,CAAC,WAAW;oBACtB,GAAG,EAAE,WAAW,IAAI,SAAS;iBAC9B;aACF,EACD;gBACE,GAAG,IAAI;gBACP,QAAQ,EAAE,kBAAkB;aAC7B,CACF,CACF,CAAA;YACD,OAAO,IAAI,CAAA;QACb,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,iBAAQ,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,0BAA0B,CAAC,CAAA;YACzE,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,EAAU;QAC/B,MAAM,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YACxC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,EAAE;iBACvB,UAAU,CAAC,iBAAiB,CAAC;iBAC7B,SAAS,EAAE;iBACX,SAAS,EAAE;iBACX,UAAU,EAAE;iBACZ,KAAK,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC;iBACpB,KAAK,CAAC,aAAa,EAAE,IAAI,EAAE,IAAI,CAAC;iBAChC,gBAAgB,EAAE,CAAA;YACrB,IAAI,CAAC,GAAG;gBAAE,OAAM;YAChB,MAAM,OAAO,GAAG,GAAG,CAAC,SAAS,KAAK,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAA;YAC1E,IAAA,qBAAM,EAAC,OAAO,CAAC,CAAA;YACf,MAAM,OAAO,GAAG;gBACd,KAAK,EAAE,gCAAgC;gBACvC,GAAG,EAAE,GAAG,CAAC,UAAU;aACpB,CAAA;YACD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,sBAAsB,CACjD,OAAO,EACP,OAAO,EACP,GAAG,CAAC,WAAW,CAChB,CAAA;YACD,MAAM,KAAK,CAAC,EAAE;iBACX,WAAW,CAAC,iBAAiB,CAAC;iBAC9B,GAAG,CACF,SAAS;gBACP,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,IAAI,EAAE,EAAE;gBAC7B,CAAC,CAAC;oBACE,aAAa,EAAE,IAAI,IAAI,EAAE;oBACzB,QAAQ,EAAE,CAAC,GAAG,CAAC,QAAQ,IAAI,CAAC,CAAC,GAAG,CAAC;iBAClC,CACN;iBACA,KAAK,CAAC,YAAY,EAAE,GAAG,EAAE,GAAG,CAAC,UAAU,CAAC;iBACxC,KAAK,CAAC,WAAW,EAAE,GAAG,EAAE,GAAG,CAAC,SAAS,CAAC;iBACtC,OAAO,EAAE,CAAA;QACd,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,EAAU;QACjC,MAAM,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YACxC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,EAAE;iBACvB,UAAU,CAAC,mBAAmB,CAAC;iBAC/B,SAAS,EAAE;iBACX,SAAS,EAAE;iBACX,UAAU,EAAE;iBACZ,KAAK,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC;iBACpB,KAAK,CAAC,aAAa,EAAE,IAAI,EAAE,IAAI,CAAC;iBAChC,gBAAgB,EAAE,CAAA;YACrB,IAAI,CAAC,GAAG;gBAAE,OAAM;YAChB,MAAM,OAAO,GAAG,GAAG,CAAC,SAAS,KAAK,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAA;YAC1E,IAAA,qBAAM,EAAC,OAAO,CAAC,CAAA;YACf,MAAM,OAAO,GAAG;gBACd,KAAK,EAAE,4BAA4B;gBACnC,GAAG,EAAE,GAAG,CAAC,UAAU;gBACnB,GAAG,EAAE,GAAG,CAAC,UAAU;aACpB,CAAA;YACD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,sBAAsB,CACjD,OAAO,EACP,OAAO,EACP,GAAG,CAAC,WAAW,CAChB,CAAA;YACD,MAAM,KAAK,CAAC,EAAE;iBACX,WAAW,CAAC,mBAAmB,CAAC;iBAChC,GAAG,CACF,SAAS;gBACP,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,IAAI,EAAE,EAAE;gBAC7B,CAAC,CAAC;oBACE,aAAa,EAAE,IAAI,IAAI,EAAE;oBACzB,QAAQ,EAAE,CAAC,GAAG,CAAC,QAAQ,IAAI,CAAC,CAAC,GAAG,CAAC;iBAClC,CACN;iBACA,KAAK,CAAC,YAAY,EAAE,GAAG,EAAE,GAAG,CAAC,UAAU,CAAC;iBACxC,KAAK,CAAC,WAAW,EAAE,GAAG,EAAE,GAAG,CAAC,SAAS,CAAC;iBACtC,OAAO,EAAE,CAAA;QACd,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,EAAU;QAC/B,MAAM,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YACxC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,EAAE;iBACvB,UAAU,CAAC,iBAAiB,CAAC;iBAC7B,SAAS,EAAE;iBACX,SAAS,EAAE;iBACX,UAAU,EAAE;iBACZ,KAAK,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC;iBACpB,KAAK,CAAC,aAAa,EAAE,IAAI,EAAE,IAAI,CAAC;iBAChC,gBAAgB,EAAE,CAAA;YACrB,IAAI,CAAC,GAAG;gBAAE,OAAM;YAEhB,MAAM,OAAO,GAAG,GAAG,CAAC,SAAS,KAAK,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAA;YAC1E,IAAA,qBAAM,EAAC,OAAO,CAAC,CAAA;YACf,MAAM,OAAO,GAAG;gBACd,KAAK,EAAE,oCAAoC;gBAC3C,GAAG,EAAE,GAAG,CAAC,UAAU;gBACnB,GAAG,EAAE,GAAG,CAAC,cAAc;aACxB,CAAA;YACD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,sBAAsB,CACjD,OAAO,EACP,OAAO,EACP,GAAG,CAAC,WAAW,CAChB,CAAA;YACD,MAAM,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,GAAG,EAAE,SAAS,CAAC,CAAA;QACxD,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,oBAAoB,CACxB,KAAe,EACf,KAAgC,EAChC,SAAkB;QAElB,MAAM,KAAK,CAAC,EAAE;aACX,WAAW,CAAC,iBAAiB,CAAC;aAC9B,GAAG,CACF,SAAS;YACP,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,IAAI,EAAE,EAAE;YAC7B,CAAC,CAAC;gBACE,aAAa,EAAE,IAAI,IAAI,EAAE;gBACzB,QAAQ,EAAE,CAAC,KAAK,CAAC,QAAQ,IAAI,CAAC,CAAC,GAAG,CAAC;aACpC,CACN;aACA,KAAK,CAAC,YAAY,EAAE,GAAG,EAAE,KAAK,CAAC,UAAU,CAAC;aAC1C,KAAK,CAAC,gBAAgB,EAAE,GAAG,EAAE,KAAK,CAAC,cAAc,CAAC;aAClD,KAAK,CAAC,WAAW,EAAE,GAAG,EAAE,KAAK,CAAC,SAAS,CAAC;aACxC,OAAO,EAAE,CAAA;IACd,CAAC;IAED,KAAK,CAAC,gBAAgB,CACpB,UAAuC,EACvC,WAA2B;QAE3B,OAAO,IAAI,CAAC,EAAE,CAAC,EAAE;aACd,UAAU,CAAC,iBAAiB,CAAC;aAC7B,MAAM,CAAC,UAAU,CAAC;aAClB,UAAU,CAAC,CAAC,EAAE,EAAE,EAAE,CACjB,EAAE,CAAC,OAAO,CAAC,CAAC,YAAY,EAAE,gBAAgB,EAAE,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC;YACpE,WAAW;YACX,WAAW,EAAE,IAAI;YACjB,QAAQ,EAAE,CAAC;YACX,aAAa,EAAE,IAAI;SACpB,CAAC,CACH;aACA,SAAS,CAAC;YACT,IAAI;YACJ,YAAY;YACZ,YAAY;YACZ,gBAAgB;YAChB,WAAW;SACZ,CAAC;aACD,OAAO,EAAE,CAAA;IACd,CAAC;CACF;AA5UD,kCA4UC","sourcesContent":["import assert from 'node:assert'\nimport { Insertable, Selectable } from 'kysely'\nimport { AtpAgent } from '@atproto/api'\nimport { SECOND } from '@atproto/common'\nimport { Database } from '../db'\nimport { BlobPushEvent } from '../db/schema/blob_push_event'\nimport { RepoPushEventType } from '../db/schema/repo_push_event'\nimport { ids } from '../lexicon/lexicons'\nimport { InputSchema } from '../lexicon/types/com/atproto/admin/updateSubjectStatus'\nimport { dbLogger } from '../logger'\nimport { retryHttp } from '../util'\n\ntype EventSubject = InputSchema['subject']\n\ntype PollState = {\n timer?: NodeJS.Timeout\n promise: Promise<void>\n}\n\ntype AuthHeaders = {\n headers: {\n authorization: string\n }\n}\n\ntype Service = {\n agent: AtpAgent\n did: string\n}\n\nexport class EventPusher {\n destroyed = false\n\n repoPollState: PollState = {\n promise: Promise.resolve(),\n }\n recordPollState: PollState = {\n promise: Promise.resolve(),\n }\n blobPollState: PollState = {\n promise: Promise.resolve(),\n }\n\n appview: Service | undefined\n pds: Service | undefined\n\n constructor(\n public db: Database,\n public createAuthHeaders: (\n aud: string,\n method: string,\n ) => Promise<AuthHeaders>,\n services: {\n appview?: {\n url: string\n did: string\n }\n pds?: {\n url: string\n did: string\n }\n },\n ) {\n if (services.appview) {\n this.appview = {\n agent: new AtpAgent({ service: services.appview.url }),\n did: services.appview.did,\n }\n }\n if (services.pds) {\n this.pds = {\n agent: new AtpAgent({ service: services.pds.url }),\n did: services.pds.did,\n }\n }\n }\n\n start() {\n this.poll(this.repoPollState, () => this.pushRepoEvents())\n this.poll(this.recordPollState, () => this.pushRecordEvents())\n this.poll(this.blobPollState, () => this.pushBlobEvents())\n }\n\n // event pusher may be configured with both appview and pds\n // but the takedown may particularly want only one of them\n // unless the target services are specified, we will push to all configured services\n getTakedownServices(targetServices: Set<string>): RepoPushEventType[] {\n let configured: RepoPushEventType[] = []\n if (this.pds) configured.push('pds_takedown')\n if (this.appview) configured.push('appview_takedown')\n\n if (!targetServices.size) {\n return configured\n }\n\n if (!targetServices.has('appview')) {\n configured = configured.filter(\n (service) => service !== 'appview_takedown',\n )\n }\n if (!targetServices.has('pds')) {\n configured = configured.filter((service) => service !== 'pds_takedown')\n }\n\n return configured\n }\n\n poll(state: PollState, fn: () => Promise<void>) {\n if (this.destroyed) return\n state.promise = fn()\n .catch((err) => {\n dbLogger.error({ err }, 'event push failed')\n })\n .finally(() => {\n state.timer = setTimeout(() => this.poll(state, fn), 30 * SECOND)\n })\n }\n\n async processAll() {\n await Promise.all([\n this.pushRepoEvents(),\n this.pushRecordEvents(),\n this.pushBlobEvents(),\n this.repoPollState.promise,\n this.recordPollState.promise,\n this.blobPollState.promise,\n ])\n }\n\n async destroy() {\n this.destroyed = true\n const destroyState = (state: PollState) => {\n if (state.timer) {\n clearTimeout(state.timer)\n }\n return state.promise\n }\n await Promise.all([\n destroyState(this.repoPollState),\n destroyState(this.recordPollState),\n destroyState(this.blobPollState),\n ])\n }\n\n async pushRepoEvents() {\n const toPush = await this.db.db\n .selectFrom('repo_push_event')\n .select('id')\n .forUpdate()\n .skipLocked()\n .where('confirmedAt', 'is', null)\n .where('attempts', '<', 10)\n .execute()\n await Promise.all(toPush.map((evt) => this.attemptRepoEvent(evt.id)))\n }\n\n async pushRecordEvents() {\n const toPush = await this.db.db\n .selectFrom('record_push_event')\n .select('id')\n .forUpdate()\n .skipLocked()\n .where('confirmedAt', 'is', null)\n .where('attempts', '<', 10)\n .execute()\n await Promise.all(toPush.map((evt) => this.attemptRecordEvent(evt.id)))\n }\n\n async pushBlobEvents() {\n const toPush = await this.db.db\n .selectFrom('blob_push_event')\n .select('id')\n .forUpdate()\n .skipLocked()\n .where('confirmedAt', 'is', null)\n .where('attempts', '<', 10)\n .execute()\n await Promise.all(toPush.map((evt) => this.attemptBlobEvent(evt.id)))\n }\n\n private async updateSubjectOnService(\n service: Service,\n subject: EventSubject,\n takedownRef: string | null,\n ): Promise<boolean> {\n const auth = await this.createAuthHeaders(\n service.did,\n ids.ComAtprotoAdminUpdateSubjectStatus,\n )\n try {\n await retryHttp(() =>\n service.agent.com.atproto.admin.updateSubjectStatus(\n {\n subject,\n takedown: {\n applied: !!takedownRef,\n ref: takedownRef ?? undefined,\n },\n },\n {\n ...auth,\n encoding: 'application/json',\n },\n ),\n )\n return true\n } catch (err) {\n dbLogger.error({ err, subject, takedownRef }, 'failed to push out event')\n return false\n }\n }\n\n async attemptRepoEvent(id: number) {\n await this.db.transaction(async (dbTxn) => {\n const evt = await dbTxn.db\n .selectFrom('repo_push_event')\n .selectAll()\n .forUpdate()\n .skipLocked()\n .where('id', '=', id)\n .where('confirmedAt', 'is', null)\n .executeTakeFirst()\n if (!evt) return\n const service = evt.eventType === 'pds_takedown' ? this.pds : this.appview\n assert(service)\n const subject = {\n $type: 'com.atproto.admin.defs#repoRef',\n did: evt.subjectDid,\n }\n const succeeded = await this.updateSubjectOnService(\n service,\n subject,\n evt.takedownRef,\n )\n await dbTxn.db\n .updateTable('repo_push_event')\n .set(\n succeeded\n ? { confirmedAt: new Date() }\n : {\n lastAttempted: new Date(),\n attempts: (evt.attempts ?? 0) + 1,\n },\n )\n .where('subjectDid', '=', evt.subjectDid)\n .where('eventType', '=', evt.eventType)\n .execute()\n })\n }\n\n async attemptRecordEvent(id: number) {\n await this.db.transaction(async (dbTxn) => {\n const evt = await dbTxn.db\n .selectFrom('record_push_event')\n .selectAll()\n .forUpdate()\n .skipLocked()\n .where('id', '=', id)\n .where('confirmedAt', 'is', null)\n .executeTakeFirst()\n if (!evt) return\n const service = evt.eventType === 'pds_takedown' ? this.pds : this.appview\n assert(service)\n const subject = {\n $type: 'com.atproto.repo.strongRef',\n uri: evt.subjectUri,\n cid: evt.subjectCid,\n }\n const succeeded = await this.updateSubjectOnService(\n service,\n subject,\n evt.takedownRef,\n )\n await dbTxn.db\n .updateTable('record_push_event')\n .set(\n succeeded\n ? { confirmedAt: new Date() }\n : {\n lastAttempted: new Date(),\n attempts: (evt.attempts ?? 0) + 1,\n },\n )\n .where('subjectUri', '=', evt.subjectUri)\n .where('eventType', '=', evt.eventType)\n .execute()\n })\n }\n\n async attemptBlobEvent(id: number) {\n await this.db.transaction(async (dbTxn) => {\n const evt = await dbTxn.db\n .selectFrom('blob_push_event')\n .selectAll()\n .forUpdate()\n .skipLocked()\n .where('id', '=', id)\n .where('confirmedAt', 'is', null)\n .executeTakeFirst()\n if (!evt) return\n\n const service = evt.eventType === 'pds_takedown' ? this.pds : this.appview\n assert(service)\n const subject = {\n $type: 'com.atproto.admin.defs#repoBlobRef',\n did: evt.subjectDid,\n cid: evt.subjectBlobCid,\n }\n const succeeded = await this.updateSubjectOnService(\n service,\n subject,\n evt.takedownRef,\n )\n await this.markBlobEventAttempt(dbTxn, evt, succeeded)\n })\n }\n\n async markBlobEventAttempt(\n dbTxn: Database,\n event: Selectable<BlobPushEvent>,\n succeeded: boolean,\n ) {\n await dbTxn.db\n .updateTable('blob_push_event')\n .set(\n succeeded\n ? { confirmedAt: new Date() }\n : {\n lastAttempted: new Date(),\n attempts: (event.attempts ?? 0) + 1,\n },\n )\n .where('subjectDid', '=', event.subjectDid)\n .where('subjectBlobCid', '=', event.subjectBlobCid)\n .where('eventType', '=', event.eventType)\n .execute()\n }\n\n async logBlobPushEvent(\n blobValues: Insertable<BlobPushEvent>[],\n takedownRef?: string | null,\n ) {\n return this.db.db\n .insertInto('blob_push_event')\n .values(blobValues)\n .onConflict((oc) =>\n oc.columns(['subjectDid', 'subjectBlobCid', 'eventType']).doUpdateSet({\n takedownRef,\n confirmedAt: null,\n attempts: 0,\n lastAttempted: null,\n }),\n )\n .returning([\n 'id',\n 'subjectDid',\n 'subjectUri',\n 'subjectBlobCid',\n 'eventType',\n ])\n .execute()\n }\n}\n"]}
@@ -20,7 +20,11 @@ export declare class ScheduledActionProcessor {
20
20
  poll(): void;
21
21
  destroy(): Promise<void>;
22
22
  executeScheduledAction(actionId: number): Promise<void>;
23
- performTakedown({ action, event, modTool, moderationTxn, settingService, }: {
23
+ performTakedown({ email, action, event, modTool, moderationTxn, settingService, }: {
24
+ email: {
25
+ subject: string;
26
+ content: string;
27
+ };
24
28
  action: Selectable<ScheduledAction>;
25
29
  event: ModEventType;
26
30
  modTool: ModTool | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"scheduled-action-processor.d.ts","sourceRoot":"","sources":["../../src/daemon/scheduled-action-processor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAMnC,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,EAEL,OAAO,EACR,MAAM,8CAA8C,CAAA;AAErD,OAAO,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAA;AAE5E,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,EAAE,6BAA6B,EAAE,MAAM,6BAA6B,CAAA;AAC3E,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAE1E,qBAAa,wBAAwB;IAMjC,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,sBAAsB;IAThC,SAAS,UAAQ;IACjB,iBAAiB,EAAE,OAAO,CAAC,IAAI,CAAC,CAAoB;IACpD,KAAK,CAAC,EAAE,MAAM,CAAC,OAAO,CAAA;gBAGZ,EAAE,EAAE,QAAQ,EACZ,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,qBAAqB,EACrC,UAAU,EAAE,wBAAwB,EACpC,sBAAsB,EAAE,6BAA6B;IAG/D,KAAK;IAIL,IAAI;IAWE,OAAO;IASP,sBAAsB,CAAC,QAAQ,EAAE,MAAM;IAuFvC,eAAe,CAAC,EACpB,MAAM,EACN,KAAK,EACL,OAAO,EACP,aAAa,EACb,cAAc,GACf,EAAE;QACD,MAAM,EAAE,UAAU,CAAC,eAAe,CAAC,CAAA;QACnC,KAAK,EAAE,YAAY,CAAA;QACnB,OAAO,EAAE,OAAO,GAAG,SAAS,CAAA;QAE5B,aAAa,EAAE,iBAAiB,CAAA;QAChC,cAAc,EAAE,cAAc,CAAA;KAC/B;;;;IAyCK,8BAA8B;CAqCrC"}
1
+ {"version":3,"file":"scheduled-action-processor.d.ts","sourceRoot":"","sources":["../../src/daemon/scheduled-action-processor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAMnC,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,EAEL,OAAO,EACR,MAAM,8CAA8C,CAAA;AAErD,OAAO,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAA;AAE5E,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,EAAE,6BAA6B,EAAE,MAAM,6BAA6B,CAAA;AAC3E,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAG1E,qBAAa,wBAAwB;IAMjC,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,sBAAsB;IAThC,SAAS,UAAQ;IACjB,iBAAiB,EAAE,OAAO,CAAC,IAAI,CAAC,CAAoB;IACpD,KAAK,CAAC,EAAE,MAAM,CAAC,OAAO,CAAA;gBAGZ,EAAE,EAAE,QAAQ,EACZ,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,qBAAqB,EACrC,UAAU,EAAE,wBAAwB,EACpC,sBAAsB,EAAE,6BAA6B;IAG/D,KAAK;IAIL,IAAI;IAWE,OAAO;IASP,sBAAsB,CAAC,QAAQ,EAAE,MAAM;IAqGvC,eAAe,CAAC,EACpB,KAAK,EACL,MAAM,EACN,KAAK,EACL,OAAO,EACP,aAAa,EACb,cAAc,GACf,EAAE;QACD,KAAK,EAAE;YAAE,OAAO,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAA;QAC3C,MAAM,EAAE,UAAU,CAAC,eAAe,CAAC,CAAA;QACnC,KAAK,EAAE,YAAY,CAAA;QACnB,OAAO,EAAE,OAAO,GAAG,SAAS,CAAA;QAE5B,aAAa,EAAE,iBAAiB,CAAA;QAChC,cAAc,EAAE,cAAc,CAAA;KAC/B;;;;IAkFK,8BAA8B;CAqCrC"}
@@ -5,6 +5,7 @@ const common_1 = require("@atproto/common");
5
5
  const util_1 = require("../api/moderation/util");
6
6
  const logger_1 = require("../logger");
7
7
  const subject_1 = require("../mod-service/subject");
8
+ const util_2 = require("../util");
8
9
  class ScheduledActionProcessor {
9
10
  constructor(db, serviceDid, settingService, modService, scheduledActionService) {
10
11
  Object.defineProperty(this, "db", {
@@ -94,6 +95,10 @@ class ScheduledActionProcessor {
94
95
  return;
95
96
  }
96
97
  let event;
98
+ const email = {
99
+ subject: '',
100
+ content: '',
101
+ };
97
102
  let modTool;
98
103
  // Create the appropriate moderation action based on the scheduled action type
99
104
  switch (action.action) {
@@ -107,7 +112,13 @@ class ScheduledActionProcessor {
107
112
  durationInHours: eventData.durationInHours,
108
113
  acknowledgeAccountSubjects: eventData.acknowledgeAccountSubjects,
109
114
  policies: eventData.policies,
115
+ severityLevel: eventData.severityLevel,
116
+ strikeCount: eventData.strikeCount,
110
117
  };
118
+ if (eventData.emailSubject && eventData.emailContent) {
119
+ email.subject = eventData.emailSubject;
120
+ email.content = eventData.emailContent;
121
+ }
111
122
  }
112
123
  break;
113
124
  default:
@@ -119,6 +130,7 @@ class ScheduledActionProcessor {
119
130
  modTool,
120
131
  moderationTxn,
121
132
  settingService,
133
+ email,
122
134
  });
123
135
  // Mark the scheduled action as executed
124
136
  await scheduledActionTxn.markActionAsExecuted(actionId, moderationEvent.event.id);
@@ -139,7 +151,7 @@ class ScheduledActionProcessor {
139
151
  }
140
152
  });
141
153
  }
142
- async performTakedown({ action, event, modTool, moderationTxn, settingService, }) {
154
+ async performTakedown({ email, action, event, modTool, moderationTxn, settingService, }) {
143
155
  const subject = new subject_1.RepoSubject(action.did);
144
156
  const status = await moderationTxn.getStatus(subject);
145
157
  if (status?.takendown) {
@@ -166,7 +178,37 @@ class ScheduledActionProcessor {
166
178
  createdBy: action.createdBy,
167
179
  });
168
180
  // register the takedown in event pusher
169
- await moderationTxn.takedownRepo(subject, moderationEvent.event.id);
181
+ await moderationTxn.takedownRepo(subject, moderationEvent.event.id, new Set(moderationEvent.event.meta?.targetServices
182
+ ? `${moderationEvent.event.meta.targetServices}`.split(',')
183
+ : undefined));
184
+ if (email.content && email.subject) {
185
+ let isDelivered = false;
186
+ try {
187
+ await (0, util_2.retryHttp)(() => moderationTxn.sendEmail({
188
+ ...email,
189
+ recipientDid: action.did,
190
+ }));
191
+ isDelivered = true;
192
+ }
193
+ catch (err) {
194
+ logger_1.dbLogger.error({ err, did: action.did }, 'failed to send takedown email');
195
+ }
196
+ await moderationTxn.logEvent({
197
+ event: {
198
+ content: email.content,
199
+ subjectLine: email.subject,
200
+ $type: 'tools.ozone.moderation.defs#modEventEmail',
201
+ comment: [
202
+ 'Communication attached to scheduled action',
203
+ isDelivered ? '' : 'Email delivery failed',
204
+ ].join('.'),
205
+ isDelivered,
206
+ },
207
+ subject,
208
+ modTool,
209
+ createdBy: action.createdBy,
210
+ });
211
+ }
170
212
  return moderationEvent;
171
213
  }
172
214
  async findAndExecuteScheduledActions() {