@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
package/tests/safelink.test.ts
DELETED
|
@@ -1,534 +0,0 @@
|
|
|
1
|
-
import { AtpAgent } from '@atproto/api'
|
|
2
|
-
import { SeedClient, TestNetwork, basicSeed } from '@atproto/dev-env'
|
|
3
|
-
import { ids } from '../src/lexicon/lexicons.js'
|
|
4
|
-
import { forSnapshot } from './_util.js'
|
|
5
|
-
|
|
6
|
-
describe('safelink management', () => {
|
|
7
|
-
let network: TestNetwork
|
|
8
|
-
let adminAgent: AtpAgent
|
|
9
|
-
let modAgent: AtpAgent
|
|
10
|
-
let triageAgent: AtpAgent
|
|
11
|
-
let sc: SeedClient
|
|
12
|
-
|
|
13
|
-
const getAdminHeaders = async (route: string) => {
|
|
14
|
-
return {
|
|
15
|
-
headers: await network.ozone.modHeaders(route, 'admin'),
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
beforeAll(async () => {
|
|
20
|
-
network = await TestNetwork.create({
|
|
21
|
-
dbPostgresSchema: 'ozone_safelink_test',
|
|
22
|
-
})
|
|
23
|
-
adminAgent = network.ozone.getAgent()
|
|
24
|
-
modAgent = network.ozone.getAgent()
|
|
25
|
-
triageAgent = network.ozone.getAgent()
|
|
26
|
-
sc = network.getSeedClient()
|
|
27
|
-
await basicSeed(sc)
|
|
28
|
-
await network.processAll()
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
afterAll(async () => {
|
|
32
|
-
await network?.close()
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
describe('addRule', () => {
|
|
36
|
-
const testRule = {
|
|
37
|
-
url: 'https://malicious-site.com',
|
|
38
|
-
pattern: 'domain',
|
|
39
|
-
action: 'block',
|
|
40
|
-
reason: 'phishing',
|
|
41
|
-
comment: 'Known phishing domain targeting users',
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
it('allows admins to add rules', async () => {
|
|
45
|
-
const { data: adminRule } = await adminAgent.tools.ozone.safelink.addRule(
|
|
46
|
-
testRule,
|
|
47
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkAddRule),
|
|
48
|
-
)
|
|
49
|
-
expect(forSnapshot(adminRule)).toMatchSnapshot()
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
it('rejects triage role from adding rules', async () => {
|
|
53
|
-
await expect(
|
|
54
|
-
triageAgent.tools.ozone.safelink.addRule(testRule, {
|
|
55
|
-
headers: await network.ozone.modHeaders(
|
|
56
|
-
ids.ToolsOzoneSafelinkAddRule,
|
|
57
|
-
'triage',
|
|
58
|
-
),
|
|
59
|
-
}),
|
|
60
|
-
).rejects.toThrow('Must be a moderator to add URL rules')
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
it('prevents duplicate rules for same URL/pattern combination', async () => {
|
|
64
|
-
await expect(
|
|
65
|
-
adminAgent.tools.ozone.safelink.addRule(
|
|
66
|
-
testRule,
|
|
67
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkAddRule),
|
|
68
|
-
),
|
|
69
|
-
).rejects.toThrow('A rule for this URL/domain already exists')
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
it('validates invalid pattern types', async () => {
|
|
73
|
-
await expect(
|
|
74
|
-
adminAgent.tools.ozone.safelink.addRule(
|
|
75
|
-
{
|
|
76
|
-
...testRule,
|
|
77
|
-
url: 'https://new-site.com',
|
|
78
|
-
pattern: 'invalid-pattern',
|
|
79
|
-
},
|
|
80
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkAddRule),
|
|
81
|
-
),
|
|
82
|
-
).rejects.toThrow('Invalid safelink pattern type')
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
it('validates invalid action types', async () => {
|
|
86
|
-
await expect(
|
|
87
|
-
adminAgent.tools.ozone.safelink.addRule(
|
|
88
|
-
{
|
|
89
|
-
...testRule,
|
|
90
|
-
url: 'https://new-site2.com',
|
|
91
|
-
action: 'invalid-action',
|
|
92
|
-
},
|
|
93
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkAddRule),
|
|
94
|
-
),
|
|
95
|
-
).rejects.toThrow('Invalid safelink action type')
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
it('validates invalid reason types', async () => {
|
|
99
|
-
await expect(
|
|
100
|
-
adminAgent.tools.ozone.safelink.addRule(
|
|
101
|
-
{
|
|
102
|
-
...testRule,
|
|
103
|
-
url: 'https://new-site3.com',
|
|
104
|
-
reason: 'invalid-reason',
|
|
105
|
-
},
|
|
106
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkAddRule),
|
|
107
|
-
),
|
|
108
|
-
).rejects.toThrow('Invalid safelink reason type')
|
|
109
|
-
})
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
describe('updateRule', () => {
|
|
113
|
-
const updateTestRule = {
|
|
114
|
-
url: 'https://update-test.com',
|
|
115
|
-
pattern: 'domain',
|
|
116
|
-
action: 'warn',
|
|
117
|
-
reason: 'spam',
|
|
118
|
-
comment: 'Initially marked as spam',
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
beforeAll(async () => {
|
|
122
|
-
await adminAgent.tools.ozone.safelink.addRule(
|
|
123
|
-
updateTestRule,
|
|
124
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkAddRule),
|
|
125
|
-
)
|
|
126
|
-
})
|
|
127
|
-
|
|
128
|
-
it('allows updating existing rules', async () => {
|
|
129
|
-
const updatedData = {
|
|
130
|
-
url: updateTestRule.url,
|
|
131
|
-
pattern: updateTestRule.pattern,
|
|
132
|
-
action: 'block',
|
|
133
|
-
reason: 'phishing',
|
|
134
|
-
comment: 'Updated: confirmed phishing site',
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const { data: updated } = await modAgent.tools.ozone.safelink.updateRule(
|
|
138
|
-
updatedData,
|
|
139
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkUpdateRule),
|
|
140
|
-
)
|
|
141
|
-
const { data: queried } = await modAgent.tools.ozone.safelink.queryRules(
|
|
142
|
-
{ urls: [updateTestRule.url] },
|
|
143
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkQueryRules),
|
|
144
|
-
)
|
|
145
|
-
expect(updated).toMatchObject(updatedData)
|
|
146
|
-
expect(queried.rules[0]).toMatchObject(updatedData)
|
|
147
|
-
})
|
|
148
|
-
|
|
149
|
-
it('rejects triage role from updating rules', async () => {
|
|
150
|
-
await expect(
|
|
151
|
-
triageAgent.tools.ozone.safelink.updateRule(updateTestRule, {
|
|
152
|
-
headers: await network.ozone.modHeaders(
|
|
153
|
-
ids.ToolsOzoneSafelinkUpdateRule,
|
|
154
|
-
'triage',
|
|
155
|
-
),
|
|
156
|
-
}),
|
|
157
|
-
).rejects.toThrow('Must be a moderator to update URL rules')
|
|
158
|
-
})
|
|
159
|
-
|
|
160
|
-
it('throws error when updating non-existent rule', async () => {
|
|
161
|
-
await expect(
|
|
162
|
-
adminAgent.tools.ozone.safelink.updateRule(
|
|
163
|
-
{
|
|
164
|
-
...updateTestRule,
|
|
165
|
-
url: 'https://non-existent.com',
|
|
166
|
-
},
|
|
167
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkUpdateRule),
|
|
168
|
-
),
|
|
169
|
-
).rejects.toThrow('No active rule found for this URL/domain')
|
|
170
|
-
})
|
|
171
|
-
})
|
|
172
|
-
|
|
173
|
-
describe('removeRule', () => {
|
|
174
|
-
const removeTestRule = {
|
|
175
|
-
url: 'https://remove-test.com',
|
|
176
|
-
pattern: 'url',
|
|
177
|
-
action: 'block',
|
|
178
|
-
reason: 'csam',
|
|
179
|
-
comment: 'Rule to be removed',
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
beforeAll(async () => {
|
|
183
|
-
await adminAgent.tools.ozone.safelink.addRule(
|
|
184
|
-
removeTestRule,
|
|
185
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkAddRule),
|
|
186
|
-
)
|
|
187
|
-
})
|
|
188
|
-
|
|
189
|
-
it('allows admins and moderators to remove existing rules', async () => {
|
|
190
|
-
const { data: removed } =
|
|
191
|
-
await adminAgent.tools.ozone.safelink.removeRule(
|
|
192
|
-
{
|
|
193
|
-
url: removeTestRule.url,
|
|
194
|
-
pattern: removeTestRule.pattern,
|
|
195
|
-
comment: 'Removing rule - false positive',
|
|
196
|
-
},
|
|
197
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkRemoveRule),
|
|
198
|
-
)
|
|
199
|
-
|
|
200
|
-
expect(removed.eventType).toEqual('removeRule')
|
|
201
|
-
expect(removed.url).toEqual(removeTestRule.url)
|
|
202
|
-
expect(removed.comment).toEqual('Removing rule - false positive')
|
|
203
|
-
})
|
|
204
|
-
|
|
205
|
-
it('rejects non-moderators from removing rules', async () => {
|
|
206
|
-
await adminAgent.tools.ozone.safelink.addRule(
|
|
207
|
-
{
|
|
208
|
-
url: 'https://remove-test2.com',
|
|
209
|
-
pattern: 'domain',
|
|
210
|
-
action: 'block',
|
|
211
|
-
reason: 'spam',
|
|
212
|
-
},
|
|
213
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkAddRule),
|
|
214
|
-
)
|
|
215
|
-
|
|
216
|
-
await expect(
|
|
217
|
-
triageAgent.tools.ozone.safelink.removeRule(
|
|
218
|
-
{
|
|
219
|
-
url: 'https://remove-test2.com',
|
|
220
|
-
pattern: 'domain',
|
|
221
|
-
},
|
|
222
|
-
{
|
|
223
|
-
headers: await network.ozone.modHeaders(
|
|
224
|
-
ids.ToolsOzoneSafelinkRemoveRule,
|
|
225
|
-
'triage',
|
|
226
|
-
),
|
|
227
|
-
},
|
|
228
|
-
),
|
|
229
|
-
).rejects.toThrow('Must be a moderator to remove URL rules')
|
|
230
|
-
})
|
|
231
|
-
|
|
232
|
-
it('throws error when removing non-existent rule', async () => {
|
|
233
|
-
await expect(
|
|
234
|
-
adminAgent.tools.ozone.safelink.removeRule(
|
|
235
|
-
{
|
|
236
|
-
url: 'https://never-existed.com',
|
|
237
|
-
pattern: 'domain',
|
|
238
|
-
},
|
|
239
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkRemoveRule),
|
|
240
|
-
),
|
|
241
|
-
).rejects.toThrow('No active rule found for this URL/domain')
|
|
242
|
-
})
|
|
243
|
-
})
|
|
244
|
-
|
|
245
|
-
describe('queryRules', () => {
|
|
246
|
-
beforeAll(async () => {
|
|
247
|
-
await adminAgent.tools.ozone.safelink.addRule(
|
|
248
|
-
{
|
|
249
|
-
url: 'https://query-test1.com',
|
|
250
|
-
pattern: 'domain',
|
|
251
|
-
action: 'block',
|
|
252
|
-
reason: 'phishing',
|
|
253
|
-
},
|
|
254
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkAddRule),
|
|
255
|
-
)
|
|
256
|
-
await adminAgent.tools.ozone.safelink.addRule(
|
|
257
|
-
{
|
|
258
|
-
url: 'https://query-test2.com/specific-path',
|
|
259
|
-
pattern: 'url',
|
|
260
|
-
action: 'warn',
|
|
261
|
-
reason: 'spam',
|
|
262
|
-
},
|
|
263
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkAddRule),
|
|
264
|
-
)
|
|
265
|
-
})
|
|
266
|
-
|
|
267
|
-
it('allows querying all active rules', async () => {
|
|
268
|
-
const { data: result } = await modAgent.tools.ozone.safelink.queryRules(
|
|
269
|
-
{},
|
|
270
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkQueryRules),
|
|
271
|
-
)
|
|
272
|
-
|
|
273
|
-
expect(result.rules.length).toBeGreaterThan(0)
|
|
274
|
-
expect(forSnapshot(result.rules)).toMatchSnapshot()
|
|
275
|
-
})
|
|
276
|
-
|
|
277
|
-
it('allows filtering rules by action', async () => {
|
|
278
|
-
const { data: blocked } =
|
|
279
|
-
await adminAgent.tools.ozone.safelink.queryRules(
|
|
280
|
-
{
|
|
281
|
-
actions: ['block'],
|
|
282
|
-
},
|
|
283
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkQueryRules),
|
|
284
|
-
)
|
|
285
|
-
|
|
286
|
-
const { data: warned } = await adminAgent.tools.ozone.safelink.queryRules(
|
|
287
|
-
{
|
|
288
|
-
actions: ['warn'],
|
|
289
|
-
},
|
|
290
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkQueryRules),
|
|
291
|
-
)
|
|
292
|
-
|
|
293
|
-
expect(blocked.rules.every((rule) => rule.action === 'block')).toBe(true)
|
|
294
|
-
expect(warned.rules.every((rule) => rule.action === 'warn')).toBe(true)
|
|
295
|
-
})
|
|
296
|
-
|
|
297
|
-
it('allows filtering rules by reason', async () => {
|
|
298
|
-
const { data: phishing } =
|
|
299
|
-
await adminAgent.tools.ozone.safelink.queryRules(
|
|
300
|
-
{
|
|
301
|
-
reason: 'phishing',
|
|
302
|
-
},
|
|
303
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkQueryRules),
|
|
304
|
-
)
|
|
305
|
-
|
|
306
|
-
const { data: spam } = await adminAgent.tools.ozone.safelink.queryRules(
|
|
307
|
-
{
|
|
308
|
-
reason: 'spam',
|
|
309
|
-
},
|
|
310
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkQueryRules),
|
|
311
|
-
)
|
|
312
|
-
|
|
313
|
-
expect(phishing.rules.every((rule) => rule.reason === 'phishing')).toBe(
|
|
314
|
-
true,
|
|
315
|
-
)
|
|
316
|
-
expect(spam.rules.every((rule) => rule.reason === 'spam')).toBe(true)
|
|
317
|
-
})
|
|
318
|
-
|
|
319
|
-
it('allows searching by URL', async () => {
|
|
320
|
-
const { data: result } = await adminAgent.tools.ozone.safelink.queryRules(
|
|
321
|
-
{
|
|
322
|
-
urls: ['https://query-test1.com'],
|
|
323
|
-
},
|
|
324
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkQueryRules),
|
|
325
|
-
)
|
|
326
|
-
|
|
327
|
-
expect(result.rules.length).toEqual(1)
|
|
328
|
-
expect(result.rules[0]?.url).toEqual('https://query-test1.com')
|
|
329
|
-
})
|
|
330
|
-
|
|
331
|
-
it('supports pagination', async () => {
|
|
332
|
-
const headers = await getAdminHeaders(ids.ToolsOzoneSafelinkQueryRules)
|
|
333
|
-
const { data: page1 } = await adminAgent.tools.ozone.safelink.queryRules(
|
|
334
|
-
{ limit: 4 },
|
|
335
|
-
headers,
|
|
336
|
-
)
|
|
337
|
-
|
|
338
|
-
expect(page1.rules.length).toEqual(4)
|
|
339
|
-
|
|
340
|
-
const { data: page2 } = await adminAgent.tools.ozone.safelink.queryRules(
|
|
341
|
-
{
|
|
342
|
-
limit: 5,
|
|
343
|
-
cursor: page1.cursor,
|
|
344
|
-
},
|
|
345
|
-
headers,
|
|
346
|
-
)
|
|
347
|
-
|
|
348
|
-
expect(page2.rules.length).toEqual(1)
|
|
349
|
-
})
|
|
350
|
-
})
|
|
351
|
-
|
|
352
|
-
describe('queryEvents', () => {
|
|
353
|
-
beforeAll(async () => {
|
|
354
|
-
await adminAgent.tools.ozone.safelink.addRule(
|
|
355
|
-
{
|
|
356
|
-
url: 'https://events-test.com',
|
|
357
|
-
pattern: 'domain',
|
|
358
|
-
action: 'warn',
|
|
359
|
-
reason: 'spam',
|
|
360
|
-
comment: 'Initial rule creation',
|
|
361
|
-
},
|
|
362
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkAddRule),
|
|
363
|
-
)
|
|
364
|
-
await adminAgent.tools.ozone.safelink.updateRule(
|
|
365
|
-
{
|
|
366
|
-
url: 'https://events-test.com',
|
|
367
|
-
pattern: 'domain',
|
|
368
|
-
action: 'block',
|
|
369
|
-
reason: 'phishing',
|
|
370
|
-
comment: 'Escalated to block',
|
|
371
|
-
},
|
|
372
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkUpdateRule),
|
|
373
|
-
)
|
|
374
|
-
})
|
|
375
|
-
|
|
376
|
-
it('allows querying safelink events', async () => {
|
|
377
|
-
const { data: result } = await modAgent.tools.ozone.safelink.queryEvents(
|
|
378
|
-
{},
|
|
379
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkQueryEvents),
|
|
380
|
-
)
|
|
381
|
-
|
|
382
|
-
expect(result.events.length).toBeGreaterThan(0)
|
|
383
|
-
expect(forSnapshot(result.events)).toMatchSnapshot()
|
|
384
|
-
})
|
|
385
|
-
|
|
386
|
-
it('allows filtering events by URL', async () => {
|
|
387
|
-
const { data: result } =
|
|
388
|
-
await adminAgent.tools.ozone.safelink.queryEvents(
|
|
389
|
-
{
|
|
390
|
-
urls: ['https://events-test.com'],
|
|
391
|
-
},
|
|
392
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkQueryEvents),
|
|
393
|
-
)
|
|
394
|
-
|
|
395
|
-
expect(
|
|
396
|
-
result.events.every((event) => event.url === 'https://events-test.com'),
|
|
397
|
-
).toBe(true)
|
|
398
|
-
expect(result.events.length).toBeGreaterThanOrEqual(2)
|
|
399
|
-
})
|
|
400
|
-
|
|
401
|
-
it('supports pagination', async () => {
|
|
402
|
-
const headers = await getAdminHeaders(ids.ToolsOzoneSafelinkQueryEvents)
|
|
403
|
-
const { data: page1 } = await adminAgent.tools.ozone.safelink.queryEvents(
|
|
404
|
-
{
|
|
405
|
-
limit: 9,
|
|
406
|
-
},
|
|
407
|
-
headers,
|
|
408
|
-
)
|
|
409
|
-
|
|
410
|
-
const { data: page2 } = await adminAgent.tools.ozone.safelink.queryEvents(
|
|
411
|
-
{
|
|
412
|
-
limit: 10,
|
|
413
|
-
cursor: page1.cursor,
|
|
414
|
-
},
|
|
415
|
-
headers,
|
|
416
|
-
)
|
|
417
|
-
|
|
418
|
-
const { data: page3 } = await adminAgent.tools.ozone.safelink.queryEvents(
|
|
419
|
-
{
|
|
420
|
-
limit: 10,
|
|
421
|
-
cursor: page2.cursor,
|
|
422
|
-
},
|
|
423
|
-
headers,
|
|
424
|
-
)
|
|
425
|
-
|
|
426
|
-
expect(page1.events.length).toBeLessThanOrEqual(9)
|
|
427
|
-
expect(page2.events.length).toEqual(1)
|
|
428
|
-
expect(page3.cursor).toBeUndefined()
|
|
429
|
-
})
|
|
430
|
-
})
|
|
431
|
-
|
|
432
|
-
describe('event history over time', () => {
|
|
433
|
-
it('maintains audit trail through rule lifecycle', async () => {
|
|
434
|
-
const testUrl = 'https://lifecycle-test.com'
|
|
435
|
-
const pattern = 'domain'
|
|
436
|
-
|
|
437
|
-
await adminAgent.tools.ozone.safelink.addRule(
|
|
438
|
-
{
|
|
439
|
-
url: testUrl,
|
|
440
|
-
pattern,
|
|
441
|
-
action: 'warn',
|
|
442
|
-
reason: 'spam',
|
|
443
|
-
comment: 'Initial warning',
|
|
444
|
-
},
|
|
445
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkAddRule),
|
|
446
|
-
)
|
|
447
|
-
|
|
448
|
-
await modAgent.tools.ozone.safelink.updateRule(
|
|
449
|
-
{
|
|
450
|
-
url: testUrl,
|
|
451
|
-
pattern,
|
|
452
|
-
action: 'block',
|
|
453
|
-
reason: 'phishing',
|
|
454
|
-
comment: 'Escalated to block',
|
|
455
|
-
},
|
|
456
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkUpdateRule),
|
|
457
|
-
)
|
|
458
|
-
|
|
459
|
-
await adminAgent.tools.ozone.safelink.removeRule(
|
|
460
|
-
{
|
|
461
|
-
url: testUrl,
|
|
462
|
-
pattern,
|
|
463
|
-
comment: 'False positive',
|
|
464
|
-
},
|
|
465
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkRemoveRule),
|
|
466
|
-
)
|
|
467
|
-
|
|
468
|
-
const { data: events } =
|
|
469
|
-
await adminAgent.tools.ozone.safelink.queryEvents(
|
|
470
|
-
{
|
|
471
|
-
urls: [testUrl],
|
|
472
|
-
},
|
|
473
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkQueryEvents),
|
|
474
|
-
)
|
|
475
|
-
|
|
476
|
-
expect(events.events.length).toEqual(3)
|
|
477
|
-
const eventTypes = events.events.map((e) => e.eventType).sort()
|
|
478
|
-
expect(eventTypes).toEqual(['addRule', 'updateRule', 'removeRule'].sort())
|
|
479
|
-
|
|
480
|
-
const { data: queryResult } =
|
|
481
|
-
await adminAgent.tools.ozone.safelink.queryRules(
|
|
482
|
-
{
|
|
483
|
-
urls: [testUrl],
|
|
484
|
-
},
|
|
485
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkQueryRules),
|
|
486
|
-
)
|
|
487
|
-
expect(queryResult.rules.length).toEqual(0)
|
|
488
|
-
})
|
|
489
|
-
|
|
490
|
-
it('handles domain vs URL pattern precedence correctly', async () => {
|
|
491
|
-
const domain = 'precedence-test.com'
|
|
492
|
-
const specificUrl = 'https://precedence-test.com/safe-page'
|
|
493
|
-
const headers = await getAdminHeaders(ids.ToolsOzoneSafelinkAddRule)
|
|
494
|
-
|
|
495
|
-
await adminAgent.tools.ozone.safelink.addRule(
|
|
496
|
-
{
|
|
497
|
-
url: domain,
|
|
498
|
-
pattern: 'domain',
|
|
499
|
-
action: 'block',
|
|
500
|
-
reason: 'phishing',
|
|
501
|
-
},
|
|
502
|
-
headers,
|
|
503
|
-
)
|
|
504
|
-
|
|
505
|
-
await adminAgent.tools.ozone.safelink.addRule(
|
|
506
|
-
{
|
|
507
|
-
url: specificUrl,
|
|
508
|
-
pattern: 'url',
|
|
509
|
-
action: 'whitelist',
|
|
510
|
-
reason: 'none',
|
|
511
|
-
},
|
|
512
|
-
headers,
|
|
513
|
-
)
|
|
514
|
-
|
|
515
|
-
const { data: specificResult } =
|
|
516
|
-
await adminAgent.tools.ozone.safelink.queryRules(
|
|
517
|
-
{
|
|
518
|
-
urls: [specificUrl],
|
|
519
|
-
},
|
|
520
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkQueryRules),
|
|
521
|
-
)
|
|
522
|
-
expect(specificResult.rules.length).toEqual(1)
|
|
523
|
-
expect(specificResult.rules[0]?.action).toEqual('whitelist')
|
|
524
|
-
|
|
525
|
-
const { data: domainResult } =
|
|
526
|
-
await adminAgent.tools.ozone.safelink.queryRules(
|
|
527
|
-
{ urls: [domain] },
|
|
528
|
-
await getAdminHeaders(ids.ToolsOzoneSafelinkQueryRules),
|
|
529
|
-
)
|
|
530
|
-
expect(domainResult.rules.length).toEqual(1)
|
|
531
|
-
expect(domainResult.rules[0]?.action).toEqual('block')
|
|
532
|
-
})
|
|
533
|
-
})
|
|
534
|
-
})
|