@atproto/ozone 0.1.53 → 0.1.55
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/index.d.ts.map +1 -1
- package/dist/api/index.js +6 -0
- package/dist/api/index.js.map +1 -1
- package/dist/api/moderation/queryStatuses.d.ts.map +1 -1
- package/dist/api/moderation/queryStatuses.js +6 -1
- package/dist/api/moderation/queryStatuses.js.map +1 -1
- package/dist/api/setting/listOptions.d.ts +4 -0
- package/dist/api/setting/listOptions.d.ts.map +1 -0
- package/dist/api/setting/listOptions.js +38 -0
- package/dist/api/setting/listOptions.js.map +1 -0
- package/dist/api/setting/removeOptions.d.ts +4 -0
- package/dist/api/setting/removeOptions.d.ts.map +1 -0
- package/dist/api/setting/removeOptions.js +55 -0
- package/dist/api/setting/removeOptions.js.map +1 -0
- package/dist/api/setting/upsertOption.d.ts +4 -0
- package/dist/api/setting/upsertOption.d.ts.map +1 -0
- package/dist/api/setting/upsertOption.js +109 -0
- package/dist/api/setting/upsertOption.js.map +1 -0
- package/dist/context.d.ts +3 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +6 -0
- package/dist/context.js.map +1 -1
- package/dist/db/migrations/20241018T205730722Z-setting.d.ts +4 -0
- package/dist/db/migrations/20241018T205730722Z-setting.d.ts.map +1 -0
- package/dist/db/migrations/20241018T205730722Z-setting.js +26 -0
- package/dist/db/migrations/20241018T205730722Z-setting.js.map +1 -0
- package/dist/db/migrations/20241026T205730722Z-add-hosting-status-to-subject-status.d.ts +4 -0
- package/dist/db/migrations/20241026T205730722Z-add-hosting-status-to-subject-status.d.ts.map +1 -0
- package/dist/db/migrations/20241026T205730722Z-add-hosting-status-to-subject-status.js +57 -0
- package/dist/db/migrations/20241026T205730722Z-add-hosting-status-to-subject-status.js.map +1 -0
- package/dist/db/migrations/index.d.ts +2 -0
- package/dist/db/migrations/index.d.ts.map +1 -1
- package/dist/db/migrations/index.js +3 -1
- package/dist/db/migrations/index.js.map +1 -1
- package/dist/db/schema/index.d.ts +2 -1
- package/dist/db/schema/index.d.ts.map +1 -1
- package/dist/db/schema/moderation_event.d.ts +1 -1
- package/dist/db/schema/moderation_event.d.ts.map +1 -1
- package/dist/db/schema/moderation_subject_status.d.ts +6 -0
- package/dist/db/schema/moderation_subject_status.d.ts.map +1 -1
- package/dist/db/schema/setting.d.ts +21 -0
- package/dist/db/schema/setting.d.ts.map +1 -0
- package/dist/db/schema/setting.js +5 -0
- package/dist/db/schema/setting.js.map +1 -0
- 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 +362 -1
- package/dist/lexicon/lexicons.d.ts.map +1 -1
- package/dist/lexicon/lexicons.js +406 -5
- package/dist/lexicon/lexicons.js.map +1 -1
- package/dist/lexicon/types/chat/bsky/convo/defs.d.ts +1 -0
- package/dist/lexicon/types/chat/bsky/convo/defs.d.ts.map +1 -1
- package/dist/lexicon/types/chat/bsky/convo/defs.js.map +1 -1
- package/dist/lexicon/types/tools/ozone/moderation/defs.d.ts +60 -4
- package/dist/lexicon/types/tools/ozone/moderation/defs.d.ts.map +1 -1
- package/dist/lexicon/types/tools/ozone/moderation/defs.js +50 -0
- package/dist/lexicon/types/tools/ozone/moderation/defs.js.map +1 -1
- package/dist/lexicon/types/tools/ozone/moderation/emitEvent.d.ts +1 -1
- package/dist/lexicon/types/tools/ozone/moderation/emitEvent.d.ts.map +1 -1
- package/dist/lexicon/types/tools/ozone/moderation/queryStatuses.d.ts +10 -0
- package/dist/lexicon/types/tools/ozone/moderation/queryStatuses.d.ts.map +1 -1
- package/dist/lexicon/types/tools/ozone/setting/defs.d.ts +20 -0
- package/dist/lexicon/types/tools/ozone/setting/defs.d.ts.map +1 -0
- package/dist/lexicon/types/tools/ozone/setting/defs.js +15 -0
- package/dist/lexicon/types/tools/ozone/setting/defs.js.map +1 -0
- package/dist/lexicon/types/tools/ozone/setting/listOptions.d.ts +43 -0
- package/dist/lexicon/types/tools/ozone/setting/listOptions.d.ts.map +1 -0
- package/dist/lexicon/types/tools/ozone/setting/listOptions.js +3 -0
- package/dist/lexicon/types/tools/ozone/setting/listOptions.js.map +1 -0
- package/dist/lexicon/types/tools/ozone/setting/removeOptions.d.ts +40 -0
- package/dist/lexicon/types/tools/ozone/setting/removeOptions.d.ts.map +1 -0
- package/dist/lexicon/types/tools/ozone/setting/removeOptions.js +3 -0
- package/dist/lexicon/types/tools/ozone/setting/removeOptions.js.map +1 -0
- package/dist/lexicon/types/tools/ozone/setting/upsertOption.d.ts +45 -0
- package/dist/lexicon/types/tools/ozone/setting/upsertOption.d.ts.map +1 -0
- package/dist/lexicon/types/tools/ozone/setting/upsertOption.js +3 -0
- package/dist/lexicon/types/tools/ozone/setting/upsertOption.js.map +1 -0
- package/dist/mod-service/index.d.ts +19 -2
- package/dist/mod-service/index.d.ts.map +1 -1
- package/dist/mod-service/index.js +37 -1
- package/dist/mod-service/index.js.map +1 -1
- package/dist/mod-service/status.d.ts +2 -22
- package/dist/mod-service/status.d.ts.map +1 -1
- package/dist/mod-service/status.js +91 -1
- package/dist/mod-service/status.js.map +1 -1
- package/dist/mod-service/types.d.ts +19 -1
- package/dist/mod-service/types.d.ts.map +1 -1
- package/dist/mod-service/views.d.ts.map +1 -1
- package/dist/mod-service/views.js +36 -1
- package/dist/mod-service/views.js.map +1 -1
- package/dist/setting/service.d.ts +33 -0
- package/dist/setting/service.d.ts.map +1 -0
- package/dist/setting/service.js +101 -0
- package/dist/setting/service.js.map +1 -0
- package/package.json +10 -10
- package/src/api/index.ts +6 -0
- package/src/api/moderation/queryStatuses.ts +10 -0
- package/src/api/setting/listOptions.ts +44 -0
- package/src/api/setting/removeOptions.ts +63 -0
- package/src/api/setting/upsertOption.ts +142 -0
- package/src/context.ts +8 -0
- package/src/db/migrations/20241018T205730722Z-setting.ts +27 -0
- package/src/db/migrations/20241026T205730722Z-add-hosting-status-to-subject-status.ts +57 -0
- package/src/db/migrations/index.ts +2 -0
- package/src/db/schema/index.ts +3 -1
- package/src/db/schema/moderation_event.ts +3 -0
- package/src/db/schema/moderation_subject_status.ts +6 -0
- package/src/db/schema/setting.ts +24 -0
- package/src/lexicon/index.ts +46 -0
- package/src/lexicon/lexicons.ts +417 -5
- package/src/lexicon/types/chat/bsky/convo/defs.ts +1 -0
- package/src/lexicon/types/tools/ozone/moderation/defs.ts +132 -2
- package/src/lexicon/types/tools/ozone/moderation/emitEvent.ts +3 -0
- package/src/lexicon/types/tools/ozone/moderation/queryStatuses.ts +10 -0
- package/src/lexicon/types/tools/ozone/setting/defs.ts +37 -0
- package/src/lexicon/types/tools/ozone/setting/listOptions.ts +53 -0
- package/src/lexicon/types/tools/ozone/setting/removeOptions.ts +49 -0
- package/src/lexicon/types/tools/ozone/setting/upsertOption.ts +58 -0
- package/src/mod-service/index.ts +52 -0
- package/src/mod-service/status.ts +114 -2
- package/src/mod-service/types.ts +25 -0
- package/src/mod-service/views.ts +45 -2
- package/src/setting/service.ts +148 -0
- package/tests/__snapshots__/get-record.test.ts.snap +8 -0
- package/tests/__snapshots__/get-records.test.ts.snap +4 -0
- package/tests/__snapshots__/get-repo.test.ts.snap +4 -0
- package/tests/__snapshots__/get-repos.test.ts.snap +4 -0
- package/tests/__snapshots__/moderation-events.test.ts.snap +4 -0
- package/tests/__snapshots__/moderation-statuses.test.ts.snap +24 -0
- package/tests/__snapshots__/settings.test.ts.snap +52 -0
- package/tests/record-and-account-events.test.ts +185 -0
- package/tests/settings.test.ts +310 -0
- package/tsconfig.build.tsbuildinfo +1 -1
- package/tsconfig.tests.tsbuildinfo +1 -1
|
@@ -29,6 +29,10 @@ Object {
|
|
|
29
29
|
"moderation": Object {
|
|
30
30
|
"subjectStatus": Object {
|
|
31
31
|
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
32
|
+
"hosting": Object {
|
|
33
|
+
"$type": "tools.ozone.moderation.defs#recordHosting",
|
|
34
|
+
"status": "unknown",
|
|
35
|
+
},
|
|
32
36
|
"id": 1,
|
|
33
37
|
"lastReportedAt": "1970-01-01T00:00:00.000Z",
|
|
34
38
|
"lastReviewedAt": "1970-01-01T00:00:00.000Z",
|
|
@@ -129,6 +133,10 @@ Object {
|
|
|
129
133
|
"moderation": Object {
|
|
130
134
|
"subjectStatus": Object {
|
|
131
135
|
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
136
|
+
"hosting": Object {
|
|
137
|
+
"$type": "tools.ozone.moderation.defs#recordHosting",
|
|
138
|
+
"status": "unknown",
|
|
139
|
+
},
|
|
132
140
|
"id": 1,
|
|
133
141
|
"lastReportedAt": "1970-01-01T00:00:00.000Z",
|
|
134
142
|
"lastReviewedAt": "1970-01-01T00:00:00.000Z",
|
|
@@ -32,6 +32,10 @@ Object {
|
|
|
32
32
|
"moderation": Object {
|
|
33
33
|
"subjectStatus": Object {
|
|
34
34
|
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
35
|
+
"hosting": Object {
|
|
36
|
+
"$type": "tools.ozone.moderation.defs#recordHosting",
|
|
37
|
+
"status": "unknown",
|
|
38
|
+
},
|
|
35
39
|
"id": 1,
|
|
36
40
|
"lastReportedAt": "1970-01-01T00:00:00.000Z",
|
|
37
41
|
"lastReviewedAt": "1970-01-01T00:00:00.000Z",
|
|
@@ -23,6 +23,10 @@ Object {
|
|
|
23
23
|
"moderation": Object {
|
|
24
24
|
"subjectStatus": Object {
|
|
25
25
|
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
26
|
+
"hosting": Object {
|
|
27
|
+
"$type": "tools.ozone.moderation.defs#accountHosting",
|
|
28
|
+
"status": "unknown",
|
|
29
|
+
},
|
|
26
30
|
"id": 1,
|
|
27
31
|
"lastReportedAt": "1970-01-01T00:00:00.000Z",
|
|
28
32
|
"lastReviewedAt": "1970-01-01T00:00:00.000Z",
|
|
@@ -26,6 +26,10 @@ Object {
|
|
|
26
26
|
"moderation": Object {
|
|
27
27
|
"subjectStatus": Object {
|
|
28
28
|
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
29
|
+
"hosting": Object {
|
|
30
|
+
"$type": "tools.ozone.moderation.defs#accountHosting",
|
|
31
|
+
"status": "unknown",
|
|
32
|
+
},
|
|
29
33
|
"id": 1,
|
|
30
34
|
"lastReportedAt": "1970-01-01T00:00:00.000Z",
|
|
31
35
|
"lastReviewedAt": "1970-01-01T00:00:00.000Z",
|
|
@@ -19,6 +19,10 @@ Object {
|
|
|
19
19
|
"moderation": Object {
|
|
20
20
|
"subjectStatus": Object {
|
|
21
21
|
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
22
|
+
"hosting": Object {
|
|
23
|
+
"$type": "tools.ozone.moderation.defs#accountHosting",
|
|
24
|
+
"status": "unknown",
|
|
25
|
+
},
|
|
22
26
|
"id": 1,
|
|
23
27
|
"lastReportedAt": "1970-01-01T00:00:00.000Z",
|
|
24
28
|
"lastReviewedAt": "1970-01-01T00:00:00.000Z",
|
|
@@ -4,6 +4,10 @@ exports[`moderation-statuses query statuses returns statuses filtered by subject
|
|
|
4
4
|
Array [
|
|
5
5
|
Object {
|
|
6
6
|
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
7
|
+
"hosting": Object {
|
|
8
|
+
"$type": "tools.ozone.moderation.defs#recordHosting",
|
|
9
|
+
"status": "unknown",
|
|
10
|
+
},
|
|
7
11
|
"id": 7,
|
|
8
12
|
"lastReportedAt": "1970-01-01T00:00:00.000Z",
|
|
9
13
|
"reviewState": "tools.ozone.moderation.defs#reviewOpen",
|
|
@@ -23,6 +27,10 @@ Array [
|
|
|
23
27
|
},
|
|
24
28
|
Object {
|
|
25
29
|
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
30
|
+
"hosting": Object {
|
|
31
|
+
"$type": "tools.ozone.moderation.defs#accountHosting",
|
|
32
|
+
"status": "unknown",
|
|
33
|
+
},
|
|
26
34
|
"id": 5,
|
|
27
35
|
"lastReportedAt": "1970-01-01T00:00:00.000Z",
|
|
28
36
|
"reviewState": "tools.ozone.moderation.defs#reviewOpen",
|
|
@@ -46,6 +54,10 @@ exports[`moderation-statuses query statuses returns statuses for subjects that r
|
|
|
46
54
|
Array [
|
|
47
55
|
Object {
|
|
48
56
|
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
57
|
+
"hosting": Object {
|
|
58
|
+
"$type": "tools.ozone.moderation.defs#recordHosting",
|
|
59
|
+
"status": "unknown",
|
|
60
|
+
},
|
|
49
61
|
"id": 7,
|
|
50
62
|
"lastReportedAt": "1970-01-01T00:00:00.000Z",
|
|
51
63
|
"reviewState": "tools.ozone.moderation.defs#reviewOpen",
|
|
@@ -65,6 +77,10 @@ Array [
|
|
|
65
77
|
},
|
|
66
78
|
Object {
|
|
67
79
|
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
80
|
+
"hosting": Object {
|
|
81
|
+
"$type": "tools.ozone.moderation.defs#accountHosting",
|
|
82
|
+
"status": "unknown",
|
|
83
|
+
},
|
|
68
84
|
"id": 5,
|
|
69
85
|
"lastReportedAt": "1970-01-01T00:00:00.000Z",
|
|
70
86
|
"reviewState": "tools.ozone.moderation.defs#reviewOpen",
|
|
@@ -83,6 +99,10 @@ Array [
|
|
|
83
99
|
},
|
|
84
100
|
Object {
|
|
85
101
|
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
102
|
+
"hosting": Object {
|
|
103
|
+
"$type": "tools.ozone.moderation.defs#recordHosting",
|
|
104
|
+
"status": "unknown",
|
|
105
|
+
},
|
|
86
106
|
"id": 3,
|
|
87
107
|
"lastReportedAt": "1970-01-01T00:00:00.000Z",
|
|
88
108
|
"reviewState": "tools.ozone.moderation.defs#reviewOpen",
|
|
@@ -101,6 +121,10 @@ Array [
|
|
|
101
121
|
},
|
|
102
122
|
Object {
|
|
103
123
|
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
124
|
+
"hosting": Object {
|
|
125
|
+
"$type": "tools.ozone.moderation.defs#accountHosting",
|
|
126
|
+
"status": "unknown",
|
|
127
|
+
},
|
|
104
128
|
"id": 1,
|
|
105
129
|
"lastReportedAt": "1970-01-01T00:00:00.000Z",
|
|
106
130
|
"reviewState": "tools.ozone.moderation.defs#reviewOpen",
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`ozone-settings listOptions returns all personal settings 1`] = `
|
|
4
|
+
Array [
|
|
5
|
+
Object {
|
|
6
|
+
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
7
|
+
"createdBy": "user(1)",
|
|
8
|
+
"description": "List of external labelers that will be plugged into the client views",
|
|
9
|
+
"did": "user(1)",
|
|
10
|
+
"key": "tools.ozone.setting.client.externalLabelers",
|
|
11
|
+
"lastUpdatedBy": "user(1)",
|
|
12
|
+
"managerRole": "tools.ozone.team.defs#roleAdmin",
|
|
13
|
+
"scope": "instance",
|
|
14
|
+
"updatedAt": "1970-01-01T00:00:00.000Z",
|
|
15
|
+
"value": Object {
|
|
16
|
+
"dids": Array [
|
|
17
|
+
"user(0)",
|
|
18
|
+
],
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
Object {
|
|
22
|
+
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
23
|
+
"createdBy": "user(1)",
|
|
24
|
+
"description": "This determines how each queue is balanced when sorted by oldest first",
|
|
25
|
+
"did": "user(1)",
|
|
26
|
+
"key": "tools.ozone.setting.client.queueHash",
|
|
27
|
+
"lastUpdatedBy": "user(1)",
|
|
28
|
+
"managerRole": "tools.ozone.team.defs#roleAdmin",
|
|
29
|
+
"scope": "instance",
|
|
30
|
+
"updatedAt": "1970-01-01T00:00:00.000Z",
|
|
31
|
+
"value": Object {
|
|
32
|
+
"val": 10.5,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
Object {
|
|
36
|
+
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
37
|
+
"createdBy": "user(1)",
|
|
38
|
+
"description": "This determines how many queues the client interface will show",
|
|
39
|
+
"did": "user(1)",
|
|
40
|
+
"key": "tools.ozone.setting.client.queues",
|
|
41
|
+
"lastUpdatedBy": "user(1)",
|
|
42
|
+
"managerRole": "tools.ozone.team.defs#roleAdmin",
|
|
43
|
+
"scope": "instance",
|
|
44
|
+
"updatedAt": "1970-01-01T00:00:00.000Z",
|
|
45
|
+
"value": Object {
|
|
46
|
+
"stratosphere": Object {
|
|
47
|
+
"name": "Stratosphere",
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
]
|
|
52
|
+
`;
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import {
|
|
2
|
+
TestNetwork,
|
|
3
|
+
SeedClient,
|
|
4
|
+
basicSeed,
|
|
5
|
+
ModeratorClient,
|
|
6
|
+
} from '@atproto/dev-env'
|
|
7
|
+
import {
|
|
8
|
+
ComAtprotoModerationDefs,
|
|
9
|
+
ToolsOzoneModerationDefs,
|
|
10
|
+
} from '@atproto/api'
|
|
11
|
+
import { REVIEWOPEN } from '../src/lexicon/types/tools/ozone/moderation/defs'
|
|
12
|
+
import { ToolsOzoneModerationEmitEvent as EmitModerationEvent } from '@atproto/api'
|
|
13
|
+
describe('record and account events on moderation subjects', () => {
|
|
14
|
+
let network: TestNetwork
|
|
15
|
+
let sc: SeedClient
|
|
16
|
+
let modClient: ModeratorClient
|
|
17
|
+
|
|
18
|
+
beforeAll(async () => {
|
|
19
|
+
network = await TestNetwork.create({
|
|
20
|
+
dbPostgresSchema: 'ozone_record_and_account_events',
|
|
21
|
+
})
|
|
22
|
+
sc = network.getSeedClient()
|
|
23
|
+
modClient = network.ozone.getModClient()
|
|
24
|
+
await basicSeed(sc)
|
|
25
|
+
await network.processAll()
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
afterAll(async () => {
|
|
29
|
+
await network.close()
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
const getSubjectStatus = async (
|
|
33
|
+
subject: string,
|
|
34
|
+
): Promise<ToolsOzoneModerationDefs.SubjectStatusView | undefined> => {
|
|
35
|
+
const res = await modClient.queryStatuses({
|
|
36
|
+
subject,
|
|
37
|
+
})
|
|
38
|
+
return res.subjectStatuses[0]
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
describe('record events', () => {
|
|
42
|
+
const emitRecordEvent = async (
|
|
43
|
+
subject: EmitModerationEvent.InputSchema['subject'],
|
|
44
|
+
op: 'create' | 'update' | 'delete',
|
|
45
|
+
) => {
|
|
46
|
+
return await modClient.emitEvent(
|
|
47
|
+
{
|
|
48
|
+
event: {
|
|
49
|
+
op,
|
|
50
|
+
timestamp: new Date().toISOString(),
|
|
51
|
+
$type: 'tools.ozone.moderation.defs#recordEvent',
|
|
52
|
+
},
|
|
53
|
+
subject,
|
|
54
|
+
createdBy: 'did:example:admin',
|
|
55
|
+
},
|
|
56
|
+
'admin',
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
it('saves updated and deleted timestamps and record status', async () => {
|
|
61
|
+
const bobsPostSubject = {
|
|
62
|
+
$type: 'com.atproto.repo.strongRef',
|
|
63
|
+
uri: sc.posts[sc.dids.bob][1].ref.uriStr,
|
|
64
|
+
cid: sc.posts[sc.dids.bob][1].ref.cidStr,
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
await sc.createReport({
|
|
68
|
+
reportedBy: sc.dids.carol,
|
|
69
|
+
reasonType: ComAtprotoModerationDefs.REASONMISLEADING,
|
|
70
|
+
reason: 'misleading',
|
|
71
|
+
subject: bobsPostSubject,
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
await emitRecordEvent(bobsPostSubject, 'update')
|
|
75
|
+
const statusAfterUpdate = await getSubjectStatus(bobsPostSubject.uri)
|
|
76
|
+
expect(statusAfterUpdate?.hosting?.updatedAt).toBeTruthy()
|
|
77
|
+
|
|
78
|
+
await emitRecordEvent(bobsPostSubject, 'delete')
|
|
79
|
+
const statusAfterDelete = await getSubjectStatus(bobsPostSubject.uri)
|
|
80
|
+
expect(statusAfterDelete?.hosting?.deletedAt).toBeTruthy()
|
|
81
|
+
expect(statusAfterDelete?.hosting?.status).toEqual('deleted')
|
|
82
|
+
// Ensure that due to delete or update event, review state does not change
|
|
83
|
+
expect(statusAfterDelete?.reviewState).toEqual(REVIEWOPEN)
|
|
84
|
+
})
|
|
85
|
+
})
|
|
86
|
+
describe('account/identity events', () => {
|
|
87
|
+
const emitAccountEvent = async (
|
|
88
|
+
subject: EmitModerationEvent.InputSchema['subject'],
|
|
89
|
+
active: boolean,
|
|
90
|
+
status?: 'takendown' | 'deleted' | 'deactivated' | 'suspended',
|
|
91
|
+
) => {
|
|
92
|
+
return await modClient.emitEvent(
|
|
93
|
+
{
|
|
94
|
+
event: {
|
|
95
|
+
status,
|
|
96
|
+
active,
|
|
97
|
+
timestamp: new Date().toISOString(),
|
|
98
|
+
$type: 'tools.ozone.moderation.defs#accountEvent',
|
|
99
|
+
},
|
|
100
|
+
subject,
|
|
101
|
+
createdBy: 'did:example:admin',
|
|
102
|
+
},
|
|
103
|
+
'admin',
|
|
104
|
+
)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
it('saves updated and deleted timestamps and account status', async () => {
|
|
108
|
+
const carolsAccountSubject = {
|
|
109
|
+
$type: 'com.atproto.admin.defs#repoRef',
|
|
110
|
+
did: sc.dids.carol,
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
await sc.createReport({
|
|
114
|
+
reportedBy: sc.dids.carol,
|
|
115
|
+
reasonType: ComAtprotoModerationDefs.REASONMISLEADING,
|
|
116
|
+
reason: 'misleading',
|
|
117
|
+
subject: carolsAccountSubject,
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
await emitAccountEvent(carolsAccountSubject, false, 'deactivated')
|
|
121
|
+
const statusAfterDeactivation = await getSubjectStatus(
|
|
122
|
+
carolsAccountSubject.did,
|
|
123
|
+
)
|
|
124
|
+
expect(statusAfterDeactivation?.hosting?.deactivatedAt).toBeTruthy()
|
|
125
|
+
expect(statusAfterDeactivation?.hosting?.status).toEqual('deactivated')
|
|
126
|
+
expect(statusAfterDeactivation?.reviewState).toEqual(REVIEWOPEN)
|
|
127
|
+
|
|
128
|
+
await emitAccountEvent(carolsAccountSubject, true)
|
|
129
|
+
const statusAfterReactivation = await getSubjectStatus(
|
|
130
|
+
carolsAccountSubject.did,
|
|
131
|
+
)
|
|
132
|
+
expect(statusAfterReactivation?.hosting?.updatedAt).toBeTruthy()
|
|
133
|
+
expect(statusAfterReactivation?.hosting?.status).toEqual('active')
|
|
134
|
+
expect(statusAfterReactivation?.hosting?.deletedAt).toBeFalsy()
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
it('gets statuses by hosting properties', async () => {
|
|
138
|
+
await Promise.all([
|
|
139
|
+
emitAccountEvent(
|
|
140
|
+
{
|
|
141
|
+
$type: 'com.atproto.admin.defs#repoRef',
|
|
142
|
+
did: sc.dids.carol,
|
|
143
|
+
},
|
|
144
|
+
false,
|
|
145
|
+
'deactivated',
|
|
146
|
+
),
|
|
147
|
+
emitAccountEvent(
|
|
148
|
+
{
|
|
149
|
+
$type: 'com.atproto.admin.defs#repoRef',
|
|
150
|
+
did: sc.dids.bob,
|
|
151
|
+
},
|
|
152
|
+
false,
|
|
153
|
+
'deleted',
|
|
154
|
+
),
|
|
155
|
+
])
|
|
156
|
+
const [
|
|
157
|
+
{ subjectStatuses: deactivatedOrDeletedStatuses },
|
|
158
|
+
{ subjectStatuses: deletedStatusesInPastDay },
|
|
159
|
+
{ subjectStatuses: deletedStatusesBeforeYesterday },
|
|
160
|
+
] = await Promise.all([
|
|
161
|
+
modClient.queryStatuses({
|
|
162
|
+
hostingStatuses: ['deactivated', 'deleted'],
|
|
163
|
+
}),
|
|
164
|
+
modClient.queryStatuses({
|
|
165
|
+
hostingDeletedAfter: new Date(
|
|
166
|
+
Date.now() - 1000 * 60 * 60 * 24,
|
|
167
|
+
).toISOString(),
|
|
168
|
+
}),
|
|
169
|
+
modClient.queryStatuses({
|
|
170
|
+
hostingDeletedBefore: new Date(
|
|
171
|
+
Date.now() - 1000 * 60 * 60 * 24,
|
|
172
|
+
).toISOString(),
|
|
173
|
+
}),
|
|
174
|
+
])
|
|
175
|
+
|
|
176
|
+
expect(deactivatedOrDeletedStatuses.length).toEqual(3)
|
|
177
|
+
expect(deletedStatusesInPastDay.length).toEqual(2)
|
|
178
|
+
expect(deletedStatusesInPastDay[0]?.subject.uri).toEqual(
|
|
179
|
+
sc.posts[sc.dids.bob][1].ref.uriStr,
|
|
180
|
+
)
|
|
181
|
+
expect(deletedStatusesInPastDay[1]?.subject.did).toEqual(sc.dids.bob)
|
|
182
|
+
expect(deletedStatusesBeforeYesterday.length).toEqual(0)
|
|
183
|
+
})
|
|
184
|
+
})
|
|
185
|
+
})
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import { TestNetwork, SeedClient, basicSeed } from '@atproto/dev-env'
|
|
2
|
+
import AtpAgent, {
|
|
3
|
+
ToolsOzoneSettingListOptions,
|
|
4
|
+
ToolsOzoneSettingUpsertOption,
|
|
5
|
+
} from '@atproto/api'
|
|
6
|
+
import { ids } from '../src/lexicon/lexicons'
|
|
7
|
+
import { SettingScope } from '../dist/db/schema/setting'
|
|
8
|
+
import { forSnapshot } from './_util'
|
|
9
|
+
|
|
10
|
+
describe('ozone-settings', () => {
|
|
11
|
+
let network: TestNetwork
|
|
12
|
+
let agent: AtpAgent
|
|
13
|
+
let sc: SeedClient
|
|
14
|
+
|
|
15
|
+
const upsertOption = async (
|
|
16
|
+
setting: ToolsOzoneSettingUpsertOption.InputSchema,
|
|
17
|
+
callerRole: 'admin' | 'moderator' | 'triage' = 'admin',
|
|
18
|
+
) => {
|
|
19
|
+
const { data } = await agent.tools.ozone.setting.upsertOption(setting, {
|
|
20
|
+
encoding: 'application/json',
|
|
21
|
+
headers: await network.ozone.modHeaders(
|
|
22
|
+
ids.ToolsOzoneSettingUpsertOption,
|
|
23
|
+
callerRole,
|
|
24
|
+
),
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
return data
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const removeOptions = async (
|
|
31
|
+
keys: string[],
|
|
32
|
+
scope: SettingScope,
|
|
33
|
+
callerRole: 'admin' | 'moderator' | 'triage' = 'admin',
|
|
34
|
+
) => {
|
|
35
|
+
await agent.tools.ozone.setting.removeOptions(
|
|
36
|
+
{ keys, scope },
|
|
37
|
+
{
|
|
38
|
+
encoding: 'application/json',
|
|
39
|
+
headers: await network.ozone.modHeaders(
|
|
40
|
+
ids.ToolsOzoneSettingRemoveOptions,
|
|
41
|
+
callerRole,
|
|
42
|
+
),
|
|
43
|
+
},
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const listOptions = async (
|
|
48
|
+
params: ToolsOzoneSettingListOptions.QueryParams,
|
|
49
|
+
callerRole: 'admin' | 'moderator' | 'triage' = 'moderator',
|
|
50
|
+
) => {
|
|
51
|
+
const { data } = await agent.tools.ozone.setting.listOptions(params, {
|
|
52
|
+
headers: await network.ozone.modHeaders(
|
|
53
|
+
ids.ToolsOzoneSettingListOptions,
|
|
54
|
+
callerRole,
|
|
55
|
+
),
|
|
56
|
+
})
|
|
57
|
+
return data
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
beforeAll(async () => {
|
|
61
|
+
network = await TestNetwork.create({
|
|
62
|
+
dbPostgresSchema: 'ozone_settings',
|
|
63
|
+
})
|
|
64
|
+
agent = network.ozone.getClient()
|
|
65
|
+
sc = network.getSeedClient()
|
|
66
|
+
await basicSeed(sc)
|
|
67
|
+
await network.processAll()
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
afterAll(async () => {
|
|
71
|
+
await network.close()
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
describe('upsertOption', () => {
|
|
75
|
+
afterAll(async () => {
|
|
76
|
+
await removeOptions(
|
|
77
|
+
['tools.ozone.setting.upsertTest.labelers'],
|
|
78
|
+
'personal',
|
|
79
|
+
)
|
|
80
|
+
})
|
|
81
|
+
it('only allows managerRole to update instance settings', async () => {
|
|
82
|
+
await upsertOption({
|
|
83
|
+
scope: 'instance',
|
|
84
|
+
key: 'tools.ozone.setting.upsertTest.labelers',
|
|
85
|
+
value: { dids: ['did:plc:xyz'] },
|
|
86
|
+
description: 'triage users can not update this',
|
|
87
|
+
managerRole: 'tools.ozone.team.defs#roleModerator',
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
await expect(
|
|
91
|
+
upsertOption(
|
|
92
|
+
{
|
|
93
|
+
scope: 'instance',
|
|
94
|
+
key: 'tools.ozone.setting.upsertTest.labelers',
|
|
95
|
+
value: { noDids: 'test' },
|
|
96
|
+
description: 'triage users can not update this',
|
|
97
|
+
managerRole: 'tools.ozone.team.defs#roleModerator',
|
|
98
|
+
},
|
|
99
|
+
'triage',
|
|
100
|
+
),
|
|
101
|
+
).rejects.toThrow(/Not permitted/gi)
|
|
102
|
+
|
|
103
|
+
await upsertOption(
|
|
104
|
+
{
|
|
105
|
+
scope: 'instance',
|
|
106
|
+
key: 'tools.ozone.setting.upsertTest.labelers',
|
|
107
|
+
value: { noDids: 'test' },
|
|
108
|
+
description:
|
|
109
|
+
'My personal labelers that i want to use when browsing ozone',
|
|
110
|
+
managerRole: 'tools.ozone.team.defs#roleModerator',
|
|
111
|
+
},
|
|
112
|
+
'moderator',
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
const afterUpdatedByModerator = await listOptions(
|
|
116
|
+
{
|
|
117
|
+
scope: 'instance',
|
|
118
|
+
prefix: 'tools.ozone.setting.upsertTest.labelers',
|
|
119
|
+
},
|
|
120
|
+
'moderator',
|
|
121
|
+
)
|
|
122
|
+
expect(afterUpdatedByModerator.options[0].value?.['dids']).toBeFalsy()
|
|
123
|
+
expect(afterUpdatedByModerator.options[0].value?.['noDids']).toEqual(
|
|
124
|
+
'test',
|
|
125
|
+
)
|
|
126
|
+
await upsertOption(
|
|
127
|
+
{
|
|
128
|
+
scope: 'instance',
|
|
129
|
+
key: 'tools.ozone.setting.upsertTest.labelers',
|
|
130
|
+
value: { dids: 'test' },
|
|
131
|
+
description:
|
|
132
|
+
'My personal labelers that i want to use when browsing ozone',
|
|
133
|
+
managerRole: 'tools.ozone.team.defs#roleModerator',
|
|
134
|
+
},
|
|
135
|
+
'moderator',
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
const afterUpdatedByAdmin = await listOptions(
|
|
139
|
+
{
|
|
140
|
+
scope: 'instance',
|
|
141
|
+
prefix: 'tools.ozone.setting.upsertTest.labelers',
|
|
142
|
+
},
|
|
143
|
+
'admin',
|
|
144
|
+
)
|
|
145
|
+
expect(afterUpdatedByAdmin.options[0].value?.['noDids']).toBeFalsy()
|
|
146
|
+
expect(afterUpdatedByAdmin.options[0].value?.['dids']).toEqual('test')
|
|
147
|
+
})
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
describe('listOptions', () => {
|
|
151
|
+
beforeAll(async () => {
|
|
152
|
+
await Promise.all([
|
|
153
|
+
upsertOption({
|
|
154
|
+
scope: 'instance',
|
|
155
|
+
key: 'tools.ozone.setting.client.queues',
|
|
156
|
+
value: { stratosphere: { name: 'Stratosphere' } },
|
|
157
|
+
description:
|
|
158
|
+
'This determines how many queues the client interface will show',
|
|
159
|
+
managerRole: 'tools.ozone.team.defs#roleAdmin',
|
|
160
|
+
}),
|
|
161
|
+
upsertOption({
|
|
162
|
+
scope: 'instance',
|
|
163
|
+
key: 'tools.ozone.setting.client.queueHash',
|
|
164
|
+
value: { val: 10.5 },
|
|
165
|
+
description:
|
|
166
|
+
'This determines how each queue is balanced when sorted by oldest first',
|
|
167
|
+
managerRole: 'tools.ozone.team.defs#roleAdmin',
|
|
168
|
+
}),
|
|
169
|
+
upsertOption({
|
|
170
|
+
scope: 'instance',
|
|
171
|
+
key: 'tools.ozone.setting.client.externalLabelers',
|
|
172
|
+
value: { dids: ['did:plc:xyz'] },
|
|
173
|
+
description:
|
|
174
|
+
'List of external labelers that will be plugged into the client views',
|
|
175
|
+
managerRole: 'tools.ozone.team.defs#roleAdmin',
|
|
176
|
+
}),
|
|
177
|
+
])
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
afterAll(async () => {
|
|
181
|
+
await removeOptions(
|
|
182
|
+
[
|
|
183
|
+
'tools.ozone.setting.client.queues',
|
|
184
|
+
'tools.ozone.setting.client.queueHash',
|
|
185
|
+
'tools.ozone.setting.client.externalLabelers',
|
|
186
|
+
],
|
|
187
|
+
'instance',
|
|
188
|
+
)
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
it('returns all personal settings', async () => {
|
|
192
|
+
const result = await listOptions({ prefix: 'tools.ozone.setting.client' })
|
|
193
|
+
expect(result.options.length).toBe(3)
|
|
194
|
+
|
|
195
|
+
expect(forSnapshot(result.options)).toMatchSnapshot()
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
it('allows paginating options', async () => {
|
|
199
|
+
const params = { prefix: 'tools.ozone.setting.client', limit: 1 }
|
|
200
|
+
const pageOne = await listOptions(params)
|
|
201
|
+
const pageTwo = await listOptions({
|
|
202
|
+
...params,
|
|
203
|
+
cursor: pageOne.cursor,
|
|
204
|
+
})
|
|
205
|
+
const pageThree = await listOptions({
|
|
206
|
+
...params,
|
|
207
|
+
cursor: pageTwo.cursor,
|
|
208
|
+
})
|
|
209
|
+
const pageFour = await listOptions({
|
|
210
|
+
...params,
|
|
211
|
+
cursor: pageThree.cursor,
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
expect(pageFour.options.length).toBe(0)
|
|
215
|
+
expect(pageFour.cursor).toBeUndefined()
|
|
216
|
+
})
|
|
217
|
+
})
|
|
218
|
+
|
|
219
|
+
describe('removeOptions', () => {
|
|
220
|
+
afterAll(async () => {
|
|
221
|
+
await Promise.all([
|
|
222
|
+
removeOptions(['tools.ozone.setting.personal.labelers'], 'personal'),
|
|
223
|
+
removeOptions(
|
|
224
|
+
['tools.ozone.setting.only.mod', 'tools.ozone.setting.only.admin'],
|
|
225
|
+
'instance',
|
|
226
|
+
),
|
|
227
|
+
])
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
it('only allows the owner to delete personal setting', async () => {
|
|
231
|
+
await upsertOption({
|
|
232
|
+
scope: 'personal',
|
|
233
|
+
key: 'tools.ozone.setting.personal.labelers',
|
|
234
|
+
value: { dids: ['did:plc:xyz'] },
|
|
235
|
+
description:
|
|
236
|
+
'My personal labelers that i want to use when browsing ozone',
|
|
237
|
+
managerRole: 'tools.ozone.team.defs#roleOwner',
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
// one user can't remove personal setting of another
|
|
241
|
+
await removeOptions(
|
|
242
|
+
['tools.ozone.setting.personal.labelers'],
|
|
243
|
+
'personal',
|
|
244
|
+
'triage',
|
|
245
|
+
)
|
|
246
|
+
const list = await listOptions({ scope: 'personal' }, 'admin')
|
|
247
|
+
expect(list.options.length).toBe(1)
|
|
248
|
+
|
|
249
|
+
// the owner of the personal setting can remove their own setting
|
|
250
|
+
await removeOptions(['tools.ozone.setting.personal.labelers'], 'personal')
|
|
251
|
+
const listAfterRemoval = await listOptions({ scope: 'personal' }, 'admin')
|
|
252
|
+
expect(listAfterRemoval.options.length).toBe(0)
|
|
253
|
+
})
|
|
254
|
+
|
|
255
|
+
it('only allows managerRole to delete instance setting', async () => {
|
|
256
|
+
await Promise.all([
|
|
257
|
+
upsertOption({
|
|
258
|
+
scope: 'instance',
|
|
259
|
+
key: 'tools.ozone.setting.only.mod',
|
|
260
|
+
value: { dids: ['did:plc:xyz'] },
|
|
261
|
+
description: 'Triage mods can not manage these',
|
|
262
|
+
managerRole: 'tools.ozone.team.defs#roleModerator',
|
|
263
|
+
}),
|
|
264
|
+
upsertOption({
|
|
265
|
+
scope: 'instance',
|
|
266
|
+
key: 'tools.ozone.setting.only.admin',
|
|
267
|
+
value: { dids: ['did:plc:xyz'] },
|
|
268
|
+
description: 'Moderators or triage mods can not manage these',
|
|
269
|
+
managerRole: 'tools.ozone.team.defs#roleAdmin',
|
|
270
|
+
}),
|
|
271
|
+
])
|
|
272
|
+
|
|
273
|
+
await Promise.all([
|
|
274
|
+
removeOptions(['tools.ozone.setting.only.mod'], 'instance', 'triage'),
|
|
275
|
+
removeOptions(
|
|
276
|
+
['tools.ozone.setting.only.admin'],
|
|
277
|
+
'instance',
|
|
278
|
+
'moderator',
|
|
279
|
+
),
|
|
280
|
+
removeOptions(['tools.ozone.setting.only.admin'], 'instance', 'triage'),
|
|
281
|
+
])
|
|
282
|
+
|
|
283
|
+
const afterFailedAttempt = await listOptions(
|
|
284
|
+
{ scope: 'instance', prefix: 'tools.ozone.setting.only' },
|
|
285
|
+
'admin',
|
|
286
|
+
)
|
|
287
|
+
const keysAfterFailedAttempt = afterFailedAttempt.options.map(
|
|
288
|
+
(o) => o.key,
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
const keys = [
|
|
292
|
+
'tools.ozone.setting.only.mod',
|
|
293
|
+
'tools.ozone.setting.only.admin',
|
|
294
|
+
]
|
|
295
|
+
|
|
296
|
+
keys.forEach((key) => expect(keysAfterFailedAttempt).toContain(key))
|
|
297
|
+
|
|
298
|
+
await Promise.all([
|
|
299
|
+
removeOptions(['tools.ozone.setting.only.mod'], 'instance', 'admin'),
|
|
300
|
+
removeOptions(['tools.ozone.setting.only.admin'], 'instance', 'admin'),
|
|
301
|
+
])
|
|
302
|
+
|
|
303
|
+
const afterRemoval = await listOptions(
|
|
304
|
+
{ scope: 'instance', prefix: 'tools.ozone.setting.only' },
|
|
305
|
+
'admin',
|
|
306
|
+
)
|
|
307
|
+
expect(afterRemoval.options.length).toBe(0)
|
|
308
|
+
})
|
|
309
|
+
})
|
|
310
|
+
})
|