@atproto/ozone 0.0.17-next.0 → 0.0.17-next.1
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/dist/api/util.d.ts +10 -0
- package/dist/auth-verifier.d.ts +2 -2
- package/dist/communication-service/template.d.ts +2 -2
- package/dist/config/config.d.ts +5 -0
- package/dist/config/env.d.ts +2 -0
- package/dist/context.d.ts +6 -0
- package/dist/daemon/blob-diverter.d.ts +26 -0
- package/dist/daemon/event-pusher.d.ts +4 -0
- package/dist/daemon/index.d.ts +1 -0
- package/dist/db/index.js +21 -1
- package/dist/db/index.js.map +3 -3
- package/dist/db/migrations/20240228T003647759Z-add-label-sigs.d.ts +3 -0
- package/dist/db/migrations/index.d.ts +1 -0
- package/dist/db/schema/index.d.ts +2 -1
- package/dist/db/schema/label.d.ts +4 -0
- package/dist/db/schema/moderation_event.d.ts +1 -1
- package/dist/db/schema/moderation_subject_status.d.ts +1 -1
- package/dist/db/schema/signing_key.d.ts +9 -0
- package/dist/index.js +10949 -10628
- package/dist/index.js.map +3 -3
- package/dist/lexicon/index.d.ts +48 -28
- package/dist/lexicon/lexicons.d.ts +4641 -4650
- package/dist/lexicon/types/app/bsky/actor/defs.d.ts +7 -7
- package/dist/lexicon/types/app/bsky/feed/defs.d.ts +1 -0
- package/dist/lexicon/types/app/bsky/graph/defs.d.ts +3 -0
- package/dist/lexicon/types/com/atproto/admin/defs.d.ts +0 -305
- package/dist/lexicon/types/com/atproto/label/defs.d.ts +5 -0
- package/dist/lexicon/types/{com/atproto/admin/createCommunicationTemplate.d.ts → tools/ozone/communication/createTemplate.d.ts} +2 -2
- package/dist/lexicon/types/tools/ozone/communication/defs.d.ts +14 -0
- package/dist/lexicon/types/{com/atproto/admin/listCommunicationTemplates.d.ts → tools/ozone/communication/listTemplates.d.ts} +2 -2
- package/dist/lexicon/types/{com/atproto/admin/updateCommunicationTemplate.d.ts → tools/ozone/communication/updateTemplate.d.ts} +2 -2
- package/dist/lexicon/types/tools/ozone/moderation/defs.d.ts +269 -0
- package/dist/lexicon/types/{com/atproto/admin/emitModerationEvent.d.ts → tools/ozone/moderation/emitEvent.d.ts} +5 -4
- package/dist/lexicon/types/{com/atproto/admin/getModerationEvent.d.ts → tools/ozone/moderation/getEvent.d.ts} +2 -2
- package/dist/lexicon/types/{com/atproto/admin → tools/ozone/moderation}/getRecord.d.ts +2 -2
- package/dist/lexicon/types/{com/atproto/admin → tools/ozone/moderation}/getRepo.d.ts +2 -2
- package/dist/lexicon/types/{com/atproto/admin/queryModerationEvents.d.ts → tools/ozone/moderation/queryEvents.d.ts} +2 -2
- package/dist/lexicon/types/{com/atproto/admin/queryModerationStatuses.d.ts → tools/ozone/moderation/queryStatuses.d.ts} +2 -2
- package/dist/lexicon/types/{com/atproto/admin → tools/ozone/moderation}/searchRepos.d.ts +2 -2
- package/dist/mod-service/index.d.ts +16 -15
- package/dist/mod-service/subject.d.ts +1 -1
- package/dist/mod-service/types.d.ts +2 -2
- package/dist/mod-service/util.d.ts +6 -0
- package/dist/mod-service/views.d.ts +9 -3
- package/dist/sequencer/sequencer.d.ts +6 -4
- package/dist/util.d.ts +2 -0
- package/package.json +7 -7
- package/src/api/{admin/createCommunicationTemplate.ts → communication/createTemplate.ts} +1 -1
- package/src/api/{admin/deleteCommunicationTemplate.ts → communication/deleteTemplate.ts} +1 -1
- package/src/api/{admin/listCommunicationTemplates.ts → communication/listTemplates.ts} +1 -1
- package/src/api/{admin/updateCommunicationTemplate.ts → communication/updateTemplate.ts} +1 -1
- package/src/api/index.ts +21 -21
- package/src/api/{temp → label}/fetchLabels.ts +4 -2
- package/src/api/label/queryLabels.ts +4 -2
- package/src/api/moderation/emitEvent.ts +218 -0
- package/src/api/{admin/getModerationEvent.ts → moderation/getEvent.ts} +1 -1
- package/src/api/{admin → moderation}/getRecord.ts +2 -2
- package/src/api/{admin → moderation}/getRepo.ts +2 -2
- package/src/api/{admin/queryModerationEvents.ts → moderation/queryEvents.ts} +2 -2
- package/src/api/{admin/queryModerationStatuses.ts → moderation/queryStatuses.ts} +2 -2
- package/src/api/{admin → moderation}/searchRepos.ts +1 -1
- package/src/api/{moderation → report}/createReport.ts +1 -1
- package/src/api/util.ts +119 -0
- package/src/auth-verifier.ts +2 -2
- package/src/communication-service/template.ts +2 -2
- package/src/config/config.ts +14 -0
- package/src/config/env.ts +4 -0
- package/src/context.ts +35 -9
- package/src/daemon/blob-diverter.ts +150 -0
- package/src/daemon/context.ts +9 -5
- package/src/daemon/event-pusher.ts +49 -14
- package/src/daemon/index.ts +1 -0
- package/src/db/migrations/20240228T003647759Z-add-label-sigs.ts +25 -0
- package/src/db/migrations/index.ts +1 -0
- package/src/db/schema/index.ts +2 -0
- package/src/db/schema/label.ts +3 -0
- package/src/db/schema/moderation_event.ts +11 -11
- package/src/db/schema/moderation_subject_status.ts +1 -1
- package/src/db/schema/signing_key.ts +10 -0
- package/src/lexicon/index.ts +178 -138
- package/src/lexicon/lexicons.ts +6078 -6106
- package/src/lexicon/types/app/bsky/actor/defs.ts +11 -11
- package/src/lexicon/types/app/bsky/feed/defs.ts +1 -0
- package/src/lexicon/types/app/bsky/graph/defs.ts +3 -0
- package/src/lexicon/types/com/atproto/admin/defs.ts +0 -697
- package/src/lexicon/types/com/atproto/label/defs.ts +10 -0
- package/src/lexicon/types/{com/atproto/admin/createCommunicationTemplate.ts → tools/ozone/communication/createTemplate.ts} +2 -2
- package/src/lexicon/types/tools/ozone/communication/defs.ts +35 -0
- package/src/lexicon/types/{com/atproto/admin/listCommunicationTemplates.ts → tools/ozone/communication/listTemplates.ts} +2 -2
- package/src/lexicon/types/{com/atproto/admin/updateCommunicationTemplate.ts → tools/ozone/communication/updateTemplate.ts} +2 -2
- package/src/lexicon/types/tools/ozone/moderation/defs.ts +641 -0
- package/src/lexicon/types/{com/atproto/admin/emitModerationEvent.ts → tools/ozone/moderation/emitEvent.ts} +15 -14
- package/src/lexicon/types/{com/atproto/admin/getModerationEvent.ts → tools/ozone/moderation/getEvent.ts} +2 -2
- package/src/lexicon/types/{com/atproto/admin → tools/ozone/moderation}/getRecord.ts +2 -2
- package/src/lexicon/types/{com/atproto/admin → tools/ozone/moderation}/getRepo.ts +2 -2
- package/src/lexicon/types/{com/atproto/admin/queryModerationEvents.ts → tools/ozone/moderation/queryEvents.ts} +3 -3
- package/src/lexicon/types/{com/atproto/admin/queryModerationStatuses.ts → tools/ozone/moderation/queryStatuses.ts} +2 -2
- package/src/lexicon/types/{com/atproto/admin → tools/ozone/moderation}/searchRepos.ts +2 -2
- package/src/mod-service/index.ts +42 -47
- package/src/mod-service/lang.ts +1 -1
- package/src/mod-service/status.ts +19 -16
- package/src/mod-service/subject.ts +1 -1
- package/src/mod-service/types.ts +10 -10
- package/src/mod-service/util.ts +49 -5
- package/src/mod-service/views.ts +45 -18
- package/src/sequencer/sequencer.ts +12 -11
- package/src/util.ts +21 -0
- package/tests/__snapshots__/blob-divert.test.ts.snap +22 -0
- package/tests/__snapshots__/get-record.test.ts.snap +10 -2
- package/tests/__snapshots__/get-repo.test.ts.snap +5 -1
- package/tests/__snapshots__/moderation-events.test.ts.snap +8 -8
- package/tests/__snapshots__/moderation-statuses.test.ts.snap +6 -6
- package/tests/_util.ts +5 -0
- package/tests/blob-divert.test.ts +87 -0
- package/tests/communication-templates.test.ts +30 -34
- package/tests/db.test.ts +6 -6
- package/tests/get-record.test.ts +6 -6
- package/tests/get-repo.test.ts +11 -11
- package/tests/moderation-appeals.test.ts +28 -28
- package/tests/moderation-events.test.ts +44 -44
- package/tests/moderation-status-tags.test.ts +8 -10
- package/tests/moderation-statuses.test.ts +27 -27
- package/tests/moderation.test.ts +50 -57
- package/tests/query-labels.test.ts +86 -10
- package/tests/repo-search.test.ts +8 -8
- package/tests/sequencer.test.ts +6 -3
- package/dist/api/admin/util.d.ts +0 -5
- package/dist/api/moderation/util.d.ts +0 -4
- package/src/api/admin/emitModerationEvent.ts +0 -174
- package/src/api/admin/util.ts +0 -54
- package/src/api/moderation/util.ts +0 -67
- /package/dist/api/{admin/createCommunicationTemplate.d.ts → communication/createTemplate.d.ts} +0 -0
- /package/dist/api/{admin/deleteCommunicationTemplate.d.ts → communication/deleteTemplate.d.ts} +0 -0
- /package/dist/api/{admin/emitModerationEvent.d.ts → communication/listTemplates.d.ts} +0 -0
- /package/dist/api/{admin/getModerationEvent.d.ts → communication/updateTemplate.d.ts} +0 -0
- /package/dist/api/{temp → label}/fetchLabels.d.ts +0 -0
- /package/dist/api/{admin/getRecord.d.ts → moderation/emitEvent.d.ts} +0 -0
- /package/dist/api/{admin/getRepo.d.ts → moderation/getEvent.d.ts} +0 -0
- /package/dist/api/{admin/listCommunicationTemplates.d.ts → moderation/getRecord.d.ts} +0 -0
- /package/dist/api/{admin/queryModerationEvents.d.ts → moderation/getRepo.d.ts} +0 -0
- /package/dist/api/{admin/queryModerationStatuses.d.ts → moderation/queryEvents.d.ts} +0 -0
- /package/dist/api/{admin/searchRepos.d.ts → moderation/queryStatuses.d.ts} +0 -0
- /package/dist/api/{admin/updateCommunicationTemplate.d.ts → moderation/searchRepos.d.ts} +0 -0
- /package/dist/api/{moderation → report}/createReport.d.ts +0 -0
- /package/dist/lexicon/types/{com/atproto/admin/deleteCommunicationTemplate.d.ts → tools/ozone/communication/deleteTemplate.d.ts} +0 -0
- /package/src/lexicon/types/{com/atproto/admin/deleteCommunicationTemplate.ts → tools/ozone/communication/deleteTemplate.ts} +0 -0
|
@@ -31,8 +31,8 @@ describe('admin repo search view', () => {
|
|
|
31
31
|
})
|
|
32
32
|
|
|
33
33
|
beforeAll(async () => {
|
|
34
|
-
await modClient.
|
|
35
|
-
event: { $type: '
|
|
34
|
+
await modClient.emitEvent({
|
|
35
|
+
event: { $type: 'tools.ozone.moderation.defs#modEventTakedown' },
|
|
36
36
|
subject: {
|
|
37
37
|
$type: 'com.atproto.admin.defs#repoRef',
|
|
38
38
|
did: sc.dids['cara-wiegand69.test'],
|
|
@@ -41,7 +41,7 @@ describe('admin repo search view', () => {
|
|
|
41
41
|
})
|
|
42
42
|
|
|
43
43
|
it('gives relevant results', async () => {
|
|
44
|
-
const result = await agent.api.
|
|
44
|
+
const result = await agent.api.tools.ozone.moderation.searchRepos(
|
|
45
45
|
{ term: 'car' },
|
|
46
46
|
{ headers },
|
|
47
47
|
)
|
|
@@ -71,7 +71,7 @@ describe('admin repo search view', () => {
|
|
|
71
71
|
|
|
72
72
|
it('finds repo by did', async () => {
|
|
73
73
|
const term = sc.dids['cara-wiegand69.test']
|
|
74
|
-
const res = await agent.api.
|
|
74
|
+
const res = await agent.api.tools.ozone.moderation.searchRepos(
|
|
75
75
|
{ term },
|
|
76
76
|
{ headers },
|
|
77
77
|
)
|
|
@@ -83,7 +83,7 @@ describe('admin repo search view', () => {
|
|
|
83
83
|
it('paginates with term', async () => {
|
|
84
84
|
const results = (results) => results.flatMap((res) => res.users)
|
|
85
85
|
const paginator = async (cursor?: string) => {
|
|
86
|
-
const res = await agent.api.
|
|
86
|
+
const res = await agent.api.tools.ozone.moderation.searchRepos(
|
|
87
87
|
{ term: 'p', cursor, limit: 3 },
|
|
88
88
|
{ headers },
|
|
89
89
|
)
|
|
@@ -95,7 +95,7 @@ describe('admin repo search view', () => {
|
|
|
95
95
|
expect(res.repos.length).toBeLessThanOrEqual(3),
|
|
96
96
|
)
|
|
97
97
|
|
|
98
|
-
const full = await agent.api.
|
|
98
|
+
const full = await agent.api.tools.ozone.moderation.searchRepos(
|
|
99
99
|
{ term: 'p' },
|
|
100
100
|
{ headers },
|
|
101
101
|
)
|
|
@@ -107,7 +107,7 @@ describe('admin repo search view', () => {
|
|
|
107
107
|
it('paginates without term', async () => {
|
|
108
108
|
const results = (results) => results.flatMap((res) => res.repos)
|
|
109
109
|
const paginator = async (cursor?: string) => {
|
|
110
|
-
const res = await agent.api.
|
|
110
|
+
const res = await agent.api.tools.ozone.moderation.searchRepos(
|
|
111
111
|
{ cursor, limit: 3 },
|
|
112
112
|
{ headers },
|
|
113
113
|
)
|
|
@@ -119,7 +119,7 @@ describe('admin repo search view', () => {
|
|
|
119
119
|
expect(res.repos.length).toBeLessThanOrEqual(3),
|
|
120
120
|
)
|
|
121
121
|
|
|
122
|
-
const full = await agent.api.
|
|
122
|
+
const full = await agent.api.tools.ozone.moderation.searchRepos(
|
|
123
123
|
{ limit: 15 },
|
|
124
124
|
{ headers },
|
|
125
125
|
)
|
package/tests/sequencer.test.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TestNetwork } from '@atproto/dev-env'
|
|
1
|
+
import { EXAMPLE_LABELER, TestNetwork } from '@atproto/dev-env'
|
|
2
2
|
import { readFromGenerator, wait } from '@atproto/common'
|
|
3
3
|
import { LabelsEvt, Sequencer } from '../src/sequencer'
|
|
4
4
|
import Outbox from '../src/sequencer/outbox'
|
|
@@ -33,11 +33,14 @@ describe('sequencer', () => {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
const evtToDbRow = (e: LabelsEvt) => {
|
|
36
|
-
const label = e.labels[0]
|
|
36
|
+
const { ver: _, ...label } = e.labels[0]
|
|
37
37
|
return {
|
|
38
38
|
id: e.seq,
|
|
39
39
|
...label,
|
|
40
40
|
cid: label.cid ? label.cid : '',
|
|
41
|
+
exp: null,
|
|
42
|
+
sig: label.sig ? Buffer.from(label.sig) : null,
|
|
43
|
+
signingKeyId: network.ozone.ctx.signingKeyId,
|
|
41
44
|
}
|
|
42
45
|
}
|
|
43
46
|
|
|
@@ -54,7 +57,7 @@ describe('sequencer', () => {
|
|
|
54
57
|
for (let i = 0; i < count; i++) {
|
|
55
58
|
const did = `did:example:${randomStr(10, 'base32')}`
|
|
56
59
|
const label = {
|
|
57
|
-
src:
|
|
60
|
+
src: EXAMPLE_LABELER,
|
|
58
61
|
uri: did,
|
|
59
62
|
val: 'spam',
|
|
60
63
|
neg: false,
|
package/dist/api/admin/util.d.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import AppContext from '../../context';
|
|
2
|
-
import { RepoView, RepoViewDetail, AccountView } from '../../lexicon/types/com/atproto/admin/defs';
|
|
3
|
-
export declare const getPdsAccountInfo: (ctx: AppContext, did: string) => Promise<AccountView | null>;
|
|
4
|
-
export declare const addAccountInfoToRepoViewDetail: (repoView: RepoViewDetail, accountInfo: AccountView | null, includeEmail?: boolean) => RepoViewDetail;
|
|
5
|
-
export declare const addAccountInfoToRepoView: (repoView: RepoView, accountInfo: AccountView | null, includeEmail?: boolean) => RepoView;
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { InputSchema as ReportInput } from '../../lexicon/types/com/atproto/moderation/createReport';
|
|
2
|
-
export declare const getReasonType: (reasonType: ReportInput['reasonType']) => string | boolean;
|
|
3
|
-
export declare const getEventType: (type: string) => "com.atproto.admin.defs#modEventTakedown" | "com.atproto.admin.defs#modEventAcknowledge" | "com.atproto.admin.defs#modEventEscalate" | "com.atproto.admin.defs#modEventComment" | "com.atproto.admin.defs#modEventLabel" | "com.atproto.admin.defs#modEventReport" | "com.atproto.admin.defs#modEventMute" | "com.atproto.admin.defs#modEventReverseTakedown" | "com.atproto.admin.defs#modEventEmail" | "com.atproto.admin.defs#modEventResolveAppeal" | "com.atproto.admin.defs#modEventTag";
|
|
4
|
-
export declare const getReviewState: (reviewState?: string) => "com.atproto.admin.defs#reviewOpen" | "com.atproto.admin.defs#reviewEscalated" | "com.atproto.admin.defs#reviewClosed" | "com.atproto.admin.defs#reviewNone" | undefined;
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import { AuthRequiredError, InvalidRequestError } from '@atproto/xrpc-server'
|
|
2
|
-
import { Server } from '../../lexicon'
|
|
3
|
-
import AppContext from '../../context'
|
|
4
|
-
import {
|
|
5
|
-
isModEventEmail,
|
|
6
|
-
isModEventLabel,
|
|
7
|
-
isModEventReverseTakedown,
|
|
8
|
-
isModEventTakedown,
|
|
9
|
-
} from '../../lexicon/types/com/atproto/admin/defs'
|
|
10
|
-
import { subjectFromInput } from '../../mod-service/subject'
|
|
11
|
-
import { ModerationLangService } from '../../mod-service/lang'
|
|
12
|
-
import { retryHttp } from '../../util'
|
|
13
|
-
|
|
14
|
-
export default function (server: Server, ctx: AppContext) {
|
|
15
|
-
server.com.atproto.admin.emitModerationEvent({
|
|
16
|
-
auth: ctx.authVerifier.modOrAdminToken,
|
|
17
|
-
handler: async ({ input, auth }) => {
|
|
18
|
-
const access = auth.credentials
|
|
19
|
-
const createdBy =
|
|
20
|
-
auth.credentials.type === 'moderator'
|
|
21
|
-
? auth.credentials.iss
|
|
22
|
-
: input.body.createdBy
|
|
23
|
-
const db = ctx.db
|
|
24
|
-
const moderationService = ctx.modService(db)
|
|
25
|
-
const { event } = input.body
|
|
26
|
-
const isTakedownEvent = isModEventTakedown(event)
|
|
27
|
-
const isReverseTakedownEvent = isModEventReverseTakedown(event)
|
|
28
|
-
const isLabelEvent = isModEventLabel(event)
|
|
29
|
-
const subject = subjectFromInput(
|
|
30
|
-
input.body.subject,
|
|
31
|
-
input.body.subjectBlobCids,
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
// apply access rules
|
|
35
|
-
|
|
36
|
-
// if less than moderator access then can only take ack and escalation actions
|
|
37
|
-
if (isTakedownEvent || isReverseTakedownEvent) {
|
|
38
|
-
if (!access.isModerator) {
|
|
39
|
-
throw new AuthRequiredError(
|
|
40
|
-
'Must be a full moderator to take this type of action',
|
|
41
|
-
)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Non admins should not be able to take down feed generators
|
|
45
|
-
if (
|
|
46
|
-
!access.isAdmin &&
|
|
47
|
-
subject.recordPath?.includes('app.bsky.feed.generator/')
|
|
48
|
-
) {
|
|
49
|
-
throw new AuthRequiredError(
|
|
50
|
-
'Must be a full admin to take this type of action on feed generators',
|
|
51
|
-
)
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
// if less than moderator access then can not apply labels
|
|
55
|
-
if (!access.isModerator && isLabelEvent) {
|
|
56
|
-
throw new AuthRequiredError('Must be a full moderator to label content')
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (isLabelEvent) {
|
|
60
|
-
validateLabels([
|
|
61
|
-
...(event.createLabelVals ?? []),
|
|
62
|
-
...(event.negateLabelVals ?? []),
|
|
63
|
-
])
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (isTakedownEvent || isReverseTakedownEvent) {
|
|
67
|
-
const status = await moderationService.getStatus(subject)
|
|
68
|
-
|
|
69
|
-
if (status?.takendown && isTakedownEvent) {
|
|
70
|
-
throw new InvalidRequestError(`Subject is already taken down`)
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
if (!status?.takendown && isReverseTakedownEvent) {
|
|
74
|
-
throw new InvalidRequestError(`Subject is not taken down`)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
if (status?.takendown && isReverseTakedownEvent && subject.isRecord()) {
|
|
78
|
-
// due to the way blob status is modeled, we should reverse takedown on all
|
|
79
|
-
// blobs for the record being restored, which aren't taken down on another record.
|
|
80
|
-
subject.blobCids = status.blobCids ?? []
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (isModEventEmail(event) && event.content) {
|
|
85
|
-
// sending email prior to logging the event to avoid a long transaction below
|
|
86
|
-
if (!subject.isRepo()) {
|
|
87
|
-
throw new InvalidRequestError(
|
|
88
|
-
'Email can only be sent to a repo subject',
|
|
89
|
-
)
|
|
90
|
-
}
|
|
91
|
-
const { content, subjectLine } = event
|
|
92
|
-
await retryHttp(() =>
|
|
93
|
-
ctx.modService(db).sendEmail({
|
|
94
|
-
subject: subjectLine,
|
|
95
|
-
content,
|
|
96
|
-
recipientDid: subject.did,
|
|
97
|
-
}),
|
|
98
|
-
)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const moderationEvent = await db.transaction(async (dbTxn) => {
|
|
102
|
-
const moderationTxn = ctx.modService(dbTxn)
|
|
103
|
-
|
|
104
|
-
const result = await moderationTxn.logEvent({
|
|
105
|
-
event,
|
|
106
|
-
subject,
|
|
107
|
-
createdBy,
|
|
108
|
-
})
|
|
109
|
-
|
|
110
|
-
const moderationLangService = new ModerationLangService(moderationTxn)
|
|
111
|
-
await moderationLangService.tagSubjectWithLang({
|
|
112
|
-
subject,
|
|
113
|
-
createdBy: ctx.cfg.service.did,
|
|
114
|
-
subjectStatus: result.subjectStatus,
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
if (subject.isRepo()) {
|
|
118
|
-
if (isTakedownEvent) {
|
|
119
|
-
const isSuspend = !!result.event.durationInHours
|
|
120
|
-
await moderationTxn.takedownRepo(
|
|
121
|
-
subject,
|
|
122
|
-
result.event.id,
|
|
123
|
-
isSuspend,
|
|
124
|
-
)
|
|
125
|
-
} else if (isReverseTakedownEvent) {
|
|
126
|
-
await moderationTxn.reverseTakedownRepo(subject)
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
if (subject.isRecord()) {
|
|
131
|
-
if (isTakedownEvent) {
|
|
132
|
-
await moderationTxn.takedownRecord(subject, result.event.id)
|
|
133
|
-
} else if (isReverseTakedownEvent) {
|
|
134
|
-
await moderationTxn.reverseTakedownRecord(subject)
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
if (isLabelEvent) {
|
|
139
|
-
await moderationTxn.formatAndCreateLabels(
|
|
140
|
-
result.event.subjectUri ?? result.event.subjectDid,
|
|
141
|
-
result.event.subjectCid,
|
|
142
|
-
{
|
|
143
|
-
create: result.event.createLabelVals?.length
|
|
144
|
-
? result.event.createLabelVals.split(' ')
|
|
145
|
-
: undefined,
|
|
146
|
-
negate: result.event.negateLabelVals?.length
|
|
147
|
-
? result.event.negateLabelVals.split(' ')
|
|
148
|
-
: undefined,
|
|
149
|
-
},
|
|
150
|
-
)
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
return result.event
|
|
154
|
-
})
|
|
155
|
-
|
|
156
|
-
return {
|
|
157
|
-
encoding: 'application/json',
|
|
158
|
-
body: moderationService.views.formatEvent(moderationEvent),
|
|
159
|
-
}
|
|
160
|
-
},
|
|
161
|
-
})
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
const validateLabels = (labels: string[]) => {
|
|
165
|
-
for (const label of labels) {
|
|
166
|
-
for (const char of badChars) {
|
|
167
|
-
if (label.includes(char)) {
|
|
168
|
-
throw new InvalidRequestError(`Invalid label: ${label}`)
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
const badChars = [' ', ',', ';', `'`, `"`]
|
package/src/api/admin/util.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import AppContext from '../../context'
|
|
2
|
-
import {
|
|
3
|
-
RepoView,
|
|
4
|
-
RepoViewDetail,
|
|
5
|
-
AccountView,
|
|
6
|
-
} from '../../lexicon/types/com/atproto/admin/defs'
|
|
7
|
-
|
|
8
|
-
export const getPdsAccountInfo = async (
|
|
9
|
-
ctx: AppContext,
|
|
10
|
-
did: string,
|
|
11
|
-
): Promise<AccountView | null> => {
|
|
12
|
-
const agent = ctx.pdsAgent
|
|
13
|
-
if (!agent) return null
|
|
14
|
-
const auth = await ctx.pdsAuth()
|
|
15
|
-
if (!auth) return null
|
|
16
|
-
try {
|
|
17
|
-
const res = await agent.api.com.atproto.admin.getAccountInfo({ did }, auth)
|
|
18
|
-
return res.data
|
|
19
|
-
} catch {
|
|
20
|
-
return null
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export const addAccountInfoToRepoViewDetail = (
|
|
25
|
-
repoView: RepoViewDetail,
|
|
26
|
-
accountInfo: AccountView | null,
|
|
27
|
-
includeEmail = false,
|
|
28
|
-
): RepoViewDetail => {
|
|
29
|
-
if (!accountInfo) return repoView
|
|
30
|
-
return {
|
|
31
|
-
...repoView,
|
|
32
|
-
email: includeEmail ? accountInfo.email : undefined,
|
|
33
|
-
invitedBy: accountInfo.invitedBy,
|
|
34
|
-
invitesDisabled: accountInfo.invitesDisabled,
|
|
35
|
-
inviteNote: accountInfo.inviteNote,
|
|
36
|
-
invites: accountInfo.invites,
|
|
37
|
-
emailConfirmedAt: accountInfo.emailConfirmedAt,
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export const addAccountInfoToRepoView = (
|
|
42
|
-
repoView: RepoView,
|
|
43
|
-
accountInfo: AccountView | null,
|
|
44
|
-
includeEmail = false,
|
|
45
|
-
): RepoView => {
|
|
46
|
-
if (!accountInfo) return repoView
|
|
47
|
-
return {
|
|
48
|
-
...repoView,
|
|
49
|
-
email: includeEmail ? accountInfo.email : undefined,
|
|
50
|
-
invitedBy: accountInfo.invitedBy,
|
|
51
|
-
invitesDisabled: accountInfo.invitesDisabled,
|
|
52
|
-
inviteNote: accountInfo.inviteNote,
|
|
53
|
-
}
|
|
54
|
-
}
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { InvalidRequestError } from '@atproto/xrpc-server'
|
|
2
|
-
import { InputSchema as ReportInput } from '../../lexicon/types/com/atproto/moderation/createReport'
|
|
3
|
-
import {
|
|
4
|
-
REASONOTHER,
|
|
5
|
-
REASONSPAM,
|
|
6
|
-
REASONMISLEADING,
|
|
7
|
-
REASONRUDE,
|
|
8
|
-
REASONSEXUAL,
|
|
9
|
-
REASONVIOLATION,
|
|
10
|
-
REASONAPPEAL,
|
|
11
|
-
} from '../../lexicon/types/com/atproto/moderation/defs'
|
|
12
|
-
import {
|
|
13
|
-
REVIEWCLOSED,
|
|
14
|
-
REVIEWESCALATED,
|
|
15
|
-
REVIEWOPEN,
|
|
16
|
-
} from '../../lexicon/types/com/atproto/admin/defs'
|
|
17
|
-
import { ModerationEvent } from '../../db/schema/moderation_event'
|
|
18
|
-
import { ModerationSubjectStatusRow } from '../../mod-service/types'
|
|
19
|
-
|
|
20
|
-
export const getReasonType = (reasonType: ReportInput['reasonType']) => {
|
|
21
|
-
if (reasonTypes.has(reasonType)) {
|
|
22
|
-
return reasonType as NonNullable<ModerationEvent['meta']>['reportType']
|
|
23
|
-
}
|
|
24
|
-
throw new InvalidRequestError('Invalid reason type')
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export const getEventType = (type: string) => {
|
|
28
|
-
if (eventTypes.has(type)) {
|
|
29
|
-
return type as ModerationEvent['action']
|
|
30
|
-
}
|
|
31
|
-
throw new InvalidRequestError('Invalid event type')
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export const getReviewState = (reviewState?: string) => {
|
|
35
|
-
if (!reviewState) return undefined
|
|
36
|
-
if (reviewStates.has(reviewState)) {
|
|
37
|
-
return reviewState as ModerationSubjectStatusRow['reviewState']
|
|
38
|
-
}
|
|
39
|
-
throw new InvalidRequestError('Invalid review state')
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const reviewStates = new Set([REVIEWCLOSED, REVIEWESCALATED, REVIEWOPEN])
|
|
43
|
-
|
|
44
|
-
const reasonTypes = new Set([
|
|
45
|
-
REASONOTHER,
|
|
46
|
-
REASONSPAM,
|
|
47
|
-
REASONMISLEADING,
|
|
48
|
-
REASONRUDE,
|
|
49
|
-
REASONSEXUAL,
|
|
50
|
-
REASONVIOLATION,
|
|
51
|
-
REASONAPPEAL,
|
|
52
|
-
])
|
|
53
|
-
|
|
54
|
-
const eventTypes = new Set([
|
|
55
|
-
'com.atproto.admin.defs#modEventTakedown',
|
|
56
|
-
'com.atproto.admin.defs#modEventAcknowledge',
|
|
57
|
-
'com.atproto.admin.defs#modEventEscalate',
|
|
58
|
-
'com.atproto.admin.defs#modEventComment',
|
|
59
|
-
'com.atproto.admin.defs#modEventLabel',
|
|
60
|
-
'com.atproto.admin.defs#modEventReport',
|
|
61
|
-
'com.atproto.admin.defs#modEventMute',
|
|
62
|
-
'com.atproto.admin.defs#modEventUnmute',
|
|
63
|
-
'com.atproto.admin.defs#modEventReverseTakedown',
|
|
64
|
-
'com.atproto.admin.defs#modEventEmail',
|
|
65
|
-
'com.atproto.admin.defs#modEventResolveAppeal',
|
|
66
|
-
'com.atproto.admin.defs#modEventTag',
|
|
67
|
-
])
|
/package/dist/api/{admin/createCommunicationTemplate.d.ts → communication/createTemplate.d.ts}
RENAMED
|
File without changes
|
/package/dist/api/{admin/deleteCommunicationTemplate.d.ts → communication/deleteTemplate.d.ts}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|