@atproto/ozone 0.0.16 → 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 +8 -12
- package/dist/communication-service/template.d.ts +2 -2
- package/dist/config/config.d.ts +6 -0
- package/dist/config/env.d.ts +3 -2
- package/dist/config/secrets.d.ts +0 -2
- package/dist/context.d.ts +6 -0
- package/dist/daemon/blob-diverter.d.ts +26 -0
- package/dist/daemon/event-pusher.d.ts +6 -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 +2 -2
- package/dist/db/schema/signing_key.d.ts +9 -0
- package/dist/index.js +10400 -10313
- package/dist/index.js.map +3 -3
- package/dist/lexicon/index.d.ts +55 -27
- package/dist/lexicon/lexicons.d.ts +5046 -4757
- package/dist/lexicon/types/app/bsky/actor/defs.d.ts +23 -1
- package/dist/lexicon/types/app/bsky/embed/record.d.ts +2 -1
- 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/app/bsky/labeler/defs.d.ts +41 -0
- package/dist/lexicon/types/app/bsky/labeler/getServices.d.ts +36 -0
- package/dist/lexicon/types/app/bsky/labeler/service.d.ts +14 -0
- package/dist/lexicon/types/com/atproto/admin/defs.d.ts +0 -304
- package/dist/lexicon/types/com/atproto/label/defs.d.ts +23 -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 +9 -8
- package/src/api/{admin/createCommunicationTemplate.ts → communication/createTemplate.ts} +2 -2
- package/src/api/{admin/deleteCommunicationTemplate.ts → communication/deleteTemplate.ts} +2 -2
- package/src/api/{admin/listCommunicationTemplates.ts → communication/listTemplates.ts} +2 -2
- package/src/api/{admin/updateCommunicationTemplate.ts → communication/updateTemplate.ts} +2 -2
- package/src/api/index.ts +21 -21
- package/src/api/{temp → label}/fetchLabels.ts +5 -3
- 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} +2 -2
- package/src/api/{admin → moderation}/getRecord.ts +3 -3
- package/src/api/{admin → moderation}/getRepo.ts +3 -3
- package/src/api/{admin/queryModerationEvents.ts → moderation/queryEvents.ts} +3 -3
- package/src/api/{admin/queryModerationStatuses.ts → moderation/queryStatuses.ts} +3 -3
- package/src/api/{admin → moderation}/searchRepos.ts +2 -2
- package/src/api/proxied.ts +8 -8
- package/src/api/{moderation → report}/createReport.ts +2 -3
- package/src/api/util.ts +119 -0
- package/src/auth-verifier.ts +20 -30
- package/src/communication-service/template.ts +2 -2
- package/src/config/config.ts +24 -7
- package/src/config/env.ts +6 -4
- package/src/config/secrets.ts +0 -6
- package/src/context.ts +36 -12
- package/src/daemon/blob-diverter.ts +150 -0
- package/src/daemon/context.ts +11 -7
- package/src/daemon/event-pusher.ts +58 -15
- 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 +7 -2
- package/src/db/schema/signing_key.ts +10 -0
- package/src/lexicon/index.ts +200 -137
- package/src/lexicon/lexicons.ts +6310 -6012
- package/src/lexicon/types/app/bsky/actor/defs.ts +57 -1
- package/src/lexicon/types/app/bsky/embed/record.ts +2 -0
- 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/app/bsky/labeler/defs.ts +93 -0
- package/src/lexicon/types/app/bsky/labeler/getServices.ts +51 -0
- package/src/lexicon/types/app/bsky/labeler/service.ts +31 -0
- package/src/lexicon/types/com/atproto/admin/defs.ts +0 -694
- package/src/lexicon/types/com/atproto/label/defs.ts +78 -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 +46 -50
- package/src/mod-service/lang.ts +1 -1
- package/src/mod-service/status.ts +60 -41
- 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 +14 -6
- package/tests/__snapshots__/get-repo.test.ts.snap +7 -3
- 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 +33 -37
- package/tests/db.test.ts +6 -6
- package/tests/get-record.test.ts +22 -12
- package/tests/get-repo.test.ts +33 -21
- package/tests/moderation-appeals.test.ts +39 -67
- package/tests/moderation-events.test.ts +99 -142
- package/tests/moderation-status-tags.test.ts +20 -37
- package/tests/moderation-statuses.test.ts +132 -65
- package/tests/moderation.test.ts +147 -301
- package/tests/query-labels.test.ts +86 -10
- package/tests/repo-search.test.ts +18 -11
- 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 -170
- 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
|
@@ -27,37 +27,34 @@ describe('communication-templates', () => {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
const listTemplates = async () => {
|
|
30
|
-
const { data } =
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
)
|
|
30
|
+
const { data } = await agent.api.tools.ozone.communication.listTemplates(
|
|
31
|
+
{},
|
|
32
|
+
{
|
|
33
|
+
headers: await network.ozone.modHeaders('moderator'),
|
|
34
|
+
},
|
|
35
|
+
)
|
|
37
36
|
return data.communicationTemplates
|
|
38
37
|
}
|
|
39
38
|
|
|
40
39
|
describe('create templates', () => {
|
|
41
40
|
it('only allows admins to create new templates', async () => {
|
|
42
|
-
const moderatorReq =
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
)
|
|
41
|
+
const moderatorReq = agent.api.tools.ozone.communication.createTemplate(
|
|
42
|
+
{ ...templateOne, createdBy: sc.dids.bob },
|
|
43
|
+
{
|
|
44
|
+
encoding: 'application/json',
|
|
45
|
+
headers: await network.ozone.modHeaders('moderator'),
|
|
46
|
+
},
|
|
47
|
+
)
|
|
50
48
|
await expect(moderatorReq).rejects.toThrow(
|
|
51
49
|
'Must be an admin to create a communication template',
|
|
52
50
|
)
|
|
53
|
-
const modReq =
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
)
|
|
51
|
+
const modReq = await agent.api.tools.ozone.communication.createTemplate(
|
|
52
|
+
{ ...templateOne, createdBy: sc.dids.bob },
|
|
53
|
+
{
|
|
54
|
+
encoding: 'application/json',
|
|
55
|
+
headers: await network.ozone.modHeaders('admin'),
|
|
56
|
+
},
|
|
57
|
+
)
|
|
61
58
|
|
|
62
59
|
expect(modReq.data).toMatchObject({
|
|
63
60
|
...templateOne,
|
|
@@ -75,11 +72,11 @@ describe('communication-templates', () => {
|
|
|
75
72
|
...templateOne,
|
|
76
73
|
name: 'Test template 2',
|
|
77
74
|
}
|
|
78
|
-
await agent.api.
|
|
75
|
+
await agent.api.tools.ozone.communication.createTemplate(
|
|
79
76
|
{ ...templateTwo, createdBy: sc.dids.bob },
|
|
80
77
|
{
|
|
81
78
|
encoding: 'application/json',
|
|
82
|
-
headers: network.ozone.
|
|
79
|
+
headers: await network.ozone.modHeaders('admin'),
|
|
83
80
|
},
|
|
84
81
|
)
|
|
85
82
|
|
|
@@ -90,14 +87,13 @@ describe('communication-templates', () => {
|
|
|
90
87
|
})
|
|
91
88
|
describe('update template', () => {
|
|
92
89
|
it('allows moderators to update a template by id', async () => {
|
|
93
|
-
const { data } =
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
)
|
|
90
|
+
const { data } = await agent.api.tools.ozone.communication.updateTemplate(
|
|
91
|
+
{ id: '1', updatedBy: sc.dids.bob, name: '1 Test template' },
|
|
92
|
+
{
|
|
93
|
+
encoding: 'application/json',
|
|
94
|
+
headers: await network.ozone.modHeaders('admin'),
|
|
95
|
+
},
|
|
96
|
+
)
|
|
101
97
|
|
|
102
98
|
expect(data.name).not.toEqual(templateOne.name)
|
|
103
99
|
expect(data.name).toEqual('1 Test template')
|
|
@@ -105,11 +101,11 @@ describe('communication-templates', () => {
|
|
|
105
101
|
})
|
|
106
102
|
describe('delete template', () => {
|
|
107
103
|
it('allows admins to remove a template by id', async () => {
|
|
108
|
-
const modReq = agent.api.
|
|
104
|
+
const modReq = agent.api.tools.ozone.communication.deleteTemplate(
|
|
109
105
|
{ id: '1' },
|
|
110
106
|
{
|
|
111
107
|
encoding: 'application/json',
|
|
112
|
-
headers: network.ozone.
|
|
108
|
+
headers: await network.ozone.modHeaders('moderator'),
|
|
113
109
|
},
|
|
114
110
|
)
|
|
115
111
|
|
|
@@ -117,11 +113,11 @@ describe('communication-templates', () => {
|
|
|
117
113
|
'Must be an admin to delete a communication template',
|
|
118
114
|
)
|
|
119
115
|
|
|
120
|
-
await agent.api.
|
|
116
|
+
await agent.api.tools.ozone.communication.deleteTemplate(
|
|
121
117
|
{ id: '1' },
|
|
122
118
|
{
|
|
123
119
|
encoding: 'application/json',
|
|
124
|
-
headers: network.ozone.
|
|
120
|
+
headers: await network.ozone.modHeaders('admin'),
|
|
125
121
|
},
|
|
126
122
|
)
|
|
127
123
|
const list = await listTemplates()
|
package/tests/db.test.ts
CHANGED
|
@@ -48,7 +48,7 @@ describe('db', () => {
|
|
|
48
48
|
return await dbTxn.db
|
|
49
49
|
.insertInto('repo_push_event')
|
|
50
50
|
.values({
|
|
51
|
-
eventType: '
|
|
51
|
+
eventType: 'pds_takedown',
|
|
52
52
|
subjectDid: 'x',
|
|
53
53
|
})
|
|
54
54
|
.returning('subjectDid')
|
|
@@ -68,7 +68,7 @@ describe('db', () => {
|
|
|
68
68
|
.executeTakeFirst()
|
|
69
69
|
|
|
70
70
|
expect(row).toMatchObject({
|
|
71
|
-
eventType: '
|
|
71
|
+
eventType: 'pds_takedown',
|
|
72
72
|
subjectDid: 'x',
|
|
73
73
|
})
|
|
74
74
|
})
|
|
@@ -78,7 +78,7 @@ describe('db', () => {
|
|
|
78
78
|
await dbTxn.db
|
|
79
79
|
.insertInto('repo_push_event')
|
|
80
80
|
.values({
|
|
81
|
-
eventType: '
|
|
81
|
+
eventType: 'pds_takedown',
|
|
82
82
|
subjectDid: 'y',
|
|
83
83
|
})
|
|
84
84
|
.returning('subjectDid')
|
|
@@ -124,7 +124,7 @@ describe('db', () => {
|
|
|
124
124
|
leakedTx = dbTxn
|
|
125
125
|
await dbTxn.db
|
|
126
126
|
.insertInto('repo_push_event')
|
|
127
|
-
.values({ eventType: '
|
|
127
|
+
.values({ eventType: 'pds_takedown', subjectDid: 'a' })
|
|
128
128
|
.execute()
|
|
129
129
|
throw new Error('test tx failed')
|
|
130
130
|
})
|
|
@@ -132,7 +132,7 @@ describe('db', () => {
|
|
|
132
132
|
|
|
133
133
|
const attempt = leakedTx?.db
|
|
134
134
|
.insertInto('repo_push_event')
|
|
135
|
-
.values({ eventType: '
|
|
135
|
+
.values({ eventType: 'pds_takedown', subjectDid: 'b' })
|
|
136
136
|
.execute()
|
|
137
137
|
await expect(attempt).rejects.toThrow('tx already failed')
|
|
138
138
|
|
|
@@ -156,7 +156,7 @@ describe('db', () => {
|
|
|
156
156
|
const query = dbTxn.db
|
|
157
157
|
.insertInto('repo_push_event')
|
|
158
158
|
.values({
|
|
159
|
-
eventType: '
|
|
159
|
+
eventType: 'pds_takedown',
|
|
160
160
|
subjectDid: name,
|
|
161
161
|
})
|
|
162
162
|
.execute()
|
package/tests/get-record.test.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
SeedClient,
|
|
3
|
+
TestNetwork,
|
|
4
|
+
basicSeed,
|
|
5
|
+
TestOzone,
|
|
6
|
+
ModeratorClient,
|
|
7
|
+
} from '@atproto/dev-env'
|
|
2
8
|
import AtpAgent from '@atproto/api'
|
|
3
9
|
import { AtUri } from '@atproto/syntax'
|
|
4
10
|
import {
|
|
@@ -9,15 +15,19 @@ import { forSnapshot } from './_util'
|
|
|
9
15
|
|
|
10
16
|
describe('admin get record view', () => {
|
|
11
17
|
let network: TestNetwork
|
|
18
|
+
let ozone: TestOzone
|
|
12
19
|
let agent: AtpAgent
|
|
13
20
|
let sc: SeedClient
|
|
21
|
+
let modClient: ModeratorClient
|
|
14
22
|
|
|
15
23
|
beforeAll(async () => {
|
|
16
24
|
network = await TestNetwork.create({
|
|
17
25
|
dbPostgresSchema: 'ozone_admin_get_record',
|
|
18
26
|
})
|
|
19
|
-
|
|
27
|
+
ozone = network.ozone
|
|
28
|
+
agent = ozone.getClient()
|
|
20
29
|
sc = network.getSeedClient()
|
|
30
|
+
modClient = ozone.getModClient()
|
|
21
31
|
await basicSeed(sc)
|
|
22
32
|
await network.processAll()
|
|
23
33
|
})
|
|
@@ -46,8 +56,8 @@ describe('admin get record view', () => {
|
|
|
46
56
|
cid: sc.posts[sc.dids.alice][0].ref.cidStr,
|
|
47
57
|
},
|
|
48
58
|
})
|
|
49
|
-
await
|
|
50
|
-
event: { $type: '
|
|
59
|
+
await modClient.emitEvent({
|
|
60
|
+
event: { $type: 'tools.ozone.moderation.defs#modEventTakedown' },
|
|
51
61
|
subject: {
|
|
52
62
|
$type: 'com.atproto.repo.strongRef',
|
|
53
63
|
uri: sc.posts[sc.dids.alice][0].ref.uriStr,
|
|
@@ -57,26 +67,26 @@ describe('admin get record view', () => {
|
|
|
57
67
|
})
|
|
58
68
|
|
|
59
69
|
it('gets a record by uri, even when taken down.', async () => {
|
|
60
|
-
const result = await agent.api.
|
|
70
|
+
const result = await agent.api.tools.ozone.moderation.getRecord(
|
|
61
71
|
{ uri: sc.posts[sc.dids.alice][0].ref.uriStr },
|
|
62
|
-
{ headers:
|
|
72
|
+
{ headers: await ozone.modHeaders() },
|
|
63
73
|
)
|
|
64
74
|
expect(forSnapshot(result.data)).toMatchSnapshot()
|
|
65
75
|
})
|
|
66
76
|
|
|
67
77
|
it('gets a record by uri and cid.', async () => {
|
|
68
|
-
const result = await agent.api.
|
|
78
|
+
const result = await agent.api.tools.ozone.moderation.getRecord(
|
|
69
79
|
{
|
|
70
80
|
uri: sc.posts[sc.dids.alice][0].ref.uriStr,
|
|
71
81
|
cid: sc.posts[sc.dids.alice][0].ref.cidStr,
|
|
72
82
|
},
|
|
73
|
-
{ headers:
|
|
83
|
+
{ headers: await ozone.modHeaders() },
|
|
74
84
|
)
|
|
75
85
|
expect(forSnapshot(result.data)).toMatchSnapshot()
|
|
76
86
|
})
|
|
77
87
|
|
|
78
88
|
it('fails when record does not exist.', async () => {
|
|
79
|
-
const promise = agent.api.
|
|
89
|
+
const promise = agent.api.tools.ozone.moderation.getRecord(
|
|
80
90
|
{
|
|
81
91
|
uri: AtUri.make(
|
|
82
92
|
sc.dids.alice,
|
|
@@ -84,18 +94,18 @@ describe('admin get record view', () => {
|
|
|
84
94
|
'badrkey',
|
|
85
95
|
).toString(),
|
|
86
96
|
},
|
|
87
|
-
{ headers:
|
|
97
|
+
{ headers: await ozone.modHeaders() },
|
|
88
98
|
)
|
|
89
99
|
await expect(promise).rejects.toThrow('Record not found')
|
|
90
100
|
})
|
|
91
101
|
|
|
92
102
|
it('fails when record cid does not exist.', async () => {
|
|
93
|
-
const promise = agent.api.
|
|
103
|
+
const promise = agent.api.tools.ozone.moderation.getRecord(
|
|
94
104
|
{
|
|
95
105
|
uri: sc.posts[sc.dids.alice][0].ref.uriStr,
|
|
96
106
|
cid: sc.posts[sc.dids.alice][1].ref.cidStr, // Mismatching cid
|
|
97
107
|
},
|
|
98
|
-
{ headers:
|
|
108
|
+
{ headers: await ozone.modHeaders() },
|
|
99
109
|
)
|
|
100
110
|
await expect(promise).rejects.toThrow('Record not found')
|
|
101
111
|
})
|
package/tests/get-repo.test.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
SeedClient,
|
|
3
|
+
TestNetwork,
|
|
4
|
+
TestOzone,
|
|
5
|
+
basicSeed,
|
|
6
|
+
ModeratorClient,
|
|
7
|
+
} from '@atproto/dev-env'
|
|
2
8
|
import AtpAgent from '@atproto/api'
|
|
3
9
|
import {
|
|
4
10
|
REASONOTHER,
|
|
@@ -8,15 +14,21 @@ import { forSnapshot } from './_util'
|
|
|
8
14
|
|
|
9
15
|
describe('admin get repo view', () => {
|
|
10
16
|
let network: TestNetwork
|
|
17
|
+
let ozone: TestOzone
|
|
11
18
|
let agent: AtpAgent
|
|
19
|
+
let pdsAgent: AtpAgent
|
|
12
20
|
let sc: SeedClient
|
|
21
|
+
let modClient: ModeratorClient
|
|
13
22
|
|
|
14
23
|
beforeAll(async () => {
|
|
15
24
|
network = await TestNetwork.create({
|
|
16
25
|
dbPostgresSchema: 'ozone_admin_get_repo',
|
|
17
26
|
})
|
|
18
|
-
|
|
27
|
+
ozone = network.ozone
|
|
28
|
+
agent = ozone.getClient()
|
|
29
|
+
pdsAgent = network.pds.getClient()
|
|
19
30
|
sc = network.getSeedClient()
|
|
31
|
+
modClient = ozone.getModClient()
|
|
20
32
|
await basicSeed(sc)
|
|
21
33
|
await network.processAll()
|
|
22
34
|
})
|
|
@@ -26,8 +38,8 @@ describe('admin get repo view', () => {
|
|
|
26
38
|
})
|
|
27
39
|
|
|
28
40
|
beforeAll(async () => {
|
|
29
|
-
await
|
|
30
|
-
event: { $type: '
|
|
41
|
+
await modClient.emitEvent({
|
|
42
|
+
event: { $type: 'tools.ozone.moderation.defs#modEventAcknowledge' },
|
|
31
43
|
subject: {
|
|
32
44
|
$type: 'com.atproto.admin.defs#repoRef',
|
|
33
45
|
did: sc.dids.alice,
|
|
@@ -50,8 +62,8 @@ describe('admin get repo view', () => {
|
|
|
50
62
|
did: sc.dids.alice,
|
|
51
63
|
},
|
|
52
64
|
})
|
|
53
|
-
await
|
|
54
|
-
event: { $type: '
|
|
65
|
+
await modClient.emitEvent({
|
|
66
|
+
event: { $type: 'tools.ozone.moderation.defs#modEventTakedown' },
|
|
55
67
|
subject: {
|
|
56
68
|
$type: 'com.atproto.admin.defs#repoRef',
|
|
57
69
|
did: sc.dids.alice,
|
|
@@ -60,25 +72,25 @@ describe('admin get repo view', () => {
|
|
|
60
72
|
})
|
|
61
73
|
|
|
62
74
|
it('gets a repo by did, even when taken down.', async () => {
|
|
63
|
-
const result = await agent.api.
|
|
75
|
+
const result = await agent.api.tools.ozone.moderation.getRepo(
|
|
64
76
|
{ did: sc.dids.alice },
|
|
65
|
-
{ headers:
|
|
77
|
+
{ headers: await ozone.modHeaders() },
|
|
66
78
|
)
|
|
67
79
|
expect(forSnapshot(result.data)).toMatchSnapshot()
|
|
68
80
|
})
|
|
69
81
|
|
|
70
82
|
it('does not include account emails for triage mods.', async () => {
|
|
71
|
-
const { data: admin } = await agent.api.
|
|
83
|
+
const { data: admin } = await agent.api.tools.ozone.moderation.getRepo(
|
|
72
84
|
{ did: sc.dids.bob },
|
|
73
|
-
{ headers:
|
|
85
|
+
{ headers: await ozone.modHeaders() },
|
|
74
86
|
)
|
|
75
|
-
const { data: moderator } = await agent.api.
|
|
87
|
+
const { data: moderator } = await agent.api.tools.ozone.moderation.getRepo(
|
|
76
88
|
{ did: sc.dids.bob },
|
|
77
|
-
{ headers:
|
|
89
|
+
{ headers: await ozone.modHeaders('moderator') },
|
|
78
90
|
)
|
|
79
|
-
const { data: triage } = await agent.api.
|
|
91
|
+
const { data: triage } = await agent.api.tools.ozone.moderation.getRepo(
|
|
80
92
|
{ did: sc.dids.bob },
|
|
81
|
-
{ headers:
|
|
93
|
+
{ headers: await ozone.modHeaders('triage') },
|
|
82
94
|
)
|
|
83
95
|
expect(admin.email).toEqual('bob@test.com')
|
|
84
96
|
expect(moderator.email).toEqual('bob@test.com')
|
|
@@ -88,9 +100,9 @@ describe('admin get repo view', () => {
|
|
|
88
100
|
|
|
89
101
|
it('includes emailConfirmedAt timestamp', async () => {
|
|
90
102
|
const { data: beforeEmailVerification } =
|
|
91
|
-
await agent.api.
|
|
103
|
+
await agent.api.tools.ozone.moderation.getRepo(
|
|
92
104
|
{ did: sc.dids.bob },
|
|
93
|
-
{ headers:
|
|
105
|
+
{ headers: await ozone.modHeaders() },
|
|
94
106
|
)
|
|
95
107
|
|
|
96
108
|
expect(beforeEmailVerification.emailConfirmedAt).toBeUndefined()
|
|
@@ -101,7 +113,7 @@ describe('admin get repo view', () => {
|
|
|
101
113
|
sc.dids.bob,
|
|
102
114
|
'confirm_email',
|
|
103
115
|
)
|
|
104
|
-
await
|
|
116
|
+
await pdsAgent.api.com.atproto.server.confirmEmail(
|
|
105
117
|
{ email: bobsAccount.email, token: verificationToken },
|
|
106
118
|
{
|
|
107
119
|
encoding: 'application/json',
|
|
@@ -110,9 +122,9 @@ describe('admin get repo view', () => {
|
|
|
110
122
|
},
|
|
111
123
|
)
|
|
112
124
|
const { data: afterEmailVerification } =
|
|
113
|
-
await agent.api.
|
|
125
|
+
await agent.api.tools.ozone.moderation.getRepo(
|
|
114
126
|
{ did: sc.dids.bob },
|
|
115
|
-
{ headers:
|
|
127
|
+
{ headers: await ozone.modHeaders() },
|
|
116
128
|
)
|
|
117
129
|
|
|
118
130
|
expect(afterEmailVerification.emailConfirmedAt).toBeTruthy()
|
|
@@ -122,9 +134,9 @@ describe('admin get repo view', () => {
|
|
|
122
134
|
})
|
|
123
135
|
|
|
124
136
|
it('fails when repo does not exist.', async () => {
|
|
125
|
-
const promise = agent.api.
|
|
137
|
+
const promise = agent.api.tools.ozone.moderation.getRepo(
|
|
126
138
|
{ did: 'did:plc:doesnotexist' },
|
|
127
|
-
{ headers:
|
|
139
|
+
{ headers: await ozone.modHeaders() },
|
|
128
140
|
)
|
|
129
141
|
await expect(promise).rejects.toThrow('Repo not found')
|
|
130
142
|
})
|
|
@@ -1,49 +1,32 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
} from '@atproto/
|
|
1
|
+
import {
|
|
2
|
+
TestNetwork,
|
|
3
|
+
SeedClient,
|
|
4
|
+
basicSeed,
|
|
5
|
+
ModeratorClient,
|
|
6
|
+
} from '@atproto/dev-env'
|
|
7
|
+
import { ToolsOzoneModerationDefs } from '@atproto/api'
|
|
7
8
|
import {
|
|
8
9
|
REASONMISLEADING,
|
|
9
10
|
REASONSPAM,
|
|
11
|
+
REASONAPPEAL,
|
|
10
12
|
} from '../src/lexicon/types/com/atproto/moderation/defs'
|
|
11
13
|
import {
|
|
12
14
|
REVIEWCLOSED,
|
|
13
15
|
REVIEWOPEN,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
import { REVIEWESCALATED } from '../src/lexicon/types/com/atproto/admin/defs'
|
|
16
|
+
REVIEWESCALATED,
|
|
17
|
+
} from '@atproto/api/src/client/types/tools/ozone/moderation/defs'
|
|
17
18
|
|
|
18
19
|
describe('moderation-appeals', () => {
|
|
19
20
|
let network: TestNetwork
|
|
20
|
-
let agent: AtpAgent
|
|
21
|
-
let pdsAgent: AtpAgent
|
|
22
21
|
let sc: SeedClient
|
|
23
|
-
|
|
24
|
-
const emitModerationEvent = async (
|
|
25
|
-
eventData: ComAtprotoAdminEmitModerationEvent.InputSchema,
|
|
26
|
-
) => {
|
|
27
|
-
return pdsAgent.api.com.atproto.admin.emitModerationEvent(eventData, {
|
|
28
|
-
encoding: 'application/json',
|
|
29
|
-
headers: network.ozone.adminAuthHeaders('moderator'),
|
|
30
|
-
})
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const queryModerationStatuses = (
|
|
34
|
-
statusQuery: ComAtprotoAdminQueryModerationStatuses.QueryParams,
|
|
35
|
-
) =>
|
|
36
|
-
agent.api.com.atproto.admin.queryModerationStatuses(statusQuery, {
|
|
37
|
-
headers: network.ozone.adminAuthHeaders('moderator'),
|
|
38
|
-
})
|
|
22
|
+
let modClient: ModeratorClient
|
|
39
23
|
|
|
40
24
|
beforeAll(async () => {
|
|
41
25
|
network = await TestNetwork.create({
|
|
42
26
|
dbPostgresSchema: 'ozone_moderation_appeals',
|
|
43
27
|
})
|
|
44
|
-
agent = network.ozone.getClient()
|
|
45
|
-
pdsAgent = network.pds.getClient()
|
|
46
28
|
sc = network.getSeedClient()
|
|
29
|
+
modClient = network.ozone.getModClient()
|
|
47
30
|
await basicSeed(sc)
|
|
48
31
|
await network.processAll()
|
|
49
32
|
})
|
|
@@ -56,13 +39,13 @@ describe('moderation-appeals', () => {
|
|
|
56
39
|
subject: string,
|
|
57
40
|
status: string,
|
|
58
41
|
appealed: boolean | undefined,
|
|
59
|
-
): Promise<
|
|
60
|
-
const
|
|
42
|
+
): Promise<ToolsOzoneModerationDefs.SubjectStatusView | undefined> => {
|
|
43
|
+
const res = await modClient.queryStatuses({
|
|
61
44
|
subject,
|
|
62
45
|
})
|
|
63
|
-
expect(
|
|
64
|
-
expect(
|
|
65
|
-
return
|
|
46
|
+
expect(res.subjectStatuses[0]?.reviewState).toEqual(status)
|
|
47
|
+
expect(res.subjectStatuses[0]?.appealed).toEqual(appealed)
|
|
48
|
+
return res.subjectStatuses[0]
|
|
66
49
|
}
|
|
67
50
|
|
|
68
51
|
describe('appeals from users', () => {
|
|
@@ -83,13 +66,12 @@ describe('moderation-appeals', () => {
|
|
|
83
66
|
|
|
84
67
|
it('only changes subject status if original author of the content or a moderator is appealing', async () => {
|
|
85
68
|
// Create a report by alice
|
|
86
|
-
await
|
|
69
|
+
await modClient.emitEvent({
|
|
87
70
|
event: {
|
|
88
|
-
$type: '
|
|
71
|
+
$type: 'tools.ozone.moderation.defs#modEventReport',
|
|
89
72
|
reportType: REASONMISLEADING,
|
|
90
73
|
},
|
|
91
74
|
subject: getBobsPostSubject(),
|
|
92
|
-
createdBy: sc.dids.alice,
|
|
93
75
|
})
|
|
94
76
|
|
|
95
77
|
await assertBobsPostStatus(REVIEWOPEN, undefined)
|
|
@@ -108,13 +90,12 @@ describe('moderation-appeals', () => {
|
|
|
108
90
|
await assertBobsPostStatus(REVIEWOPEN, undefined)
|
|
109
91
|
|
|
110
92
|
// Emit report event as moderator
|
|
111
|
-
await
|
|
93
|
+
await modClient.emitEvent({
|
|
112
94
|
event: {
|
|
113
|
-
$type: '
|
|
95
|
+
$type: 'tools.ozone.moderation.defs#modEventReport',
|
|
114
96
|
reportType: REASONAPPEAL,
|
|
115
97
|
},
|
|
116
98
|
subject: getBobsPostSubject(),
|
|
117
|
-
createdBy: sc.dids.alice,
|
|
118
99
|
})
|
|
119
100
|
|
|
120
101
|
// Verify that appeal status changed when appeal report was emitted by moderator
|
|
@@ -151,23 +132,21 @@ describe('moderation-appeals', () => {
|
|
|
151
132
|
})
|
|
152
133
|
it('allows multiple appeals and updates last appealed timestamp', async () => {
|
|
153
134
|
// Resolve appeal with acknowledge
|
|
154
|
-
await
|
|
135
|
+
await modClient.emitEvent({
|
|
155
136
|
event: {
|
|
156
|
-
$type: '
|
|
137
|
+
$type: 'tools.ozone.moderation.defs#modEventResolveAppeal',
|
|
157
138
|
},
|
|
158
139
|
subject: getBobsPostSubject(),
|
|
159
|
-
createdBy: sc.dids.carol,
|
|
160
140
|
})
|
|
161
141
|
|
|
162
142
|
const previousStatus = await assertBobsPostStatus(REVIEWESCALATED, false)
|
|
163
143
|
|
|
164
|
-
await
|
|
144
|
+
await modClient.emitEvent({
|
|
165
145
|
event: {
|
|
166
|
-
$type: '
|
|
146
|
+
$type: 'tools.ozone.moderation.defs#modEventReport',
|
|
167
147
|
reportType: REASONAPPEAL,
|
|
168
148
|
},
|
|
169
149
|
subject: getBobsPostSubject(),
|
|
170
|
-
createdBy: sc.dids.bob,
|
|
171
150
|
})
|
|
172
151
|
|
|
173
152
|
// Verify that even after the appeal event by bob for his post, the appeal status is true again with new timestamp
|
|
@@ -186,32 +165,29 @@ describe('moderation-appeals', () => {
|
|
|
186
165
|
})
|
|
187
166
|
it('appeal status is maintained while review state changes based on incoming events', async () => {
|
|
188
167
|
// Bob reports alice's post
|
|
189
|
-
await
|
|
168
|
+
await modClient.emitEvent({
|
|
190
169
|
event: {
|
|
191
|
-
$type: '
|
|
170
|
+
$type: 'tools.ozone.moderation.defs#modEventReport',
|
|
192
171
|
reportType: REASONMISLEADING,
|
|
193
172
|
},
|
|
194
173
|
subject: getAlicesPostSubject(),
|
|
195
|
-
createdBy: sc.dids.bob,
|
|
196
174
|
})
|
|
197
175
|
|
|
198
176
|
// Moderator acknowledges the report, assume a label was applied too
|
|
199
|
-
await
|
|
177
|
+
await modClient.emitEvent({
|
|
200
178
|
event: {
|
|
201
|
-
$type: '
|
|
179
|
+
$type: 'tools.ozone.moderation.defs#modEventAcknowledge',
|
|
202
180
|
},
|
|
203
181
|
subject: getAlicesPostSubject(),
|
|
204
|
-
createdBy: sc.dids.carol,
|
|
205
182
|
})
|
|
206
183
|
|
|
207
184
|
// Alice appeals the report
|
|
208
|
-
await
|
|
185
|
+
await modClient.emitEvent({
|
|
209
186
|
event: {
|
|
210
|
-
$type: '
|
|
187
|
+
$type: 'tools.ozone.moderation.defs#modEventReport',
|
|
211
188
|
reportType: REASONAPPEAL,
|
|
212
189
|
},
|
|
213
190
|
subject: getAlicesPostSubject(),
|
|
214
|
-
createdBy: sc.dids.alice,
|
|
215
191
|
})
|
|
216
192
|
|
|
217
193
|
await assertSubjectStatus(
|
|
@@ -221,13 +197,12 @@ describe('moderation-appeals', () => {
|
|
|
221
197
|
)
|
|
222
198
|
|
|
223
199
|
// Bob reports it again
|
|
224
|
-
await
|
|
200
|
+
await modClient.emitEvent({
|
|
225
201
|
event: {
|
|
226
|
-
$type: '
|
|
202
|
+
$type: 'tools.ozone.moderation.defs#modEventReport',
|
|
227
203
|
reportType: REASONSPAM,
|
|
228
204
|
},
|
|
229
205
|
subject: getAlicesPostSubject(),
|
|
230
|
-
createdBy: sc.dids.bob,
|
|
231
206
|
})
|
|
232
207
|
|
|
233
208
|
// Assert that the status is still REVIEWESCALATED, as report events are meant to do
|
|
@@ -238,12 +213,11 @@ describe('moderation-appeals', () => {
|
|
|
238
213
|
)
|
|
239
214
|
|
|
240
215
|
// Emit an escalation event
|
|
241
|
-
await
|
|
216
|
+
await modClient.emitEvent({
|
|
242
217
|
event: {
|
|
243
|
-
$type: '
|
|
218
|
+
$type: 'tools.ozone.moderation.defs#modEventEscalate',
|
|
244
219
|
},
|
|
245
220
|
subject: getAlicesPostSubject(),
|
|
246
|
-
createdBy: sc.dids.carol,
|
|
247
221
|
})
|
|
248
222
|
|
|
249
223
|
await assertSubjectStatus(
|
|
@@ -253,25 +227,23 @@ describe('moderation-appeals', () => {
|
|
|
253
227
|
)
|
|
254
228
|
|
|
255
229
|
// Emit an acknowledge event
|
|
256
|
-
await
|
|
230
|
+
await modClient.emitEvent({
|
|
257
231
|
event: {
|
|
258
|
-
$type: '
|
|
232
|
+
$type: 'tools.ozone.moderation.defs#modEventAcknowledge',
|
|
259
233
|
},
|
|
260
234
|
subject: getAlicesPostSubject(),
|
|
261
|
-
createdBy: sc.dids.carol,
|
|
262
235
|
})
|
|
263
236
|
|
|
264
237
|
// Assert that status moved on to reviewClosed while appealed status is still true
|
|
265
238
|
await assertSubjectStatus(getAlicesPostSubject().uri, REVIEWCLOSED, true)
|
|
266
239
|
|
|
267
240
|
// Emit a resolveAppeal event
|
|
268
|
-
await
|
|
241
|
+
await modClient.emitEvent({
|
|
269
242
|
event: {
|
|
270
|
-
$type: '
|
|
243
|
+
$type: 'tools.ozone.moderation.defs#modEventResolveAppeal',
|
|
271
244
|
comment: 'lgtm',
|
|
272
245
|
},
|
|
273
246
|
subject: getAlicesPostSubject(),
|
|
274
|
-
createdBy: sc.dids.carol,
|
|
275
247
|
})
|
|
276
248
|
|
|
277
249
|
// Assert that status stayed the same while appealed status is still true
|