@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.
- package/CHANGELOG.md +27 -0
- package/dist/api/moderation/emitEvent.d.ts.map +1 -1
- package/dist/api/moderation/emitEvent.js +20 -7
- package/dist/api/moderation/emitEvent.js.map +1 -1
- package/dist/api/util.d.ts +1 -1
- package/dist/api/util.d.ts.map +1 -1
- package/dist/api/util.js +6 -1
- package/dist/api/util.js.map +1 -1
- package/dist/daemon/event-pusher.d.ts +1 -1
- package/dist/daemon/event-pusher.d.ts.map +1 -1
- package/dist/daemon/event-pusher.js +17 -5
- package/dist/daemon/event-pusher.js.map +1 -1
- package/dist/daemon/scheduled-action-processor.d.ts +5 -1
- package/dist/daemon/scheduled-action-processor.d.ts.map +1 -1
- package/dist/daemon/scheduled-action-processor.js +44 -2
- package/dist/daemon/scheduled-action-processor.js.map +1 -1
- package/dist/jetstream/service.d.ts +1 -1
- package/dist/jetstream/service.d.ts.map +1 -1
- package/dist/jetstream/service.js +2 -2
- package/dist/jetstream/service.js.map +1 -1
- package/dist/lexicon/index.d.ts +11 -0
- package/dist/lexicon/index.d.ts.map +1 -1
- package/dist/lexicon/index.js +32 -1
- package/dist/lexicon/index.js.map +1 -1
- package/dist/lexicon/lexicons.d.ts +806 -6
- package/dist/lexicon/lexicons.d.ts.map +1 -1
- package/dist/lexicon/lexicons.js +425 -3
- package/dist/lexicon/lexicons.js.map +1 -1
- package/dist/lexicon/types/app/bsky/ageassurance/begin.d.ts +31 -0
- package/dist/lexicon/types/app/bsky/ageassurance/begin.d.ts.map +1 -0
- package/dist/lexicon/types/app/bsky/ageassurance/begin.js +7 -0
- package/dist/lexicon/types/app/bsky/ageassurance/begin.js.map +1 -0
- package/dist/lexicon/types/app/bsky/ageassurance/defs.d.ts +138 -0
- package/dist/lexicon/types/app/bsky/ageassurance/defs.d.ts.map +1 -0
- package/dist/lexicon/types/app/bsky/ageassurance/defs.js +115 -0
- package/dist/lexicon/types/app/bsky/ageassurance/defs.js.map +1 -0
- package/dist/lexicon/types/app/bsky/ageassurance/getConfig.d.ts +18 -0
- package/dist/lexicon/types/app/bsky/ageassurance/getConfig.d.ts.map +1 -0
- package/dist/lexicon/types/app/bsky/ageassurance/getConfig.js +7 -0
- package/dist/lexicon/types/app/bsky/ageassurance/getConfig.js.map +1 -0
- package/dist/lexicon/types/app/bsky/ageassurance/getState.d.ts +24 -0
- package/dist/lexicon/types/app/bsky/ageassurance/getState.d.ts.map +1 -0
- package/dist/lexicon/types/app/bsky/ageassurance/getState.js +7 -0
- package/dist/lexicon/types/app/bsky/ageassurance/getState.js.map +1 -0
- package/dist/lexicon/types/tools/ozone/moderation/defs.d.ts +13 -2
- package/dist/lexicon/types/tools/ozone/moderation/defs.d.ts.map +1 -1
- package/dist/lexicon/types/tools/ozone/moderation/defs.js.map +1 -1
- package/dist/lexicon/types/tools/ozone/moderation/queryStatuses.d.ts +1 -1
- package/dist/lexicon/types/tools/ozone/moderation/queryStatuses.d.ts.map +1 -1
- package/dist/lexicon/types/tools/ozone/moderation/queryStatuses.js.map +1 -1
- package/dist/lexicon/types/tools/ozone/moderation/scheduleAction.d.ts +10 -0
- package/dist/lexicon/types/tools/ozone/moderation/scheduleAction.d.ts.map +1 -1
- package/dist/lexicon/types/tools/ozone/moderation/scheduleAction.js.map +1 -1
- package/dist/mod-service/index.d.ts +3 -3
- package/dist/mod-service/index.d.ts.map +1 -1
- package/dist/mod-service/index.js +10 -4
- package/dist/mod-service/index.js.map +1 -1
- package/dist/mod-service/status.d.ts +1 -1
- package/dist/mod-service/util.d.ts.map +1 -1
- package/dist/mod-service/util.js +1 -0
- package/dist/mod-service/util.js.map +1 -1
- package/dist/mod-service/views.d.ts.map +1 -1
- package/dist/mod-service/views.js +7 -0
- package/dist/mod-service/views.js.map +1 -1
- package/dist/setting/validators.d.ts.map +1 -1
- package/dist/setting/validators.js +10 -0
- package/dist/setting/validators.js.map +1 -1
- package/package.json +10 -9
- package/src/api/moderation/emitEvent.ts +34 -9
- package/src/api/util.ts +7 -1
- package/src/daemon/event-pusher.ts +22 -5
- package/src/daemon/scheduled-action-processor.ts +59 -1
- package/src/jetstream/service.ts +1 -1
- package/src/lexicon/index.ts +49 -0
- package/src/lexicon/lexicons.ts +458 -3
- package/src/lexicon/types/app/bsky/ageassurance/begin.ts +54 -0
- package/src/lexicon/types/app/bsky/ageassurance/defs.ts +301 -0
- package/src/lexicon/types/app/bsky/ageassurance/getConfig.ts +34 -0
- package/src/lexicon/types/app/bsky/ageassurance/getState.ts +42 -0
- package/src/lexicon/types/tools/ozone/moderation/defs.ts +13 -2
- package/src/lexicon/types/tools/ozone/moderation/queryStatuses.ts +6 -1
- package/src/lexicon/types/tools/ozone/moderation/scheduleAction.ts +10 -0
- package/src/mod-service/index.ts +21 -7
- package/src/mod-service/util.ts +2 -0
- package/src/mod-service/views.ts +10 -0
- package/src/setting/validators.ts +15 -0
- package/tests/query-labels.test.ts +4 -1
- package/tests/scheduled-action-processor.test.ts +30 -6
- package/tests/takedown.test.ts +43 -1
- 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;
|
|
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
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
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,
|
|
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":"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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 { 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"]}
|
package/dist/api/util.d.ts
CHANGED
|
@@ -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#
|
|
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;
|
package/dist/api/util.d.ts.map
CHANGED
|
@@ -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,
|
|
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([
|
|
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',
|
package/dist/api/util.js.map
CHANGED
|
@@ -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
|
-
|
|
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;
|
|
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
|
-
|
|
88
|
-
|
|
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
|
-
|
|
93
|
+
configured.push('pds_takedown');
|
|
91
94
|
if (this.appview)
|
|
92
|
-
|
|
93
|
-
|
|
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":"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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 // 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;
|
|
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() {
|