@atproto/ozone 0.2.9 → 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 +26 -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/src/auth-verifier.ts
DELETED
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
import express from 'express'
|
|
2
|
-
import * as ui8 from 'uint8arrays'
|
|
3
|
-
import { IdResolver } from '@atproto/identity'
|
|
4
|
-
import {
|
|
5
|
-
AuthRequiredError,
|
|
6
|
-
parseReqNsid,
|
|
7
|
-
verifyJwt,
|
|
8
|
-
} from '@atproto/xrpc-server'
|
|
9
|
-
import { TeamService } from './team/index.js'
|
|
10
|
-
|
|
11
|
-
type ReqCtx = {
|
|
12
|
-
req: express.Request
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export type AdminTokenOutput = {
|
|
16
|
-
credentials: {
|
|
17
|
-
type: 'admin_token'
|
|
18
|
-
isAdmin: true
|
|
19
|
-
isModerator: true
|
|
20
|
-
isTriage: true
|
|
21
|
-
isVerifier: true
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export type ModeratorOutput = {
|
|
26
|
-
credentials: {
|
|
27
|
-
type: 'moderator'
|
|
28
|
-
aud: string
|
|
29
|
-
iss: string
|
|
30
|
-
isAdmin: boolean
|
|
31
|
-
isModerator: boolean
|
|
32
|
-
isTriage: boolean
|
|
33
|
-
isVerifier: boolean
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
type StandardOutput = {
|
|
38
|
-
credentials: {
|
|
39
|
-
type: 'standard'
|
|
40
|
-
aud: string
|
|
41
|
-
iss: string
|
|
42
|
-
isAdmin: boolean
|
|
43
|
-
isModerator: boolean
|
|
44
|
-
isTriage: boolean
|
|
45
|
-
isVerifier: boolean
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
type NullOutput = {
|
|
50
|
-
credentials: {
|
|
51
|
-
type: 'none'
|
|
52
|
-
iss: null
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export type AuthVerifierOpts = {
|
|
57
|
-
serviceDid: string
|
|
58
|
-
adminPassword: string
|
|
59
|
-
teamService: TeamService
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export class AuthVerifier {
|
|
63
|
-
serviceDid: string
|
|
64
|
-
teamService: TeamService
|
|
65
|
-
private adminPassword: string
|
|
66
|
-
|
|
67
|
-
constructor(
|
|
68
|
-
public idResolver: IdResolver,
|
|
69
|
-
opts: AuthVerifierOpts,
|
|
70
|
-
) {
|
|
71
|
-
this.serviceDid = opts.serviceDid
|
|
72
|
-
this.adminPassword = opts.adminPassword
|
|
73
|
-
this.teamService = opts.teamService
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
modOrAdminToken = async (
|
|
77
|
-
reqCtx: ReqCtx,
|
|
78
|
-
): Promise<ModeratorOutput | AdminTokenOutput> => {
|
|
79
|
-
if (isBasicToken(reqCtx.req)) {
|
|
80
|
-
return this.adminToken(reqCtx)
|
|
81
|
-
} else {
|
|
82
|
-
return this.moderator(reqCtx)
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
moderator = async (reqCtx: ReqCtx): Promise<ModeratorOutput> => {
|
|
87
|
-
const creds = await this.standard(reqCtx)
|
|
88
|
-
if (!creds.credentials.isTriage && !creds.credentials.isVerifier) {
|
|
89
|
-
throw new AuthRequiredError('not a moderator account')
|
|
90
|
-
}
|
|
91
|
-
return {
|
|
92
|
-
credentials: {
|
|
93
|
-
...creds.credentials,
|
|
94
|
-
type: 'moderator',
|
|
95
|
-
},
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
standard = async (reqCtx: ReqCtx): Promise<StandardOutput> => {
|
|
100
|
-
const getSigningKey = async (
|
|
101
|
-
did: string,
|
|
102
|
-
forceRefresh: boolean,
|
|
103
|
-
): Promise<string> => {
|
|
104
|
-
const atprotoData = await this.idResolver.did.resolveAtprotoData(
|
|
105
|
-
did,
|
|
106
|
-
forceRefresh,
|
|
107
|
-
)
|
|
108
|
-
return atprotoData.signingKey
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
const jwtStr = getJwtStrFromReq(reqCtx.req)
|
|
112
|
-
if (!jwtStr) {
|
|
113
|
-
throw new AuthRequiredError('missing jwt', 'MissingJwt')
|
|
114
|
-
}
|
|
115
|
-
const nsid = parseReqNsid(reqCtx.req)
|
|
116
|
-
const payload = await verifyJwt(
|
|
117
|
-
jwtStr,
|
|
118
|
-
this.serviceDid,
|
|
119
|
-
nsid,
|
|
120
|
-
getSigningKey,
|
|
121
|
-
)
|
|
122
|
-
const iss = payload.iss
|
|
123
|
-
|
|
124
|
-
const member = await this.teamService.getMember(iss)
|
|
125
|
-
|
|
126
|
-
if (member?.disabled) {
|
|
127
|
-
throw new AuthRequiredError('member is disabled', 'MemberDisabled')
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
const { isAdmin, isModerator, isTriage, isVerifier } =
|
|
131
|
-
this.teamService.getMemberRole(member)
|
|
132
|
-
|
|
133
|
-
return {
|
|
134
|
-
credentials: {
|
|
135
|
-
type: 'standard',
|
|
136
|
-
iss,
|
|
137
|
-
aud: payload.aud,
|
|
138
|
-
isAdmin,
|
|
139
|
-
isModerator,
|
|
140
|
-
isTriage,
|
|
141
|
-
isVerifier,
|
|
142
|
-
},
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
standardOptional = async (
|
|
147
|
-
reqCtx: ReqCtx,
|
|
148
|
-
): Promise<StandardOutput | NullOutput> => {
|
|
149
|
-
if (isBearerToken(reqCtx.req)) {
|
|
150
|
-
return this.standard(reqCtx)
|
|
151
|
-
}
|
|
152
|
-
return this.nullCreds()
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
standardOptionalOrAdminToken = async (
|
|
156
|
-
reqCtx: ReqCtx,
|
|
157
|
-
): Promise<StandardOutput | AdminTokenOutput | NullOutput> => {
|
|
158
|
-
if (isBearerToken(reqCtx.req)) {
|
|
159
|
-
return this.standard(reqCtx)
|
|
160
|
-
} else if (isBasicToken(reqCtx.req)) {
|
|
161
|
-
return this.adminToken(reqCtx)
|
|
162
|
-
} else {
|
|
163
|
-
return this.nullCreds()
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
adminToken = async (reqCtx: ReqCtx): Promise<AdminTokenOutput> => {
|
|
168
|
-
const parsed = parseBasicAuth(reqCtx.req.headers.authorization ?? '')
|
|
169
|
-
const { username, password } = parsed ?? {}
|
|
170
|
-
if (username !== 'admin' || password !== this.adminPassword) {
|
|
171
|
-
throw new AuthRequiredError()
|
|
172
|
-
}
|
|
173
|
-
return {
|
|
174
|
-
credentials: {
|
|
175
|
-
type: 'admin_token',
|
|
176
|
-
isAdmin: true,
|
|
177
|
-
isModerator: true,
|
|
178
|
-
isTriage: true,
|
|
179
|
-
isVerifier: true,
|
|
180
|
-
},
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
nullCreds(): NullOutput {
|
|
185
|
-
return {
|
|
186
|
-
credentials: {
|
|
187
|
-
type: 'none',
|
|
188
|
-
iss: null,
|
|
189
|
-
},
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
const BEARER = 'Bearer '
|
|
195
|
-
const BASIC = 'Basic '
|
|
196
|
-
|
|
197
|
-
const isBearerToken = (req: express.Request): boolean => {
|
|
198
|
-
return req.headers.authorization?.startsWith(BEARER) ?? false
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
const isBasicToken = (req: express.Request): boolean => {
|
|
202
|
-
return req.headers.authorization?.startsWith(BASIC) ?? false
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
export const getJwtStrFromReq = (req: express.Request): string | null => {
|
|
206
|
-
const { authorization } = req.headers
|
|
207
|
-
if (!authorization?.startsWith(BEARER)) {
|
|
208
|
-
return null
|
|
209
|
-
}
|
|
210
|
-
return authorization.slice(BEARER.length).trim()
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
export const parseBasicAuth = (
|
|
214
|
-
token: string,
|
|
215
|
-
): { username: string; password: string } | null => {
|
|
216
|
-
if (!token.startsWith(BASIC)) return null
|
|
217
|
-
const b64 = token.slice(BASIC.length)
|
|
218
|
-
let parsed: string[]
|
|
219
|
-
try {
|
|
220
|
-
parsed = ui8.toString(ui8.fromString(b64, 'base64pad'), 'utf8').split(':')
|
|
221
|
-
} catch (err) {
|
|
222
|
-
return null
|
|
223
|
-
}
|
|
224
|
-
const [username, password] = parsed
|
|
225
|
-
if (!username || !password) return null
|
|
226
|
-
return { username, password }
|
|
227
|
-
}
|
package/src/background.ts
DELETED
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
import PQueue from 'p-queue'
|
|
2
|
-
import { Database } from './db/index.js'
|
|
3
|
-
import { dbLogger } from './logger.js'
|
|
4
|
-
import {
|
|
5
|
-
boundAbortController,
|
|
6
|
-
isCausedBySignal,
|
|
7
|
-
startInterval,
|
|
8
|
-
} from './util.js'
|
|
9
|
-
|
|
10
|
-
type Task = (db: Database, signal: AbortSignal) => Promise<void>
|
|
11
|
-
|
|
12
|
-
export type BackgroundQueueOptions = NonNullable<
|
|
13
|
-
ConstructorParameters<typeof PQueue>[0]
|
|
14
|
-
> & {
|
|
15
|
-
concurrency: number
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* A simple queue for in-process, out-of-band/backgrounded work
|
|
20
|
-
*/
|
|
21
|
-
// @NOTE Keep this in sync with the BackgroundQueue in
|
|
22
|
-
// - packages/bsky/src/data-plane/server/background.ts
|
|
23
|
-
// - packages/ozone/src/background.ts
|
|
24
|
-
// - packages/pds/src/background.ts
|
|
25
|
-
export class BackgroundQueue {
|
|
26
|
-
private abortController = new AbortController()
|
|
27
|
-
private queue: PQueue
|
|
28
|
-
|
|
29
|
-
public get signal(): AbortSignal {
|
|
30
|
-
return this.abortController.signal
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
public get destroyed() {
|
|
34
|
-
return this.signal.aborted
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
constructor(
|
|
38
|
-
protected db: Database,
|
|
39
|
-
options: BackgroundQueueOptions,
|
|
40
|
-
) {
|
|
41
|
-
this.queue = new PQueue(options)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
getStats() {
|
|
45
|
-
return {
|
|
46
|
-
runningCount: this.queue.pending,
|
|
47
|
-
waitingCount: this.queue.size,
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Add a task that will be executed at some point in the future.
|
|
53
|
-
*
|
|
54
|
-
* The task will be executed even if the backgroundQueue is destroyed, unless
|
|
55
|
-
* the provided `signal` is aborted.
|
|
56
|
-
*
|
|
57
|
-
* The `signal` provided to the task will be aborted whenever either the
|
|
58
|
-
* backgroundQueue is destroyed or the provided `signal` is aborted.
|
|
59
|
-
*/
|
|
60
|
-
async add(task: Task, signal?: AbortSignal): Promise<void> {
|
|
61
|
-
if (this.destroyed) {
|
|
62
|
-
return
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const abortController = boundAbortController(this.signal, signal)
|
|
66
|
-
|
|
67
|
-
return this.queue.add<void>(async () => {
|
|
68
|
-
try {
|
|
69
|
-
// Do not run the task if the signal provided to the task has become
|
|
70
|
-
// aborted. Do not use `abortController.signal` here since we do not
|
|
71
|
-
// want to abort the task if the backgroundQueue is being destroyed.
|
|
72
|
-
if (signal?.aborted) return
|
|
73
|
-
|
|
74
|
-
// The task will receive a "combined signal" allowing it to abort if
|
|
75
|
-
// either the backgroundQueue is destroyed or the provided signal is
|
|
76
|
-
// aborted.
|
|
77
|
-
await task(this.db, abortController.signal)
|
|
78
|
-
} catch (err) {
|
|
79
|
-
if (!isCausedBySignal(err, abortController.signal)) {
|
|
80
|
-
dbLogger.error({ err }, 'background queue task failed')
|
|
81
|
-
}
|
|
82
|
-
} finally {
|
|
83
|
-
abortController.abort()
|
|
84
|
-
}
|
|
85
|
-
})
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
async processAll() {
|
|
89
|
-
const { queue } = this
|
|
90
|
-
while (queue.size || queue.pending) await queue.onIdle()
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* On destroy we stop accepting new tasks, but complete all
|
|
95
|
-
* pending/in-progress tasks. Tasks can decide to abort their current
|
|
96
|
-
* operation based on the signal they received. The application calls this
|
|
97
|
-
* only once http connections have drained (tasks no longer being added).
|
|
98
|
-
*/
|
|
99
|
-
async destroy() {
|
|
100
|
-
if (this.destroyed) {
|
|
101
|
-
dbLogger.warn('BackgroundQueue.destroy() called multiple times')
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
this.abortController.abort()
|
|
105
|
-
return this.processAll()
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* A simple periodic background task runner. This class will schedule a task to
|
|
111
|
-
* run through a provided {@link BackgroundQueue} at a fixed interval. The task
|
|
112
|
-
* will never run more than once concurrently, and will wait at least `interval`
|
|
113
|
-
* milliseconds between the end of one run and the start of the next.
|
|
114
|
-
*/
|
|
115
|
-
export class PeriodicBackgroundTask {
|
|
116
|
-
private abortController: AbortController
|
|
117
|
-
|
|
118
|
-
private intervalPromise?: Promise<void>
|
|
119
|
-
private runningPromise?: Promise<void>
|
|
120
|
-
|
|
121
|
-
public get signal(): AbortSignal {
|
|
122
|
-
return this.abortController.signal
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
public get destroyed() {
|
|
126
|
-
return this.signal.aborted
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
constructor(
|
|
130
|
-
protected backgroundQueue: BackgroundQueue,
|
|
131
|
-
protected interval: number,
|
|
132
|
-
protected task: Task,
|
|
133
|
-
) {
|
|
134
|
-
if (!Number.isFinite(interval) || interval <= 0) {
|
|
135
|
-
throw new TypeError('interval must be a positive number')
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// Bind this class's signal to the backgroundQueue's signal (destroying this
|
|
139
|
-
// instance if the backgroundQueue is destroyed)
|
|
140
|
-
this.abortController = boundAbortController(backgroundQueue.signal)
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
public run(signal?: AbortSignal): Promise<void> {
|
|
144
|
-
// `startInterval` already ensures that only one run is in progress at a
|
|
145
|
-
// time. However, we want to be able to expose a `run()` method that can be
|
|
146
|
-
// used to force a run, which could cause concurrent executions. We prevent
|
|
147
|
-
// this using the `runningPromise` property.
|
|
148
|
-
|
|
149
|
-
if (this.runningPromise) return this.runningPromise
|
|
150
|
-
|
|
151
|
-
// Combine the `this.signal` with the provided `signal`, if any.
|
|
152
|
-
const abortController = boundAbortController(this.signal, signal)
|
|
153
|
-
|
|
154
|
-
const promise = this.backgroundQueue.add(this.task, abortController.signal)
|
|
155
|
-
|
|
156
|
-
return (this.runningPromise = promise).finally(() => {
|
|
157
|
-
if (this.runningPromise === promise) this.runningPromise = undefined
|
|
158
|
-
|
|
159
|
-
// Cleanup the listeners added by `boundAbortController`
|
|
160
|
-
abortController.abort()
|
|
161
|
-
})
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
public start() {
|
|
165
|
-
// Noop if already started. Throws if this.signal is aborted (instance is
|
|
166
|
-
// destroyed).
|
|
167
|
-
this.intervalPromise ||= startInterval(
|
|
168
|
-
async (signal) => this.run(signal),
|
|
169
|
-
this.interval,
|
|
170
|
-
this.signal,
|
|
171
|
-
)
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
public async destroy() {
|
|
175
|
-
// @NOTE This instance does not "own" the backgroundQueue, so we do not
|
|
176
|
-
// destroy it here.
|
|
177
|
-
|
|
178
|
-
this.abortController.abort()
|
|
179
|
-
|
|
180
|
-
await this.intervalPromise
|
|
181
|
-
this.intervalPromise = undefined
|
|
182
|
-
}
|
|
183
|
-
}
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import { Selectable } from 'kysely'
|
|
2
|
-
import { Database } from '../db/index.js'
|
|
3
|
-
import { CommunicationTemplate } from '../db/schema/communication_template.js'
|
|
4
|
-
import { TemplateView } from '../lexicon/types/tools/ozone/communication/defs.js'
|
|
5
|
-
|
|
6
|
-
export type CommunicationTemplateServiceCreator = (
|
|
7
|
-
db: Database,
|
|
8
|
-
) => CommunicationTemplateService
|
|
9
|
-
|
|
10
|
-
export class CommunicationTemplateService {
|
|
11
|
-
constructor(public db: Database) {}
|
|
12
|
-
|
|
13
|
-
static creator() {
|
|
14
|
-
return (db: Database) => new CommunicationTemplateService(db)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
async list(): Promise<Selectable<CommunicationTemplate>[]> {
|
|
18
|
-
const list = await this.db.db
|
|
19
|
-
.selectFrom('communication_template')
|
|
20
|
-
.selectAll()
|
|
21
|
-
.execute()
|
|
22
|
-
|
|
23
|
-
return list
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
async create({
|
|
27
|
-
name,
|
|
28
|
-
contentMarkdown,
|
|
29
|
-
subject,
|
|
30
|
-
lang,
|
|
31
|
-
disabled,
|
|
32
|
-
updatedAt,
|
|
33
|
-
createdAt,
|
|
34
|
-
lastUpdatedBy,
|
|
35
|
-
}: Omit<
|
|
36
|
-
Selectable<CommunicationTemplate>,
|
|
37
|
-
'id' | 'createdAt' | 'updatedAt'
|
|
38
|
-
> & {
|
|
39
|
-
createdAt?: Date
|
|
40
|
-
updatedAt?: Date
|
|
41
|
-
}): Promise<Selectable<CommunicationTemplate>> {
|
|
42
|
-
const newTemplate = await this.db.db
|
|
43
|
-
.insertInto('communication_template')
|
|
44
|
-
.values({
|
|
45
|
-
name,
|
|
46
|
-
contentMarkdown,
|
|
47
|
-
subject,
|
|
48
|
-
lang,
|
|
49
|
-
disabled,
|
|
50
|
-
lastUpdatedBy,
|
|
51
|
-
updatedAt: updatedAt || new Date(),
|
|
52
|
-
createdAt: createdAt || new Date(),
|
|
53
|
-
})
|
|
54
|
-
.returningAll()
|
|
55
|
-
.executeTakeFirstOrThrow()
|
|
56
|
-
|
|
57
|
-
return newTemplate
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
async update(
|
|
61
|
-
id: number,
|
|
62
|
-
{
|
|
63
|
-
name,
|
|
64
|
-
contentMarkdown,
|
|
65
|
-
subject,
|
|
66
|
-
disabled,
|
|
67
|
-
lang,
|
|
68
|
-
updatedAt,
|
|
69
|
-
lastUpdatedBy,
|
|
70
|
-
}: Partial<Omit<Selectable<CommunicationTemplate>, 'id' | 'createdAt'>>,
|
|
71
|
-
): Promise<Selectable<CommunicationTemplate>> {
|
|
72
|
-
const updatedTemplate = await this.db.db
|
|
73
|
-
.updateTable('communication_template')
|
|
74
|
-
.where('id', '=', id)
|
|
75
|
-
.set({
|
|
76
|
-
name,
|
|
77
|
-
contentMarkdown,
|
|
78
|
-
subject,
|
|
79
|
-
lang,
|
|
80
|
-
disabled,
|
|
81
|
-
lastUpdatedBy,
|
|
82
|
-
updatedAt: updatedAt || new Date(),
|
|
83
|
-
})
|
|
84
|
-
.returningAll()
|
|
85
|
-
.executeTakeFirstOrThrow()
|
|
86
|
-
|
|
87
|
-
return updatedTemplate
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
async delete(id: number): Promise<void> {
|
|
91
|
-
await this.db.db
|
|
92
|
-
.deleteFrom('communication_template')
|
|
93
|
-
.where('id', '=', id)
|
|
94
|
-
.execute()
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
view(template: Selectable<CommunicationTemplate>): TemplateView {
|
|
98
|
-
return {
|
|
99
|
-
id: `${template.id}`,
|
|
100
|
-
name: template.name,
|
|
101
|
-
contentMarkdown: template.contentMarkdown,
|
|
102
|
-
disabled: template.disabled,
|
|
103
|
-
lang: template.lang || undefined,
|
|
104
|
-
subject: template.subject || undefined,
|
|
105
|
-
createdAt: template.createdAt.toISOString(),
|
|
106
|
-
updatedAt: template.updatedAt.toISOString(),
|
|
107
|
-
lastUpdatedBy: template.lastUpdatedBy,
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
// Postgresql will throw a specific error code with the constraint when trying to create a template with duplicate name
|
|
2
|
-
// see https://www.postgresql.org/docs/current/errcodes-appendix.html
|
|
3
|
-
export const isDuplicateTemplateNameError = (err: any) => {
|
|
4
|
-
return (
|
|
5
|
-
err?.['code'] === '23505' &&
|
|
6
|
-
err?.['constraint'] === 'communication_template_unique_name'
|
|
7
|
-
)
|
|
8
|
-
}
|