@atproto/ozone 0.2.8 → 0.2.11
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 +33 -0
- package/package.json +25 -21
- package/bin/migration-create.ts +0 -38
- package/jest.config.cjs +0 -22
- package/src/api/chat/getActorMetadata.ts +0 -23
- package/src/api/chat/getConvo.ts +0 -23
- package/src/api/chat/getConvoMembers.ts +0 -23
- package/src/api/chat/getConvos.ts +0 -23
- package/src/api/chat/getMessageContext.ts +0 -42
- package/src/api/chat/index.ts +0 -16
- package/src/api/communication/createTemplate.ts +0 -51
- package/src/api/communication/deleteTemplate.ts +0 -23
- package/src/api/communication/listTemplates.ts +0 -31
- package/src/api/communication/updateTemplate.ts +0 -51
- package/src/api/health.ts +0 -27
- package/src/api/index.ts +0 -146
- package/src/api/label/fetchLabels.ts +0 -32
- package/src/api/label/queryLabels.ts +0 -57
- package/src/api/label/subscribeLabels.ts +0 -25
- package/src/api/moderation/cancelScheduledActions.ts +0 -72
- package/src/api/moderation/emitEvent.ts +0 -475
- package/src/api/moderation/getAccountTimeline.ts +0 -160
- package/src/api/moderation/getEvent.ts +0 -19
- package/src/api/moderation/getRecord.ts +0 -40
- package/src/api/moderation/getRecords.ts +0 -50
- package/src/api/moderation/getRepo.ts +0 -34
- package/src/api/moderation/getReporterStats.ts +0 -18
- package/src/api/moderation/getRepos.ts +0 -41
- package/src/api/moderation/getSubjects.ts +0 -101
- package/src/api/moderation/listScheduledActions.ts +0 -45
- package/src/api/moderation/queryEvents.ts +0 -72
- package/src/api/moderation/queryStatuses.ts +0 -23
- package/src/api/moderation/scheduleAction.ts +0 -129
- package/src/api/moderation/searchRepos.ts +0 -46
- package/src/api/moderation/util.ts +0 -96
- package/src/api/proxied.ts +0 -327
- package/src/api/queue/assignModerator.ts +0 -31
- package/src/api/queue/createQueue.ts +0 -62
- package/src/api/queue/deleteQueue.ts +0 -56
- package/src/api/queue/getAssignments.ts +0 -19
- package/src/api/queue/listQueues.ts +0 -39
- package/src/api/queue/routeReports.ts +0 -44
- package/src/api/queue/unassignModerator.ts +0 -26
- package/src/api/queue/updateQueue.ts +0 -54
- package/src/api/report/assignModerator.ts +0 -36
- package/src/api/report/createActivity.ts +0 -57
- package/src/api/report/createReport.ts +0 -93
- package/src/api/report/getAssignments.ts +0 -20
- package/src/api/report/getHistoricalStats.ts +0 -41
- package/src/api/report/getLatestReport.ts +0 -44
- package/src/api/report/getLiveStats.ts +0 -26
- package/src/api/report/getReport.ts +0 -55
- package/src/api/report/listActivities.ts +0 -37
- package/src/api/report/queryActivities.ts +0 -64
- package/src/api/report/queryReports.ts +0 -44
- package/src/api/report/reassignQueue.ts +0 -68
- package/src/api/report/refreshStats.ts +0 -27
- package/src/api/report/unassignModerator.ts +0 -21
- package/src/api/safelink/addRule.ts +0 -48
- package/src/api/safelink/queryEvents.ts +0 -32
- package/src/api/safelink/queryRules.ts +0 -58
- package/src/api/safelink/removeRule.ts +0 -42
- package/src/api/safelink/updateRule.ts +0 -48
- package/src/api/server/getConfig.ts +0 -35
- package/src/api/set/addValues.ts +0 -28
- package/src/api/set/deleteSet.ts +0 -34
- package/src/api/set/deleteValues.ts +0 -31
- package/src/api/set/getValues.ts +0 -42
- package/src/api/set/querySets.ts +0 -36
- package/src/api/set/upsertSet.ts +0 -38
- package/src/api/setting/listOptions.ts +0 -44
- package/src/api/setting/removeOptions.ts +0 -64
- package/src/api/setting/upsertOption.ts +0 -156
- package/src/api/team/addMember.ts +0 -51
- package/src/api/team/deleteMember.ts +0 -29
- package/src/api/team/listMembers.ts +0 -20
- package/src/api/team/updateMember.ts +0 -47
- package/src/api/util.ts +0 -265
- package/src/api/verification/grantVerifications.ts +0 -90
- package/src/api/verification/listVerifications.ts +0 -44
- package/src/api/verification/revokeVerifications.ts +0 -43
- package/src/api/well-known.ts +0 -46
- package/src/assignment/index.ts +0 -728
- package/src/auth-verifier.ts +0 -227
- package/src/background.ts +0 -183
- package/src/communication-service/template.ts +0 -110
- package/src/communication-service/util.ts +0 -8
- package/src/config/config.ts +0 -211
- package/src/config/env.ts +0 -95
- package/src/config/index.ts +0 -3
- package/src/config/secrets.ts +0 -17
- package/src/context.ts +0 -399
- package/src/daemon/blob-diverter.ts +0 -186
- package/src/daemon/context.ts +0 -247
- package/src/daemon/event-pusher.ts +0 -363
- package/src/daemon/event-reverser.ts +0 -128
- package/src/daemon/index.ts +0 -33
- package/src/daemon/job-cursor.ts +0 -33
- package/src/daemon/materialized-view-refresher.ts +0 -33
- package/src/daemon/queue-router.ts +0 -101
- package/src/daemon/scheduled-action-processor.ts +0 -304
- package/src/daemon/stats-computer.ts +0 -101
- package/src/daemon/strike-expiry-processor.ts +0 -95
- package/src/daemon/team-profile-synchronizer.ts +0 -15
- package/src/daemon/verification-listener.ts +0 -169
- package/src/db/index.ts +0 -203
- package/src/db/migrations/20231219T205730722Z-init.ts +0 -170
- package/src/db/migrations/20240116T085607200Z-communication-template.ts +0 -23
- package/src/db/migrations/20240201T051104136Z-mod-event-blobs.ts +0 -15
- package/src/db/migrations/20240208T213404429Z-add-tags-column-to-moderation-subject.ts +0 -31
- package/src/db/migrations/20240228T003647759Z-add-label-sigs.ts +0 -25
- package/src/db/migrations/20240408T192432676Z-mute-reporting.ts +0 -15
- package/src/db/migrations/20240506T225055595Z-message-subject.ts +0 -21
- package/src/db/migrations/20240521T211332580Z-member.ts +0 -17
- package/src/db/migrations/20240814T003647759Z-event-created-at-index.ts +0 -13
- package/src/db/migrations/20240903T205730722Z-add-template-lang.ts +0 -12
- package/src/db/migrations/20240904T205730722Z-add-subject-did-index.ts +0 -13
- package/src/db/migrations/20241001T205730722Z-subject-status-review-state-index.ts +0 -15
- package/src/db/migrations/20241008T205730722Z-sets.ts +0 -53
- package/src/db/migrations/20241018T205730722Z-setting.ts +0 -27
- package/src/db/migrations/20241026T205730722Z-add-hosting-status-to-subject-status.ts +0 -57
- package/src/db/migrations/20241220T144630860Z-stats-materialized-views.ts +0 -215
- package/src/db/migrations/20250204T003647759Z-add-subject-priority-score.ts +0 -22
- package/src/db/migrations/20250211T003647759Z-add-reporter-stats-index.ts +0 -38
- package/src/db/migrations/20250211T132135150Z-moderation-event-message-partial-idx.ts +0 -26
- package/src/db/migrations/20250221T132135150Z-member-details.ts +0 -14
- package/src/db/migrations/20250404T201720309Z-subject-status-sort-idxs.ts +0 -18
- package/src/db/migrations/20250415T201720309Z-verification.ts +0 -34
- package/src/db/migrations/20250417T201720309Z-firehose-cursor.ts +0 -16
- package/src/db/migrations/20250609T110704000Z-safelink.ts +0 -53
- package/src/db/migrations/20250618T180246000Z-add-mod-tool-to-moderation-event.ts +0 -18
- package/src/db/migrations/20250701T000000000Z-add-age-assurance-state.ts +0 -25
- package/src/db/migrations/20250715T000000000Z-add-mod-event-external-id.ts +0 -15
- package/src/db/migrations/20250718T150931000Z-update-appeal-reason-stats.ts +0 -310
- package/src/db/migrations/20250813T000000000Z-mod-tool-batch-id-index.ts +0 -14
- package/src/db/migrations/20250923T000000000Z-scheduled-actions.ts +0 -56
- package/src/db/migrations/20251008T120000000Z-add-strike-system.ts +0 -87
- package/src/db/migrations/20260210T154806448Z-mod-event-created-by-indexes.ts +0 -22
- package/src/db/migrations/20260219T164523000Z-create-report-table.ts +0 -155
- package/src/db/migrations/20260219T165302248Z-moderator-assignment.ts +0 -42
- package/src/db/migrations/20260225T000000000Z-add-report-queue-table.ts +0 -41
- package/src/db/migrations/20260313T000000000Z-add-report-activity-table.ts +0 -48
- package/src/db/migrations/20260318T152058935Z-add-report-stat.ts +0 -35
- package/src/db/migrations/20260428T000000000Z-add-expiring-tag-table.ts +0 -32
- package/src/db/migrations/20260513T202941104Z-add-subject-convo-id.ts +0 -114
- package/src/db/migrations/20260602T120000000Z-add-report-activity-created-index.ts +0 -17
- package/src/db/migrations/index.ts +0 -44
- package/src/db/migrations/provider.ts +0 -26
- package/src/db/pagination.ts +0 -335
- package/src/db/schema/account_events_stats.ts +0 -16
- package/src/db/schema/account_record_events_stats.ts +0 -15
- package/src/db/schema/account_record_status_stats.ts +0 -15
- package/src/db/schema/account_strike.ts +0 -13
- package/src/db/schema/blob_push_event.ts +0 -21
- package/src/db/schema/communication_template.ts +0 -19
- package/src/db/schema/expiring_tag.ts +0 -18
- package/src/db/schema/firehose_cursor.ts +0 -13
- package/src/db/schema/index.ts +0 -60
- package/src/db/schema/job_cursor.ts +0 -13
- package/src/db/schema/label.ts +0 -22
- package/src/db/schema/member.ts +0 -22
- package/src/db/schema/moderation_event.ts +0 -61
- package/src/db/schema/moderation_subject_status.ts +0 -52
- package/src/db/schema/moderator_assignment.ts +0 -16
- package/src/db/schema/ozone_set.ts +0 -24
- package/src/db/schema/record_events_stats.ts +0 -15
- package/src/db/schema/record_push_event.ts +0 -21
- package/src/db/schema/repo_push_event.ts +0 -19
- package/src/db/schema/report.ts +0 -28
- package/src/db/schema/report_activity.ts +0 -22
- package/src/db/schema/report_queue.ts +0 -21
- package/src/db/schema/report_stat.ts +0 -27
- package/src/db/schema/safelink.ts +0 -39
- package/src/db/schema/scheduled-action.ts +0 -25
- package/src/db/schema/setting.ts +0 -24
- package/src/db/schema/signing_key.ts +0 -10
- package/src/db/schema/verification.ts +0 -21
- package/src/db/types.ts +0 -24
- package/src/error.ts +0 -12
- package/src/image-invalidator.ts +0 -7
- package/src/index.ts +0 -154
- package/src/jetstream/service.ts +0 -107
- package/src/logger.ts +0 -29
- package/src/mod-service/expiring-tags.ts +0 -104
- package/src/mod-service/index.ts +0 -1842
- package/src/mod-service/profile.ts +0 -139
- package/src/mod-service/report.ts +0 -429
- package/src/mod-service/status.ts +0 -549
- package/src/mod-service/strike.ts +0 -96
- package/src/mod-service/subject.ts +0 -311
- package/src/mod-service/types.ts +0 -96
- package/src/mod-service/util.ts +0 -99
- package/src/mod-service/views.ts +0 -912
- package/src/queue/service.ts +0 -603
- package/src/report/activity.ts +0 -281
- package/src/report/handle-report-update.ts +0 -209
- package/src/report/reassign.ts +0 -109
- package/src/report/stats.ts +0 -852
- package/src/report/views.ts +0 -239
- package/src/safelink/service.ts +0 -304
- package/src/scheduled-action/service.ts +0 -281
- package/src/scheduled-action/types.ts +0 -17
- package/src/sequencer/index.ts +0 -2
- package/src/sequencer/outbox.ts +0 -123
- package/src/sequencer/sequencer.ts +0 -147
- package/src/set/service.ts +0 -230
- package/src/setting/constants.ts +0 -3
- package/src/setting/service.ts +0 -148
- package/src/setting/types.ts +0 -3
- package/src/setting/validators.ts +0 -333
- package/src/tag-service/content-tagger.ts +0 -30
- package/src/tag-service/embed-tagger.ts +0 -70
- package/src/tag-service/index.ts +0 -70
- package/src/tag-service/language-data.ts +0 -561
- package/src/tag-service/language-tagger.ts +0 -101
- package/src/tag-service/util.ts +0 -13
- package/src/team/index.ts +0 -296
- package/src/util.ts +0 -230
- package/src/verification/issuer.ts +0 -146
- package/src/verification/service.ts +0 -208
- package/src/verification/util.ts +0 -53
- package/test.env +0 -2
- package/tests/3p-labeler.test.ts +0 -288
- package/tests/__snapshots__/account-strikes.test.ts.snap +0 -159
- package/tests/__snapshots__/age-assurance.test.ts.snap +0 -66
- package/tests/__snapshots__/blob-divert.test.ts.snap +0 -219
- package/tests/__snapshots__/get-account-timeline.test.ts.snap +0 -36
- package/tests/__snapshots__/get-record.test.ts.snap +0 -271
- package/tests/__snapshots__/get-records.test.ts.snap +0 -175
- package/tests/__snapshots__/get-repo.test.ts.snap +0 -91
- package/tests/__snapshots__/get-repos.test.ts.snap +0 -127
- package/tests/__snapshots__/get-starter-pack.test.ts.snap +0 -535
- package/tests/__snapshots__/get-subjects.test.ts.snap +0 -529
- package/tests/__snapshots__/moderation-events.test.ts.snap +0 -347
- package/tests/__snapshots__/moderation-statuses.test.ts.snap +0 -276
- package/tests/__snapshots__/moderation.test.ts.snap +0 -85
- package/tests/__snapshots__/report-reason.test.ts.snap +0 -14
- package/tests/__snapshots__/safelink.test.ts.snap +0 -179
- package/tests/__snapshots__/scheduled-action.test.ts.snap +0 -61
- package/tests/__snapshots__/sets.test.ts.snap +0 -46
- package/tests/__snapshots__/settings.test.ts.snap +0 -52
- package/tests/__snapshots__/team.test.ts.snap +0 -374
- package/tests/__snapshots__/verification-listener.test.ts.snap +0 -152
- package/tests/__snapshots__/verification.test.ts.snap +0 -302
- package/tests/_util.ts +0 -242
- package/tests/account-strikes.test.ts +0 -184
- package/tests/ack-all-subjects-of-account.test.ts +0 -177
- package/tests/age-assurance.test.ts +0 -372
- package/tests/blob-divert.test.ts +0 -106
- package/tests/communication-templates.test.ts +0 -149
- package/tests/content-tagger.test.ts +0 -170
- package/tests/db.test.ts +0 -184
- package/tests/expiring-label.test.ts +0 -72
- package/tests/expiring-tags.test.ts +0 -232
- package/tests/get-account-timeline.test.ts +0 -85
- package/tests/get-config.test.ts +0 -55
- package/tests/get-lists.test.ts +0 -111
- package/tests/get-profiles.test.ts +0 -70
- package/tests/get-record.test.ts +0 -130
- package/tests/get-records.test.ts +0 -91
- package/tests/get-repo.test.ts +0 -171
- package/tests/get-report.test.ts +0 -136
- package/tests/get-reporter-stats.test.ts +0 -132
- package/tests/get-repos.test.ts +0 -91
- package/tests/get-starter-pack.test.ts +0 -115
- package/tests/get-subjects.test.ts +0 -81
- package/tests/mod-tool.test.ts +0 -268
- package/tests/moderation-appeals.test.ts +0 -260
- package/tests/moderation-events.test.ts +0 -756
- package/tests/moderation-status-tags.test.ts +0 -140
- package/tests/moderation-statuses.test.ts +0 -495
- package/tests/moderation.test.ts +0 -992
- package/tests/protected-tags.test.ts +0 -218
- package/tests/query-labels.test.ts +0 -238
- package/tests/query-reports.test.ts +0 -608
- package/tests/queue-assignment.test.ts +0 -428
- package/tests/queue-router.test.ts +0 -306
- package/tests/queues.test.ts +0 -690
- package/tests/record-and-account-events.test.ts +0 -197
- package/tests/repo-search.test.ts +0 -136
- package/tests/report-action.test.ts +0 -308
- package/tests/report-activity.test.ts +0 -711
- package/tests/report-assignment.test.ts +0 -517
- package/tests/report-muting.test.ts +0 -100
- package/tests/report-reason.test.ts +0 -154
- package/tests/report-reassign-queue.test.ts +0 -340
- package/tests/report-routing.test.ts +0 -245
- package/tests/report-stats.test.ts +0 -545
- package/tests/revoke-account-credentials.test.ts +0 -54
- package/tests/safelink.test.ts +0 -534
- package/tests/scheduled-action-processor.test.ts +0 -488
- package/tests/scheduled-action.test.ts +0 -334
- package/tests/sequencer.test.ts +0 -227
- package/tests/server.test.ts +0 -62
- package/tests/sets.test.ts +0 -246
- package/tests/settings.test.ts +0 -308
- package/tests/strike-expiry-processor.test.ts +0 -299
- package/tests/subject-priority-score.test.ts +0 -96
- package/tests/takedown.test.ts +0 -105
- package/tests/team.test.ts +0 -216
- package/tests/verification-listener.test.ts +0 -129
- package/tests/verification.test.ts +0 -186
- package/tsconfig.build.json +0 -9
- package/tsconfig.build.tsbuildinfo +0 -1
- package/tsconfig.json +0 -7
- package/tsconfig.tests.json +0 -8
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ModeratorClient,
|
|
3
|
-
SeedClient,
|
|
4
|
-
TestNetwork,
|
|
5
|
-
basicSeed,
|
|
6
|
-
} from '@atproto/dev-env'
|
|
7
|
-
import { REASONMISLEADING } from '../dist/lexicon/types/com/atproto/moderation/defs.js'
|
|
8
|
-
import { REASONSPAM } from '../src/lexicon/types/com/atproto/moderation/defs.js'
|
|
9
|
-
|
|
10
|
-
describe('moderation subject content tagging', () => {
|
|
11
|
-
let network: TestNetwork
|
|
12
|
-
let sc: SeedClient
|
|
13
|
-
let modClient: ModeratorClient
|
|
14
|
-
|
|
15
|
-
beforeAll(async () => {
|
|
16
|
-
network = await TestNetwork.create({
|
|
17
|
-
dbPostgresSchema: 'ozone_content_tagger_test',
|
|
18
|
-
})
|
|
19
|
-
sc = network.getSeedClient()
|
|
20
|
-
modClient = network.ozone.getModClient()
|
|
21
|
-
await basicSeed(sc)
|
|
22
|
-
await network.processAll()
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
afterAll(async () => {
|
|
26
|
-
await network?.close()
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
const getStatus = async (subject: string) => {
|
|
30
|
-
const { subjectStatuses } = await modClient.queryStatuses({
|
|
31
|
-
subject,
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
return subjectStatuses[0]
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
describe('lang tagger', () => {
|
|
38
|
-
it('Adds language tag to post from text', async () => {
|
|
39
|
-
const createPostAndReport = async (text: string) => {
|
|
40
|
-
const post = await sc.post(sc.dids.carol, text)
|
|
41
|
-
await network.processAll()
|
|
42
|
-
const report = await sc.createReport({
|
|
43
|
-
reasonType: REASONSPAM,
|
|
44
|
-
subject: {
|
|
45
|
-
$type: 'com.atproto.repo.strongRef',
|
|
46
|
-
uri: post.ref.uriStr,
|
|
47
|
-
cid: post.ref.cidStr,
|
|
48
|
-
},
|
|
49
|
-
reportedBy: sc.dids.alice,
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
return { post, report }
|
|
53
|
-
}
|
|
54
|
-
const [japanesePost, greekPost] = await Promise.all([
|
|
55
|
-
createPostAndReport('Xで有名な人達+反AIや絵描きによくない'),
|
|
56
|
-
createPostAndReport(
|
|
57
|
-
'Λορεμ ιπσθμ δολορ σιτ αμετ, μει θτ vιδιτ νοστρθμ προπριαε',
|
|
58
|
-
),
|
|
59
|
-
])
|
|
60
|
-
|
|
61
|
-
const [japanesePostStatus, greekPostStatus] = await Promise.all([
|
|
62
|
-
getStatus(japanesePost.post.ref.uriStr),
|
|
63
|
-
getStatus(greekPost.post.ref.uriStr),
|
|
64
|
-
])
|
|
65
|
-
|
|
66
|
-
expect(japanesePostStatus.tags).toContain('lang:ja')
|
|
67
|
-
expect(greekPostStatus.tags).toContain('lang:el')
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
it('Uses name/description text for language tag for list', async () => {
|
|
71
|
-
const createListAndReport = async (
|
|
72
|
-
name: string,
|
|
73
|
-
description?: string,
|
|
74
|
-
) => {
|
|
75
|
-
const list = await sc.createList(sc.dids.carol, name, 'mod', {
|
|
76
|
-
description,
|
|
77
|
-
})
|
|
78
|
-
await network.processAll()
|
|
79
|
-
const report = await sc.createReport({
|
|
80
|
-
reasonType: REASONSPAM,
|
|
81
|
-
subject: {
|
|
82
|
-
$type: 'com.atproto.repo.strongRef',
|
|
83
|
-
uri: list.uriStr,
|
|
84
|
-
cid: list.cidStr,
|
|
85
|
-
},
|
|
86
|
-
reportedBy: sc.dids.alice,
|
|
87
|
-
})
|
|
88
|
-
return { list, report }
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const [listWithDescription, listWithoutDescription] = await Promise.all([
|
|
92
|
-
createListAndReport(
|
|
93
|
-
'よくない',
|
|
94
|
-
'Xで有名な人達+反AIや絵描きによくない感情を持つ人達+絵描き詐称',
|
|
95
|
-
),
|
|
96
|
-
createListAndReport('人達+反AIや絵描きによくない感情'),
|
|
97
|
-
])
|
|
98
|
-
|
|
99
|
-
const [japaneseListStatus, chineseListStatus] = await Promise.all([
|
|
100
|
-
getStatus(listWithDescription.list.uriStr),
|
|
101
|
-
getStatus(listWithoutDescription.list.uriStr),
|
|
102
|
-
])
|
|
103
|
-
|
|
104
|
-
expect(japaneseListStatus.tags).toContain('lang:ja')
|
|
105
|
-
expect(chineseListStatus.tags).toContain('lang:ja')
|
|
106
|
-
})
|
|
107
|
-
})
|
|
108
|
-
|
|
109
|
-
describe('embed tagger', () => {
|
|
110
|
-
it('Adds image tag to post with image', async () => {
|
|
111
|
-
const postWithImageMediaEmbed = sc.posts[sc.dids.carol][0]
|
|
112
|
-
const postWithImageEmbed = sc.replies[sc.dids.bob][0]
|
|
113
|
-
await Promise.all([
|
|
114
|
-
sc.createReport({
|
|
115
|
-
reasonType: REASONSPAM,
|
|
116
|
-
subject: {
|
|
117
|
-
$type: 'com.atproto.repo.strongRef',
|
|
118
|
-
uri: postWithImageMediaEmbed.ref.uriStr,
|
|
119
|
-
cid: postWithImageMediaEmbed.ref.cidStr,
|
|
120
|
-
},
|
|
121
|
-
reportedBy: sc.dids.alice,
|
|
122
|
-
}),
|
|
123
|
-
sc.createReport({
|
|
124
|
-
reasonType: REASONSPAM,
|
|
125
|
-
subject: {
|
|
126
|
-
$type: 'com.atproto.repo.strongRef',
|
|
127
|
-
uri: postWithImageEmbed.ref.uriStr,
|
|
128
|
-
cid: postWithImageEmbed.ref.cidStr,
|
|
129
|
-
},
|
|
130
|
-
reportedBy: sc.dids.alice,
|
|
131
|
-
}),
|
|
132
|
-
])
|
|
133
|
-
|
|
134
|
-
const [mediaImagePostStatus, imagePostStatus] = await Promise.all([
|
|
135
|
-
getStatus(postWithImageMediaEmbed.ref.uriStr),
|
|
136
|
-
getStatus(postWithImageEmbed.ref.uriStr),
|
|
137
|
-
])
|
|
138
|
-
expect(mediaImagePostStatus.tags).toContain('embed:image')
|
|
139
|
-
expect(imagePostStatus.tags).toContain('embed:image')
|
|
140
|
-
})
|
|
141
|
-
})
|
|
142
|
-
|
|
143
|
-
describe('report tagger', () => {
|
|
144
|
-
it('Adds report reason tag', async () => {
|
|
145
|
-
await Promise.all([
|
|
146
|
-
sc.createReport({
|
|
147
|
-
reasonType: REASONSPAM,
|
|
148
|
-
subject: {
|
|
149
|
-
$type: 'com.atproto.admin.defs#repoRef',
|
|
150
|
-
did: sc.dids.carol,
|
|
151
|
-
},
|
|
152
|
-
reportedBy: sc.dids.alice,
|
|
153
|
-
}),
|
|
154
|
-
sc.createReport({
|
|
155
|
-
reasonType: REASONMISLEADING,
|
|
156
|
-
subject: {
|
|
157
|
-
$type: 'com.atproto.admin.defs#repoRef',
|
|
158
|
-
did: sc.dids.carol,
|
|
159
|
-
},
|
|
160
|
-
reportedBy: sc.dids.alice,
|
|
161
|
-
}),
|
|
162
|
-
])
|
|
163
|
-
|
|
164
|
-
const accountStatus = await getStatus(sc.dids.carol)
|
|
165
|
-
|
|
166
|
-
expect(accountStatus.tags).toContain('report:spam')
|
|
167
|
-
expect(accountStatus.tags).toContain('report:misleading')
|
|
168
|
-
})
|
|
169
|
-
})
|
|
170
|
-
})
|
package/tests/db.test.ts
DELETED
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
import { sql } from 'kysely'
|
|
2
|
-
import { wait } from '@atproto/common'
|
|
3
|
-
import { TestNetwork } from '@atproto/dev-env'
|
|
4
|
-
import { Database } from '../src/index.js'
|
|
5
|
-
|
|
6
|
-
describe('db', () => {
|
|
7
|
-
let network: TestNetwork
|
|
8
|
-
let db: Database
|
|
9
|
-
|
|
10
|
-
beforeAll(async () => {
|
|
11
|
-
network = await TestNetwork.create({
|
|
12
|
-
dbPostgresSchema: 'ozone_db',
|
|
13
|
-
})
|
|
14
|
-
db = network.ozone.ctx.db
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
afterAll(async () => {
|
|
18
|
-
await network?.close()
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
it('handles client errors without crashing.', async () => {
|
|
22
|
-
const tryKillConnection = db.transaction(async (dbTxn) => {
|
|
23
|
-
const result = await sql`select pg_backend_pid() as pid;`.execute(
|
|
24
|
-
dbTxn.db,
|
|
25
|
-
)
|
|
26
|
-
const pid = result.rows[0]?.['pid'] as number
|
|
27
|
-
await sql`select pg_terminate_backend(${pid});`.execute(db.db)
|
|
28
|
-
await sql`select 1;`.execute(dbTxn.db)
|
|
29
|
-
})
|
|
30
|
-
// This should throw, but no unhandled error
|
|
31
|
-
await expect(tryKillConnection).rejects.toThrow()
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
it('handles pool errors without crashing.', async () => {
|
|
35
|
-
const conn1 = await db.pool.connect()
|
|
36
|
-
const conn2 = await db.pool.connect()
|
|
37
|
-
const result = await conn1.query('select pg_backend_pid() as pid;')
|
|
38
|
-
const conn1pid: number = result.rows[0].pid
|
|
39
|
-
conn1.release()
|
|
40
|
-
await wait(100) // let release apply, conn is now idle on pool.
|
|
41
|
-
await conn2.query(`select pg_terminate_backend(${conn1pid});`)
|
|
42
|
-
conn2.release()
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
describe('transaction()', () => {
|
|
46
|
-
it('commits changes', async () => {
|
|
47
|
-
const result = await db.transaction(async (dbTxn) => {
|
|
48
|
-
return await dbTxn.db
|
|
49
|
-
.insertInto('repo_push_event')
|
|
50
|
-
.values({
|
|
51
|
-
eventType: 'pds_takedown',
|
|
52
|
-
subjectDid: 'x',
|
|
53
|
-
})
|
|
54
|
-
.returning('subjectDid')
|
|
55
|
-
.executeTakeFirst()
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
if (!result) {
|
|
59
|
-
return expect(result).toBeTruthy()
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
expect(result.subjectDid).toEqual('x')
|
|
63
|
-
|
|
64
|
-
const row = await db.db
|
|
65
|
-
.selectFrom('repo_push_event')
|
|
66
|
-
.selectAll()
|
|
67
|
-
.where('subjectDid', '=', 'x')
|
|
68
|
-
.executeTakeFirst()
|
|
69
|
-
|
|
70
|
-
expect(row).toMatchObject({
|
|
71
|
-
eventType: 'pds_takedown',
|
|
72
|
-
subjectDid: 'x',
|
|
73
|
-
})
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
it('rolls-back changes on failure', async () => {
|
|
77
|
-
const promise = db.transaction(async (dbTxn) => {
|
|
78
|
-
await dbTxn.db
|
|
79
|
-
.insertInto('repo_push_event')
|
|
80
|
-
.values({
|
|
81
|
-
eventType: 'pds_takedown',
|
|
82
|
-
subjectDid: 'y',
|
|
83
|
-
})
|
|
84
|
-
.returning('subjectDid')
|
|
85
|
-
.executeTakeFirst()
|
|
86
|
-
|
|
87
|
-
throw new Error('Oops!')
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
await expect(promise).rejects.toThrow('Oops!')
|
|
91
|
-
|
|
92
|
-
const row = await db.db
|
|
93
|
-
.selectFrom('repo_push_event')
|
|
94
|
-
.selectAll()
|
|
95
|
-
.where('subjectDid', '=', 'y')
|
|
96
|
-
.executeTakeFirst()
|
|
97
|
-
|
|
98
|
-
expect(row).toBeUndefined()
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
it('indicates isTransaction', async () => {
|
|
102
|
-
expect(db.isTransaction).toEqual(false)
|
|
103
|
-
|
|
104
|
-
await db.transaction(async (dbTxn) => {
|
|
105
|
-
expect(db.isTransaction).toEqual(false)
|
|
106
|
-
expect(dbTxn.isTransaction).toEqual(true)
|
|
107
|
-
})
|
|
108
|
-
|
|
109
|
-
expect(db.isTransaction).toEqual(false)
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
it('asserts transaction', async () => {
|
|
113
|
-
expect(() => db.assertTransaction()).toThrow('Transaction required')
|
|
114
|
-
|
|
115
|
-
await db.transaction(async (dbTxn) => {
|
|
116
|
-
expect(() => dbTxn.assertTransaction()).not.toThrow()
|
|
117
|
-
})
|
|
118
|
-
})
|
|
119
|
-
|
|
120
|
-
it('does not allow leaky transactions', async () => {
|
|
121
|
-
let leakedTx: Database | undefined
|
|
122
|
-
|
|
123
|
-
const tx = db.transaction(async (dbTxn) => {
|
|
124
|
-
leakedTx = dbTxn
|
|
125
|
-
await dbTxn.db
|
|
126
|
-
.insertInto('repo_push_event')
|
|
127
|
-
.values({ eventType: 'pds_takedown', subjectDid: 'a' })
|
|
128
|
-
.execute()
|
|
129
|
-
throw new Error('test tx failed')
|
|
130
|
-
})
|
|
131
|
-
await expect(tx).rejects.toThrow('test tx failed')
|
|
132
|
-
|
|
133
|
-
const attempt = leakedTx?.db
|
|
134
|
-
.insertInto('repo_push_event')
|
|
135
|
-
.values({ eventType: 'pds_takedown', subjectDid: 'b' })
|
|
136
|
-
.execute()
|
|
137
|
-
await expect(attempt).rejects.toThrow('tx already failed')
|
|
138
|
-
|
|
139
|
-
const res = await db.db
|
|
140
|
-
.selectFrom('repo_push_event')
|
|
141
|
-
.selectAll()
|
|
142
|
-
.where('subjectDid', 'in', ['a', 'b'])
|
|
143
|
-
.execute()
|
|
144
|
-
|
|
145
|
-
expect(res.length).toBe(0)
|
|
146
|
-
})
|
|
147
|
-
|
|
148
|
-
it('ensures all inflight queries are rolled back', async () => {
|
|
149
|
-
let promise: Promise<unknown> | undefined = undefined
|
|
150
|
-
const names: string[] = []
|
|
151
|
-
try {
|
|
152
|
-
await db.transaction(async (dbTxn) => {
|
|
153
|
-
const queries: Promise<unknown>[] = []
|
|
154
|
-
for (let i = 0; i < 20; i++) {
|
|
155
|
-
const name = `user${i}`
|
|
156
|
-
const query = dbTxn.db
|
|
157
|
-
.insertInto('repo_push_event')
|
|
158
|
-
.values({
|
|
159
|
-
eventType: 'pds_takedown',
|
|
160
|
-
subjectDid: name,
|
|
161
|
-
})
|
|
162
|
-
.execute()
|
|
163
|
-
names.push(name)
|
|
164
|
-
queries.push(query)
|
|
165
|
-
}
|
|
166
|
-
promise = Promise.allSettled(queries)
|
|
167
|
-
throw new Error()
|
|
168
|
-
})
|
|
169
|
-
} catch (err) {
|
|
170
|
-
expect(err).toBeDefined()
|
|
171
|
-
}
|
|
172
|
-
if (promise) {
|
|
173
|
-
await promise
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
const res = await db.db
|
|
177
|
-
.selectFrom('repo_push_event')
|
|
178
|
-
.selectAll()
|
|
179
|
-
.where('subjectDid', 'in', names)
|
|
180
|
-
.execute()
|
|
181
|
-
expect(res.length).toBe(0)
|
|
182
|
-
})
|
|
183
|
-
})
|
|
184
|
-
})
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import AtpAgent from '@atproto/api'
|
|
2
|
-
import {
|
|
3
|
-
ModeratorClient,
|
|
4
|
-
SeedClient,
|
|
5
|
-
TestNetwork,
|
|
6
|
-
basicSeed,
|
|
7
|
-
} from '@atproto/dev-env'
|
|
8
|
-
import { ids } from '../src/lexicon/lexicons.js'
|
|
9
|
-
|
|
10
|
-
describe('expiring label', () => {
|
|
11
|
-
let network: TestNetwork
|
|
12
|
-
let sc: SeedClient
|
|
13
|
-
let modClient: ModeratorClient
|
|
14
|
-
let agent: AtpAgent
|
|
15
|
-
|
|
16
|
-
beforeAll(async () => {
|
|
17
|
-
network = await TestNetwork.create({
|
|
18
|
-
dbPostgresSchema: 'ozone_expiring_label_test',
|
|
19
|
-
})
|
|
20
|
-
sc = network.getSeedClient()
|
|
21
|
-
agent = network.ozone.getAgent()
|
|
22
|
-
modClient = network.ozone.getModClient()
|
|
23
|
-
await basicSeed(sc)
|
|
24
|
-
await network.processAll()
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
afterAll(async () => {
|
|
28
|
-
await network?.close()
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
const emitExpiringLabel = async (did: string) =>
|
|
32
|
-
modClient.emitEvent(
|
|
33
|
-
{
|
|
34
|
-
subject: { $type: 'com.atproto.admin.defs#repoRef', did },
|
|
35
|
-
event: {
|
|
36
|
-
$type: 'tools.ozone.moderation.defs#modEventLabel',
|
|
37
|
-
comment: 'Testing expiring label',
|
|
38
|
-
createLabelVals: ['expiring'],
|
|
39
|
-
negateLabelVals: [],
|
|
40
|
-
durationInHours: 1,
|
|
41
|
-
},
|
|
42
|
-
createdBy: sc.dids.alice,
|
|
43
|
-
},
|
|
44
|
-
'moderator',
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
it('Returns expiring label only within expiration period', async () => {
|
|
48
|
-
const getRepo = async (did: string) =>
|
|
49
|
-
agent.tools.ozone.moderation.getRepo(
|
|
50
|
-
{ did },
|
|
51
|
-
{
|
|
52
|
-
headers: await network.ozone.modHeaders(
|
|
53
|
-
ids.ToolsOzoneModerationGetRepo,
|
|
54
|
-
),
|
|
55
|
-
},
|
|
56
|
-
)
|
|
57
|
-
|
|
58
|
-
const now = new Date().toISOString()
|
|
59
|
-
await emitExpiringLabel(sc.dids.carol)
|
|
60
|
-
const { data: repoWithExpiringLabel } = await getRepo(sc.dids.carol)
|
|
61
|
-
expect(repoWithExpiringLabel.labels?.[0].val).toEqual('expiring')
|
|
62
|
-
// Manually expire the label in db
|
|
63
|
-
await network.ozone.ctx.db.db
|
|
64
|
-
.updateTable('label')
|
|
65
|
-
.set({ exp: now })
|
|
66
|
-
.where('uri', '=', sc.dids.carol)
|
|
67
|
-
.execute()
|
|
68
|
-
|
|
69
|
-
const { data: repoAfterExpiringLabel } = await getRepo(sc.dids.carol)
|
|
70
|
-
expect(repoAfterExpiringLabel.labels?.length).toEqual(0)
|
|
71
|
-
})
|
|
72
|
-
})
|
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ModeratorClient,
|
|
3
|
-
SeedClient,
|
|
4
|
-
TestNetwork,
|
|
5
|
-
basicSeed,
|
|
6
|
-
} from '@atproto/dev-env'
|
|
7
|
-
import { EventReverser } from '../src/daemon/event-reverser.js'
|
|
8
|
-
import { REASONSPAM } from '../src/lexicon/types/com/atproto/moderation/defs.js'
|
|
9
|
-
|
|
10
|
-
describe('expiring tags', () => {
|
|
11
|
-
let network: TestNetwork
|
|
12
|
-
let sc: SeedClient
|
|
13
|
-
let modClient: ModeratorClient
|
|
14
|
-
|
|
15
|
-
beforeAll(async () => {
|
|
16
|
-
network = await TestNetwork.create({
|
|
17
|
-
dbPostgresSchema: 'ozone_expiring_tags',
|
|
18
|
-
})
|
|
19
|
-
sc = network.getSeedClient()
|
|
20
|
-
modClient = network.ozone.getModClient()
|
|
21
|
-
await basicSeed(sc)
|
|
22
|
-
await network.processAll()
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
afterAll(async () => {
|
|
26
|
-
await network?.close()
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
const emitTagEvent = (
|
|
30
|
-
did: string,
|
|
31
|
-
add: string[],
|
|
32
|
-
remove: string[],
|
|
33
|
-
durationInHours?: number,
|
|
34
|
-
) =>
|
|
35
|
-
modClient.emitEvent({
|
|
36
|
-
subject: { $type: 'com.atproto.admin.defs#repoRef', did },
|
|
37
|
-
event: {
|
|
38
|
-
$type: 'tools.ozone.moderation.defs#modEventTag',
|
|
39
|
-
add,
|
|
40
|
-
remove,
|
|
41
|
-
...(durationInHours !== undefined ? { durationInHours } : {}),
|
|
42
|
-
},
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
const getSubjectTags = async (did: string): Promise<string[]> => {
|
|
46
|
-
const result = await modClient.queryStatuses({ subject: did })
|
|
47
|
-
return result.subjectStatuses[0]?.tags ?? []
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const createReverser = () =>
|
|
51
|
-
new EventReverser(
|
|
52
|
-
network.ozone.ctx.db,
|
|
53
|
-
// @ts-expect-error Error due to circular dependency with the dev-env package
|
|
54
|
-
network.ozone.ctx.modService,
|
|
55
|
-
)
|
|
56
|
-
|
|
57
|
-
it('creates expiring_tag rows when durationInHours is set', async () => {
|
|
58
|
-
// Create a report so the subject exists in moderation_subject_status
|
|
59
|
-
await sc.createReport({
|
|
60
|
-
reasonType: REASONSPAM,
|
|
61
|
-
reason: 'test',
|
|
62
|
-
subject: { $type: 'com.atproto.admin.defs#repoRef', did: sc.dids.bob },
|
|
63
|
-
reportedBy: sc.dids.alice,
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
await emitTagEvent(sc.dids.bob, ['temp-tag-1', 'temp-tag-2'], [], 1)
|
|
67
|
-
|
|
68
|
-
const tags = await getSubjectTags(sc.dids.bob)
|
|
69
|
-
expect(tags).toContain('temp-tag-1')
|
|
70
|
-
expect(tags).toContain('temp-tag-2')
|
|
71
|
-
|
|
72
|
-
// Verify expiring_tag rows were created
|
|
73
|
-
const expiringRows = await network.ozone.ctx.db.db
|
|
74
|
-
.selectFrom('expiring_tag')
|
|
75
|
-
.where('did', '=', sc.dids.bob)
|
|
76
|
-
.selectAll()
|
|
77
|
-
.execute()
|
|
78
|
-
|
|
79
|
-
expect(expiringRows).toHaveLength(2)
|
|
80
|
-
expect(expiringRows.map((r) => r.tag).sort()).toEqual([
|
|
81
|
-
'temp-tag-1',
|
|
82
|
-
'temp-tag-2',
|
|
83
|
-
])
|
|
84
|
-
expect(expiringRows[0].expiresAt).toBeTruthy()
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
it('does not create expiring_tag rows without durationInHours', async () => {
|
|
88
|
-
await emitTagEvent(sc.dids.bob, ['permanent-tag'], [])
|
|
89
|
-
|
|
90
|
-
const tags = await getSubjectTags(sc.dids.bob)
|
|
91
|
-
expect(tags).toContain('permanent-tag')
|
|
92
|
-
|
|
93
|
-
const expiringRows = await network.ozone.ctx.db.db
|
|
94
|
-
.selectFrom('expiring_tag')
|
|
95
|
-
.where('did', '=', sc.dids.bob)
|
|
96
|
-
.where('tag', '=', 'permanent-tag')
|
|
97
|
-
.selectAll()
|
|
98
|
-
.execute()
|
|
99
|
-
|
|
100
|
-
expect(expiringRows).toHaveLength(0)
|
|
101
|
-
})
|
|
102
|
-
|
|
103
|
-
it('daemon reverts expired tags', async () => {
|
|
104
|
-
// Manually expire the tags in the DB
|
|
105
|
-
await network.ozone.ctx.db.db
|
|
106
|
-
.updateTable('expiring_tag')
|
|
107
|
-
.set({ expiresAt: new Date(Date.now() - 1000).toISOString() })
|
|
108
|
-
.where('did', '=', sc.dids.bob)
|
|
109
|
-
.execute()
|
|
110
|
-
|
|
111
|
-
const reverser = createReverser()
|
|
112
|
-
await reverser.findAndRevertDueActions()
|
|
113
|
-
|
|
114
|
-
const tags = await getSubjectTags(sc.dids.bob)
|
|
115
|
-
expect(tags).not.toContain('temp-tag-1')
|
|
116
|
-
expect(tags).not.toContain('temp-tag-2')
|
|
117
|
-
// Permanent tag should still be there
|
|
118
|
-
expect(tags).toContain('permanent-tag')
|
|
119
|
-
|
|
120
|
-
// Verify expiring_tag rows are cleaned up
|
|
121
|
-
const remainingRows = await network.ozone.ctx.db.db
|
|
122
|
-
.selectFrom('expiring_tag')
|
|
123
|
-
.where('did', '=', sc.dids.bob)
|
|
124
|
-
.selectAll()
|
|
125
|
-
.execute()
|
|
126
|
-
|
|
127
|
-
expect(remainingRows).toHaveLength(0)
|
|
128
|
-
})
|
|
129
|
-
|
|
130
|
-
it('daemon emits a modEventTag removal event', async () => {
|
|
131
|
-
const events = await modClient.queryEvents({
|
|
132
|
-
subject: sc.dids.bob,
|
|
133
|
-
types: ['tools.ozone.moderation.defs#modEventTag'],
|
|
134
|
-
})
|
|
135
|
-
|
|
136
|
-
const lastTagEvent = events.events[0]
|
|
137
|
-
expect(lastTagEvent.event).toMatchObject({
|
|
138
|
-
$type: 'tools.ozone.moderation.defs#modEventTag',
|
|
139
|
-
add: [],
|
|
140
|
-
remove: expect.arrayContaining(['temp-tag-1', 'temp-tag-2']),
|
|
141
|
-
comment:
|
|
142
|
-
'[SCHEDULED_REVERSAL] Reverting temporary tags as originally scheduled',
|
|
143
|
-
})
|
|
144
|
-
})
|
|
145
|
-
|
|
146
|
-
it('cleans up expiring_tag rows when tags are manually removed', async () => {
|
|
147
|
-
await sc.createReport({
|
|
148
|
-
reasonType: REASONSPAM,
|
|
149
|
-
reason: 'test',
|
|
150
|
-
subject: {
|
|
151
|
-
$type: 'com.atproto.admin.defs#repoRef',
|
|
152
|
-
did: sc.dids.carol,
|
|
153
|
-
},
|
|
154
|
-
reportedBy: sc.dids.alice,
|
|
155
|
-
})
|
|
156
|
-
|
|
157
|
-
await emitTagEvent(sc.dids.carol, ['auto-remove-tag'], [], 24)
|
|
158
|
-
|
|
159
|
-
// Verify the expiring_tag row exists
|
|
160
|
-
let expiringRows = await network.ozone.ctx.db.db
|
|
161
|
-
.selectFrom('expiring_tag')
|
|
162
|
-
.where('did', '=', sc.dids.carol)
|
|
163
|
-
.where('tag', '=', 'auto-remove-tag')
|
|
164
|
-
.selectAll()
|
|
165
|
-
.execute()
|
|
166
|
-
expect(expiringRows).toHaveLength(1)
|
|
167
|
-
|
|
168
|
-
// Manually remove the tag
|
|
169
|
-
await emitTagEvent(sc.dids.carol, [], ['auto-remove-tag'])
|
|
170
|
-
|
|
171
|
-
// Verify the expiring_tag row is cleaned up
|
|
172
|
-
expiringRows = await network.ozone.ctx.db.db
|
|
173
|
-
.selectFrom('expiring_tag')
|
|
174
|
-
.where('did', '=', sc.dids.carol)
|
|
175
|
-
.where('tag', '=', 'auto-remove-tag')
|
|
176
|
-
.selectAll()
|
|
177
|
-
.execute()
|
|
178
|
-
expect(expiringRows).toHaveLength(0)
|
|
179
|
-
})
|
|
180
|
-
|
|
181
|
-
it('daemon skips tags already manually removed', async () => {
|
|
182
|
-
await emitTagEvent(sc.dids.carol, ['skip-tag'], [], 1)
|
|
183
|
-
|
|
184
|
-
// Manually remove the tag first
|
|
185
|
-
await emitTagEvent(sc.dids.carol, [], ['skip-tag'])
|
|
186
|
-
|
|
187
|
-
// Re-insert an expiring_tag row to simulate the race condition
|
|
188
|
-
// (row wasn't cleaned up for some reason)
|
|
189
|
-
await network.ozone.ctx.db.db
|
|
190
|
-
.insertInto('expiring_tag')
|
|
191
|
-
.values({
|
|
192
|
-
eventId: 0,
|
|
193
|
-
did: sc.dids.carol,
|
|
194
|
-
recordPath: '',
|
|
195
|
-
convoId: '',
|
|
196
|
-
tag: 'skip-tag',
|
|
197
|
-
expiresAt: new Date(Date.now() - 1000).toISOString(),
|
|
198
|
-
createdBy: sc.dids.alice,
|
|
199
|
-
})
|
|
200
|
-
.execute()
|
|
201
|
-
|
|
202
|
-
const tagsBefore = await getSubjectTags(sc.dids.carol)
|
|
203
|
-
expect(tagsBefore).not.toContain('skip-tag')
|
|
204
|
-
|
|
205
|
-
const reverser = createReverser()
|
|
206
|
-
await reverser.findAndRevertDueActions()
|
|
207
|
-
|
|
208
|
-
// Verify no removal event was emitted for a tag that's already gone
|
|
209
|
-
const events = await modClient.queryEvents({
|
|
210
|
-
subject: sc.dids.carol,
|
|
211
|
-
types: ['tools.ozone.moderation.defs#modEventTag'],
|
|
212
|
-
})
|
|
213
|
-
|
|
214
|
-
// The last tag event should be the manual removal, not a scheduled reversal
|
|
215
|
-
const lastEvent = events.events[0]
|
|
216
|
-
expect(lastEvent.event).toMatchObject({
|
|
217
|
-
$type: 'tools.ozone.moderation.defs#modEventTag',
|
|
218
|
-
remove: ['skip-tag'],
|
|
219
|
-
})
|
|
220
|
-
const comment = (lastEvent.event as { comment?: string }).comment ?? ''
|
|
221
|
-
expect(comment).not.toContain('SCHEDULED_REVERSAL')
|
|
222
|
-
|
|
223
|
-
// Verify the expiring_tag row is still cleaned up
|
|
224
|
-
const remainingRows = await network.ozone.ctx.db.db
|
|
225
|
-
.selectFrom('expiring_tag')
|
|
226
|
-
.where('did', '=', sc.dids.carol)
|
|
227
|
-
.where('tag', '=', 'skip-tag')
|
|
228
|
-
.selectAll()
|
|
229
|
-
.execute()
|
|
230
|
-
expect(remainingRows).toHaveLength(0)
|
|
231
|
-
})
|
|
232
|
-
})
|