@atproto/pds 0.5.5 → 0.5.7
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 +31 -0
- package/dist/account-manager/account-manager.d.ts +51 -13
- package/dist/account-manager/account-manager.d.ts.map +1 -1
- package/dist/account-manager/account-manager.js +86 -26
- package/dist/account-manager/account-manager.js.map +1 -1
- package/dist/account-manager/db/migrations/005-oauth-account-management.d.ts.map +1 -1
- package/dist/account-manager/db/migrations/005-oauth-account-management.js +3 -4
- package/dist/account-manager/db/migrations/005-oauth-account-management.js.map +1 -1
- package/dist/account-manager/db/schema/authorization-request.d.ts +2 -2
- package/dist/account-manager/db/schema/authorization-request.d.ts.map +1 -1
- package/dist/account-manager/db/schema/authorization-request.js.map +1 -1
- package/dist/account-manager/db/schema/authorized-client.d.ts +2 -2
- package/dist/account-manager/db/schema/authorized-client.d.ts.map +1 -1
- package/dist/account-manager/db/schema/authorized-client.js.map +1 -1
- package/dist/account-manager/db/schema/token.d.ts +2 -2
- package/dist/account-manager/db/schema/token.d.ts.map +1 -1
- package/dist/account-manager/db/schema/token.js.map +1 -1
- package/dist/account-manager/helpers/account-device.d.ts +23 -196
- package/dist/account-manager/helpers/account-device.d.ts.map +1 -1
- package/dist/account-manager/helpers/account-device.js +3 -3
- package/dist/account-manager/helpers/account-device.js.map +1 -1
- package/dist/account-manager/helpers/account.d.ts +14 -4
- package/dist/account-manager/helpers/account.d.ts.map +1 -1
- package/dist/account-manager/helpers/account.js +17 -11
- package/dist/account-manager/helpers/account.js.map +1 -1
- package/dist/account-manager/helpers/auth.js +1 -1
- package/dist/account-manager/helpers/auth.js.map +1 -1
- package/dist/account-manager/helpers/authorization-request.d.ts +83 -5
- package/dist/account-manager/helpers/authorization-request.d.ts.map +1 -1
- package/dist/account-manager/helpers/authorization-request.js +8 -8
- package/dist/account-manager/helpers/authorization-request.js.map +1 -1
- package/dist/account-manager/helpers/authorized-client.d.ts +5 -4
- package/dist/account-manager/helpers/authorized-client.d.ts.map +1 -1
- package/dist/account-manager/helpers/authorized-client.js +3 -0
- package/dist/account-manager/helpers/authorized-client.js.map +1 -1
- package/dist/account-manager/helpers/device.d.ts +9 -3
- package/dist/account-manager/helpers/device.d.ts.map +1 -1
- package/dist/account-manager/helpers/device.js +4 -4
- package/dist/account-manager/helpers/device.js.map +1 -1
- package/dist/account-manager/helpers/invite.d.ts +35 -2
- package/dist/account-manager/helpers/invite.d.ts.map +1 -1
- package/dist/account-manager/helpers/lexicon.d.ts.map +1 -1
- package/dist/account-manager/helpers/lexicon.js +6 -0
- package/dist/account-manager/helpers/lexicon.js.map +1 -1
- package/dist/account-manager/helpers/password.d.ts +1 -0
- package/dist/account-manager/helpers/password.d.ts.map +1 -1
- package/dist/account-manager/helpers/password.js +3 -0
- package/dist/account-manager/helpers/password.js.map +1 -1
- package/dist/account-manager/helpers/token.d.ts +72 -1031
- package/dist/account-manager/helpers/token.d.ts.map +1 -1
- package/dist/account-manager/helpers/token.js +13 -10
- package/dist/account-manager/helpers/token.js.map +1 -1
- package/dist/account-manager/helpers/used-refresh-token.d.ts +6 -2
- package/dist/account-manager/helpers/used-refresh-token.d.ts.map +1 -1
- package/dist/account-manager/oauth-store.d.ts +17 -13
- package/dist/account-manager/oauth-store.d.ts.map +1 -1
- package/dist/account-manager/oauth-store.js +89 -39
- package/dist/account-manager/oauth-store.js.map +1 -1
- package/dist/actor-store/blob/reader.d.ts.map +1 -1
- package/dist/actor-store/blob/reader.js +2 -3
- package/dist/actor-store/blob/reader.js.map +1 -1
- package/dist/actor-store/record/reader.js +3 -3
- package/dist/actor-store/record/reader.js.map +1 -1
- package/dist/actor-store/repo/sql-repo-reader.d.ts +5 -1
- package/dist/actor-store/repo/sql-repo-reader.d.ts.map +1 -1
- package/dist/actor-store/repo/sql-repo-reader.js.map +1 -1
- package/dist/api/com/atproto/admin/updateSubjectStatus.d.ts.map +1 -1
- package/dist/api/com/atproto/admin/updateSubjectStatus.js +12 -4
- package/dist/api/com/atproto/admin/updateSubjectStatus.js.map +1 -1
- package/dist/api/com/atproto/server/activateAccount.d.ts.map +1 -1
- package/dist/api/com/atproto/server/activateAccount.js +25 -31
- package/dist/api/com/atproto/server/activateAccount.js.map +1 -1
- package/dist/api/com/atproto/server/deactivateAccount.d.ts.map +1 -1
- package/dist/api/com/atproto/server/deactivateAccount.js +3 -4
- package/dist/api/com/atproto/server/deactivateAccount.js.map +1 -1
- package/dist/api/com/atproto/server/deleteAccount.d.ts.map +1 -1
- package/dist/api/com/atproto/server/deleteAccount.js +51 -37
- package/dist/api/com/atproto/server/deleteAccount.js.map +1 -1
- package/dist/api/com/atproto/server/util.d.ts +25 -6
- package/dist/api/com/atproto/server/util.d.ts.map +1 -1
- package/dist/api/com/atproto/server/util.js.map +1 -1
- package/dist/background.d.ts +12 -6
- package/dist/background.d.ts.map +1 -1
- package/dist/background.js +32 -13
- package/dist/background.js.map +1 -1
- package/dist/config/config.d.ts +2 -1
- package/dist/config/config.d.ts.map +1 -1
- package/dist/config/config.js +4 -1
- package/dist/config/config.js.map +1 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +5 -32
- package/dist/context.js.map +1 -1
- package/dist/db/migrator.d.ts +4 -3
- package/dist/db/migrator.d.ts.map +1 -1
- package/dist/db/migrator.js +1 -1
- package/dist/db/migrator.js.map +1 -1
- package/dist/db/pagination.d.ts +2 -1
- package/dist/db/pagination.d.ts.map +1 -1
- package/dist/db/pagination.js +2 -2
- package/dist/db/pagination.js.map +1 -1
- package/dist/db/util.d.ts +3 -3
- package/dist/db/util.d.ts.map +1 -1
- package/dist/db/util.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +33 -11
- package/dist/index.js.map +1 -1
- package/dist/lexicons/app/bsky/notification/defs.defs.d.ts +5 -0
- package/dist/lexicons/app/bsky/notification/defs.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/notification/defs.defs.js +1 -0
- package/dist/lexicons/app/bsky/notification/defs.defs.js.map +1 -1
- package/dist/lexicons/chat/bsky/notification/defs.d.ts +2 -0
- package/dist/lexicons/chat/bsky/notification/defs.d.ts.map +1 -0
- package/dist/lexicons/chat/bsky/notification/defs.defs.d.ts +20 -0
- package/dist/lexicons/chat/bsky/notification/defs.defs.d.ts.map +1 -0
- package/dist/lexicons/chat/bsky/notification/defs.defs.js +19 -0
- package/dist/lexicons/chat/bsky/notification/defs.defs.js.map +1 -0
- package/dist/lexicons/chat/bsky/notification/defs.js +5 -0
- package/dist/lexicons/chat/bsky/notification/defs.js.map +1 -0
- package/dist/lexicons/chat/bsky/notification/getPreferences.d.ts +3 -0
- package/dist/lexicons/chat/bsky/notification/getPreferences.d.ts.map +1 -0
- package/dist/lexicons/chat/bsky/notification/getPreferences.defs.d.ts +18 -0
- package/dist/lexicons/chat/bsky/notification/getPreferences.defs.d.ts.map +1 -0
- package/dist/lexicons/chat/bsky/notification/getPreferences.defs.js +16 -0
- package/dist/lexicons/chat/bsky/notification/getPreferences.defs.js.map +1 -0
- package/dist/lexicons/chat/bsky/notification/getPreferences.js +6 -0
- package/dist/lexicons/chat/bsky/notification/getPreferences.js.map +1 -0
- package/dist/lexicons/chat/bsky/notification/putPreferences.d.ts +3 -0
- package/dist/lexicons/chat/bsky/notification/putPreferences.d.ts.map +1 -0
- package/dist/lexicons/chat/bsky/notification/putPreferences.defs.d.ts +27 -0
- package/dist/lexicons/chat/bsky/notification/putPreferences.defs.d.ts.map +1 -0
- package/dist/lexicons/chat/bsky/notification/putPreferences.defs.js +22 -0
- package/dist/lexicons/chat/bsky/notification/putPreferences.defs.js.map +1 -0
- package/dist/lexicons/chat/bsky/notification/putPreferences.js +6 -0
- package/dist/lexicons/chat/bsky/notification/putPreferences.js.map +1 -0
- package/dist/lexicons/chat/bsky/notification.d.ts +4 -0
- package/dist/lexicons/chat/bsky/notification.d.ts.map +1 -0
- package/dist/lexicons/chat/bsky/notification.js +7 -0
- package/dist/lexicons/chat/bsky/notification.js.map +1 -0
- package/dist/lexicons/chat/bsky.d.ts +1 -0
- package/dist/lexicons/chat/bsky.d.ts.map +1 -1
- package/dist/lexicons/chat/bsky.js +1 -0
- package/dist/lexicons/chat/bsky.js.map +1 -1
- package/dist/lexicons/tools/ozone/report/defs.defs.d.ts +4 -0
- package/dist/lexicons/tools/ozone/report/defs.defs.d.ts.map +1 -1
- package/dist/lexicons/tools/ozone/report/defs.defs.js +2 -0
- package/dist/lexicons/tools/ozone/report/defs.defs.js.map +1 -1
- package/dist/lexicons/tools/ozone/report/queryActivities.d.ts +3 -0
- package/dist/lexicons/tools/ozone/report/queryActivities.d.ts.map +1 -0
- package/dist/lexicons/tools/ozone/report/queryActivities.defs.d.ts +42 -0
- package/dist/lexicons/tools/ozone/report/queryActivities.defs.d.ts.map +1 -0
- package/dist/lexicons/tools/ozone/report/queryActivities.defs.js +31 -0
- package/dist/lexicons/tools/ozone/report/queryActivities.defs.js.map +1 -0
- package/dist/lexicons/tools/ozone/report/queryActivities.js +6 -0
- package/dist/lexicons/tools/ozone/report/queryActivities.js.map +1 -0
- package/dist/lexicons/tools/ozone/report.d.ts +1 -0
- package/dist/lexicons/tools/ozone/report.d.ts.map +1 -1
- package/dist/lexicons/tools/ozone/report.js +1 -0
- package/dist/lexicons/tools/ozone/report.js.map +1 -1
- package/dist/mailer/index.d.ts +2 -0
- package/dist/mailer/index.d.ts.map +1 -1
- package/dist/mailer/index.js +2 -0
- package/dist/mailer/index.js.map +1 -1
- package/dist/pipethrough.d.ts +3 -0
- package/dist/pipethrough.d.ts.map +1 -1
- package/dist/pipethrough.js +32 -0
- package/dist/pipethrough.js.map +1 -1
- package/dist/scripts/sequencer-recovery/recovery-db.js.map +1 -1
- package/dist/sequencer/events.d.ts.map +1 -1
- package/dist/sequencer/events.js +6 -13
- package/dist/sequencer/events.js.map +1 -1
- package/dist/sequencer/sequencer.d.ts +1 -1
- package/dist/sequencer/sequencer.d.ts.map +1 -1
- package/dist/sequencer/sequencer.js.map +1 -1
- package/package.json +14 -14
- package/src/account-manager/account-manager.ts +135 -36
- package/src/account-manager/db/migrations/005-oauth-account-management.ts +6 -5
- package/src/account-manager/db/schema/authorization-request.ts +2 -1
- package/src/account-manager/db/schema/authorized-client.ts +6 -2
- package/src/account-manager/db/schema/token.ts +2 -2
- package/src/account-manager/helpers/account-device.ts +5 -11
- package/src/account-manager/helpers/account.ts +39 -16
- package/src/account-manager/helpers/auth.ts +2 -2
- package/src/account-manager/helpers/authorization-request.ts +12 -8
- package/src/account-manager/helpers/authorized-client.ts +12 -6
- package/src/account-manager/helpers/device.ts +4 -4
- package/src/account-manager/helpers/lexicon.ts +8 -3
- package/src/account-manager/helpers/password.ts +6 -0
- package/src/account-manager/helpers/token.ts +17 -11
- package/src/account-manager/oauth-store.ts +129 -61
- package/src/actor-store/blob/reader.ts +8 -5
- package/src/actor-store/record/reader.ts +3 -3
- package/src/actor-store/repo/sql-repo-reader.ts +1 -1
- package/src/api/com/atproto/admin/updateSubjectStatus.ts +16 -4
- package/src/api/com/atproto/server/activateAccount.ts +27 -49
- package/src/api/com/atproto/server/deactivateAccount.ts +3 -7
- package/src/api/com/atproto/server/deleteAccount.ts +60 -43
- package/src/api/com/atproto/server/util.ts +24 -7
- package/src/background.ts +49 -18
- package/src/config/config.ts +7 -2
- package/src/context.ts +6 -40
- package/src/db/migrator.ts +2 -1
- package/src/db/pagination.ts +7 -7
- package/src/db/util.ts +5 -2
- package/src/index.ts +31 -13
- package/src/mailer/index.ts +4 -2
- package/src/pipethrough.ts +38 -1
- package/src/scripts/sequencer-recovery/recovery-db.ts +1 -1
- package/src/sequencer/events.ts +8 -13
- package/src/sequencer/sequencer.ts +1 -3
- package/tests/_util.ts +8 -25
- package/tests/account-deactivation.test.ts +1 -1
- package/tests/account-deletion.test.ts +1 -1
- package/tests/account-manager.test.ts +79 -0
- package/tests/account-migration.test.ts +2 -2
- package/tests/account-status.test.ts +206 -0
- package/tests/account.test.ts +1 -1
- package/tests/app-passwords.test.ts +1 -1
- package/tests/auth.test.ts +1 -1
- package/tests/blob-deletes.test.ts +1 -1
- package/tests/create-post.test.ts +1 -1
- package/tests/crud.test.ts +1 -1
- package/tests/db.test.ts +4 -4
- package/tests/email-confirmation.test.ts +1 -1
- package/tests/file-uploads.test.ts +2 -2
- package/tests/get-service-auth.test.ts +1 -1
- package/tests/handles.test.ts +1 -1
- package/tests/invite-codes.test.ts +1 -1
- package/tests/invites-admin.test.ts +1 -1
- package/tests/moderation.test.ts +1 -1
- package/tests/moderator-auth.test.ts +1 -1
- package/tests/oauth.test.ts +91 -0
- package/tests/plc-operations.test.ts +1 -1
- package/tests/preferences.test.ts +1 -1
- package/tests/proxied/admin.test.ts +1 -1
- package/tests/proxied/feedgen.test.ts +1 -1
- package/tests/proxied/notif.test.ts +6 -13
- package/tests/proxied/procedures.test.ts +1 -1
- package/tests/proxied/proxy-catchall.test.ts +9 -8
- package/tests/proxied/proxy-header.test.ts +12 -8
- package/tests/proxied/proxy-oauth-aud.test.ts +17 -10
- package/tests/proxied/read-after-write.test.ts +4 -5
- package/tests/proxied/views.test.ts +1 -1
- package/tests/races.test.ts +1 -1
- package/tests/rate-limits.test.ts +1 -1
- package/tests/recovery.test.ts +1 -1
- package/tests/seeds/basic.ts +2 -2
- package/tests/seeds/users.ts +4 -1
- package/tests/sequencer.test.ts +1 -1
- package/tests/server.test.ts +9 -12
- package/tests/sync/invertible-ops.test.ts +1 -1
- package/tests/sync/list.test.ts +1 -1
- package/tests/sync/subscribe-repos.test.ts +1 -1
- package/tests/sync/sync.test.ts +1 -1
- package/tests/takedown-appeal.test.ts +1 -1
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -2,6 +2,7 @@ import { MINUTE } from '@atproto/common'
|
|
|
2
2
|
import {
|
|
3
3
|
AuthRequiredError,
|
|
4
4
|
InvalidRequestError,
|
|
5
|
+
MethodRateLimit,
|
|
5
6
|
Server,
|
|
6
7
|
} from '@atproto/xrpc-server'
|
|
7
8
|
import { OLD_PASSWORD_MAX_LENGTH } from '../../../../account-manager/helpers/scrypt.js'
|
|
@@ -11,58 +12,74 @@ import { com } from '../../../../lexicons/index.js'
|
|
|
11
12
|
export default function (server: Server, ctx: AppContext) {
|
|
12
13
|
const { entrywayClient } = ctx
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
},
|
|
19
|
-
handler: async ({ input: { body }, req }) => {
|
|
20
|
-
const { did, password, token } = body
|
|
15
|
+
const rateLimit: MethodRateLimit = {
|
|
16
|
+
durationMs: 5 * MINUTE,
|
|
17
|
+
points: 50,
|
|
18
|
+
}
|
|
21
19
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
20
|
+
if (entrywayClient) {
|
|
21
|
+
server.add(com.atproto.server.deleteAccount, {
|
|
22
|
+
rateLimit,
|
|
23
|
+
handler: async ({ input: { body }, req }) => {
|
|
24
|
+
const account = await ctx.accountManager.getAccount(body.did, {
|
|
25
|
+
includeDeactivated: true,
|
|
26
|
+
includeTakenDown: true,
|
|
27
|
+
})
|
|
28
|
+
if (!account) {
|
|
29
|
+
throw new InvalidRequestError('account not found')
|
|
30
|
+
}
|
|
29
31
|
|
|
30
|
-
if (entrywayClient) {
|
|
31
32
|
const { headers } = ctx.entrywayPassthruHeaders(req)
|
|
32
33
|
await entrywayClient.xrpc(com.atproto.server.deleteAccount, {
|
|
33
34
|
body,
|
|
34
35
|
headers,
|
|
35
36
|
})
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
},
|
|
38
|
+
})
|
|
39
|
+
} else {
|
|
40
|
+
server.add(com.atproto.server.deleteAccount, {
|
|
41
|
+
rateLimit,
|
|
42
|
+
handler: async ({ input: { body } }) => {
|
|
43
|
+
const { did, password, token } = body
|
|
44
|
+
|
|
45
|
+
if (password.length > OLD_PASSWORD_MAX_LENGTH) {
|
|
46
|
+
throw new AuthRequiredError(
|
|
47
|
+
'Password too long. Consider resetting your password.',
|
|
48
|
+
)
|
|
49
|
+
}
|
|
38
50
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
51
|
+
const account = await ctx.accountManager.getAccount(did, {
|
|
52
|
+
includeDeactivated: true,
|
|
53
|
+
includeTakenDown: true,
|
|
54
|
+
})
|
|
55
|
+
if (!account) {
|
|
56
|
+
throw new InvalidRequestError('account not found')
|
|
57
|
+
}
|
|
42
58
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
59
|
+
const validPass = await ctx.accountManager.verifyAccountPassword(
|
|
60
|
+
did,
|
|
61
|
+
password,
|
|
62
|
+
)
|
|
63
|
+
if (!validPass) {
|
|
64
|
+
throw new AuthRequiredError('Invalid did or password')
|
|
65
|
+
}
|
|
50
66
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
67
|
+
await ctx.accountManager.assertValidEmailToken(
|
|
68
|
+
did,
|
|
69
|
+
'delete_account',
|
|
70
|
+
token,
|
|
71
|
+
)
|
|
56
72
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
73
|
+
// @NOTE Order matters here: first "unlink" the account by removing it
|
|
74
|
+
// from the account manager database ("source of truth"), then notify the
|
|
75
|
+
// sequencer, and finally cleanup files from the file system.
|
|
76
|
+
await ctx.accountManager.deleteAccount(did)
|
|
77
|
+
try {
|
|
78
|
+
await ctx.sequencer.sequenceAccountDeletion(did)
|
|
79
|
+
} finally {
|
|
80
|
+
await ctx.actorStore.destroy(did)
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
})
|
|
84
|
+
}
|
|
68
85
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import * as plc from '@did-plc/lib'
|
|
1
2
|
import { getPdsEndpoint, getSigningDidKey } from '@atproto/common'
|
|
2
3
|
import * as crypto from '@atproto/crypto'
|
|
3
|
-
import { DidDocument } from '@atproto/identity'
|
|
4
|
+
import { DidDocument, IdResolver } from '@atproto/identity'
|
|
4
5
|
import { InvalidRequestError } from '@atproto/xrpc-server'
|
|
6
|
+
import { ActorStore } from '../../../../actor-store/actor-store.js'
|
|
5
7
|
import { ServerConfig } from '../../../../config/index.js'
|
|
6
|
-
import { AppContext } from '../../../../context.js'
|
|
7
8
|
import { httpLogger } from '../../../../logger.js'
|
|
8
9
|
|
|
9
10
|
// generate an invite code preceded by the hostname
|
|
@@ -29,7 +30,7 @@ export const getRandomToken = () => {
|
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
export const safeResolveDidDoc = async (
|
|
32
|
-
ctx:
|
|
33
|
+
ctx: { idResolver: IdResolver },
|
|
33
34
|
did: string,
|
|
34
35
|
forceRefresh?: boolean,
|
|
35
36
|
): Promise<DidDocument | undefined> => {
|
|
@@ -42,7 +43,7 @@ export const safeResolveDidDoc = async (
|
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
export const didDocForSession = async (
|
|
45
|
-
ctx:
|
|
46
|
+
ctx: { idResolver: IdResolver; cfg: ServerConfig },
|
|
46
47
|
did: string,
|
|
47
48
|
forceRefresh?: boolean,
|
|
48
49
|
): Promise<DidDocument | undefined> => {
|
|
@@ -51,7 +52,13 @@ export const didDocForSession = async (
|
|
|
51
52
|
}
|
|
52
53
|
|
|
53
54
|
export const isValidDidDocForService = async (
|
|
54
|
-
ctx:
|
|
55
|
+
ctx: {
|
|
56
|
+
plcClient: plc.Client
|
|
57
|
+
idResolver: IdResolver
|
|
58
|
+
cfg: ServerConfig
|
|
59
|
+
plcRotationKey: crypto.Keypair
|
|
60
|
+
actorStore: ActorStore
|
|
61
|
+
},
|
|
55
62
|
did: string,
|
|
56
63
|
): Promise<boolean> => {
|
|
57
64
|
try {
|
|
@@ -63,7 +70,13 @@ export const isValidDidDocForService = async (
|
|
|
63
70
|
}
|
|
64
71
|
|
|
65
72
|
export const assertValidDidDocumentForService = async (
|
|
66
|
-
ctx:
|
|
73
|
+
ctx: {
|
|
74
|
+
plcClient: plc.Client
|
|
75
|
+
idResolver: IdResolver
|
|
76
|
+
cfg: ServerConfig
|
|
77
|
+
plcRotationKey: crypto.Keypair
|
|
78
|
+
actorStore: ActorStore
|
|
79
|
+
},
|
|
67
80
|
did: string,
|
|
68
81
|
) => {
|
|
69
82
|
if (did.startsWith('did:plc')) {
|
|
@@ -86,7 +99,11 @@ export const assertValidDidDocumentForService = async (
|
|
|
86
99
|
}
|
|
87
100
|
|
|
88
101
|
const assertValidDocContents = async (
|
|
89
|
-
ctx:
|
|
102
|
+
ctx: {
|
|
103
|
+
cfg: ServerConfig
|
|
104
|
+
plcRotationKey: crypto.Keypair
|
|
105
|
+
actorStore: ActorStore
|
|
106
|
+
},
|
|
90
107
|
did: string,
|
|
91
108
|
contents: {
|
|
92
109
|
signingKey?: string
|
package/src/background.ts
CHANGED
|
@@ -1,34 +1,65 @@
|
|
|
1
1
|
import PQueue from 'p-queue'
|
|
2
2
|
import { dbLogger } from './logger.js'
|
|
3
|
-
|
|
4
3
|
// A simple queue for in-process, out-of-band/backgrounded work
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
queue: InstanceType<typeof PQueue> = new PQueue({ concurrency: 5 })
|
|
8
|
-
destroyed = false
|
|
9
|
-
constructor() {}
|
|
5
|
+
type Task<TContext> = (ctx: TContext, signal: AbortSignal) => Promise<void>
|
|
10
6
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
7
|
+
export type BackgroundQueueOptions = NonNullable<
|
|
8
|
+
ConstructorParameters<typeof PQueue>[0]
|
|
9
|
+
> & {
|
|
10
|
+
concurrency: number
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// @NOTE Keep this in sync with the BackgroundQueue in
|
|
14
|
+
// - packages/bsky/src/data-plane/server/background.ts
|
|
15
|
+
// - packages/ozone/src/background.ts
|
|
16
|
+
// - packages/pds/src/background.ts
|
|
17
|
+
export class BackgroundQueue<TContext = unknown> {
|
|
18
|
+
private abortController = new AbortController()
|
|
19
|
+
private queue: PQueue
|
|
20
|
+
|
|
21
|
+
public get signal(): AbortSignal {
|
|
22
|
+
return this.abortController.signal
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public get destroyed() {
|
|
26
|
+
return this.signal.aborted
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
constructor(
|
|
30
|
+
private readonly context: TContext,
|
|
31
|
+
options?: BackgroundQueueOptions,
|
|
32
|
+
) {
|
|
33
|
+
this.queue = new PQueue(options)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
add(task: Task<TContext>) {
|
|
37
|
+
if (this.destroyed) return
|
|
38
|
+
|
|
39
|
+
this.queue.add<void>(async () => {
|
|
40
|
+
try {
|
|
41
|
+
// The task will receive a signal allowing it to abort if the
|
|
42
|
+
// backgroundQueue is destroyed.
|
|
43
|
+
await task(this.context, this.signal)
|
|
44
|
+
} catch (err) {
|
|
18
45
|
dbLogger.error({ err }, 'background queue task failed')
|
|
19
|
-
}
|
|
46
|
+
}
|
|
47
|
+
})
|
|
20
48
|
}
|
|
21
49
|
|
|
22
50
|
async processAll() {
|
|
23
|
-
|
|
51
|
+
const { queue } = this
|
|
52
|
+
while (queue.size || queue.pending) await queue.onIdle()
|
|
24
53
|
}
|
|
25
54
|
|
|
26
55
|
// On destroy we stop accepting new tasks, but complete all pending/in-progress tasks.
|
|
27
56
|
// The application calls this only once http connections have drained (tasks no longer being added).
|
|
28
57
|
async destroy() {
|
|
29
|
-
this.destroyed
|
|
30
|
-
|
|
58
|
+
if (this.destroyed) {
|
|
59
|
+
dbLogger.warn('BackgroundQueue.destroy() called multiple times')
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
this.abortController.abort()
|
|
63
|
+
return this.processAll()
|
|
31
64
|
}
|
|
32
65
|
}
|
|
33
|
-
|
|
34
|
-
type Task = () => Promise<void>
|
package/src/config/config.ts
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
BrandingInput as BrandingConfig,
|
|
6
6
|
HcaptchaConfig,
|
|
7
7
|
} from '@atproto/oauth-provider'
|
|
8
|
-
import { ensureValidDid } from '@atproto/syntax'
|
|
8
|
+
import { DidString, ensureValidDid, isValidDid } from '@atproto/syntax'
|
|
9
9
|
import { ServerEnvironment } from './env.js'
|
|
10
10
|
|
|
11
11
|
export type { BrandingConfig }
|
|
@@ -21,6 +21,11 @@ export const envToCfg = (env: ServerEnvironment): ServerConfig => {
|
|
|
21
21
|
? `http://localhost:${port}`
|
|
22
22
|
: `https://${hostname}`
|
|
23
23
|
const did = env.serviceDid ?? `did:web:${hostname}`
|
|
24
|
+
|
|
25
|
+
if (!isValidDid(did)) {
|
|
26
|
+
throw new Error(`Invalid service DID: ${did}`)
|
|
27
|
+
}
|
|
28
|
+
|
|
24
29
|
const serviceCfg: ServerConfig['service'] = {
|
|
25
30
|
port,
|
|
26
31
|
hostname,
|
|
@@ -400,7 +405,7 @@ export type ServiceConfig = {
|
|
|
400
405
|
port: number
|
|
401
406
|
hostname: string
|
|
402
407
|
publicUrl: string
|
|
403
|
-
did:
|
|
408
|
+
did: DidString
|
|
404
409
|
version?: string
|
|
405
410
|
privacyPolicyUrl?: string
|
|
406
411
|
termsOfServiceUrl?: string
|
package/src/context.ts
CHANGED
|
@@ -21,12 +21,7 @@ import {
|
|
|
21
21
|
createServiceAuthHeaders,
|
|
22
22
|
createServiceJwt,
|
|
23
23
|
} from '@atproto/xrpc-server'
|
|
24
|
-
import {
|
|
25
|
-
Fetch,
|
|
26
|
-
isUnicastIp,
|
|
27
|
-
safeFetchWrap,
|
|
28
|
-
unicastLookup,
|
|
29
|
-
} from '@atproto-labs/fetch-node'
|
|
24
|
+
import { Fetch, safeFetchWrap } from '@atproto-labs/fetch-node'
|
|
30
25
|
import { AccountManager } from './account-manager/account-manager.js'
|
|
31
26
|
import { OAuthStore } from './account-manager/oauth-store.js'
|
|
32
27
|
import { ScopeReferenceGetter } from './account-manager/scope-reference-getter.js'
|
|
@@ -47,6 +42,7 @@ import { ImageUrlBuilder } from './image/image-url-builder.js'
|
|
|
47
42
|
import { fetchLogger, lexiconResolverLogger, oauthLogger } from './logger.js'
|
|
48
43
|
import { ServerMailer } from './mailer/index.js'
|
|
49
44
|
import { ModerationMailer } from './mailer/moderation.js'
|
|
45
|
+
import { buildProxyAgent } from './pipethrough.js'
|
|
50
46
|
import { LocalViewer, LocalViewerCreator } from './read-after-write/viewer.js'
|
|
51
47
|
import { getRedisClient } from './redis.js'
|
|
52
48
|
import { Sequencer } from './sequencer/index.js'
|
|
@@ -181,7 +177,7 @@ export class AppContext {
|
|
|
181
177
|
})
|
|
182
178
|
const plcClient = new plc.Client(cfg.identity.plcUrl)
|
|
183
179
|
|
|
184
|
-
const backgroundQueue = new BackgroundQueue()
|
|
180
|
+
const backgroundQueue = new BackgroundQueue(undefined, { concurrency: 5 })
|
|
185
181
|
const crawlers = new Crawlers(
|
|
186
182
|
backgroundQueue,
|
|
187
183
|
cfg.service.hostname,
|
|
@@ -277,15 +273,14 @@ export class AppContext {
|
|
|
277
273
|
)
|
|
278
274
|
|
|
279
275
|
const accountManager = new AccountManager(
|
|
276
|
+
cfg,
|
|
277
|
+
actorStore,
|
|
280
278
|
idResolver,
|
|
281
279
|
jwtSecretKey,
|
|
282
280
|
mailer,
|
|
283
281
|
sequencer,
|
|
284
282
|
plcClient,
|
|
285
283
|
plcRotationKey,
|
|
286
|
-
cfg.service.did,
|
|
287
|
-
cfg.identity.serviceHandleDomains,
|
|
288
|
-
cfg.db,
|
|
289
284
|
)
|
|
290
285
|
await accountManager.migrateOrThrow()
|
|
291
286
|
|
|
@@ -296,36 +291,7 @@ export class AppContext {
|
|
|
296
291
|
)
|
|
297
292
|
|
|
298
293
|
// An agent for performing HTTP requests based on user provided URLs.
|
|
299
|
-
const
|
|
300
|
-
allowH2: cfg.proxy.allowHTTP2, // This is experimental
|
|
301
|
-
headersTimeout: cfg.proxy.headersTimeout,
|
|
302
|
-
maxResponseSize: cfg.proxy.maxResponseSize,
|
|
303
|
-
bodyTimeout: cfg.proxy.bodyTimeout,
|
|
304
|
-
factory: cfg.proxy.disableSsrfProtection
|
|
305
|
-
? undefined
|
|
306
|
-
: (origin, opts) => {
|
|
307
|
-
const { protocol, hostname } =
|
|
308
|
-
origin instanceof URL ? origin : new URL(origin)
|
|
309
|
-
if (protocol !== 'https:') {
|
|
310
|
-
throw new Error(`Forbidden protocol "${protocol}"`)
|
|
311
|
-
}
|
|
312
|
-
if (isUnicastIp(hostname) === false) {
|
|
313
|
-
throw new Error('Hostname resolved to non-unicast address')
|
|
314
|
-
}
|
|
315
|
-
return new undici.Pool(origin, opts)
|
|
316
|
-
},
|
|
317
|
-
connect: {
|
|
318
|
-
lookup: cfg.proxy.disableSsrfProtection ? undefined : unicastLookup,
|
|
319
|
-
},
|
|
320
|
-
})
|
|
321
|
-
const proxyAgent =
|
|
322
|
-
cfg.proxy.maxRetries > 0
|
|
323
|
-
? new undici.RetryAgent(proxyAgentBase, {
|
|
324
|
-
statusCodes: [], // Only retry on socket errors
|
|
325
|
-
methods: ['GET', 'HEAD'],
|
|
326
|
-
maxRetries: cfg.proxy.maxRetries,
|
|
327
|
-
})
|
|
328
|
-
: proxyAgentBase
|
|
294
|
+
const proxyAgent = buildProxyAgent(cfg.proxy)
|
|
329
295
|
|
|
330
296
|
/**
|
|
331
297
|
* A fetch() function that protects against SSRF attacks, large responses &
|
package/src/db/migrator.ts
CHANGED
package/src/db/pagination.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { sql } from 'kysely'
|
|
1
|
+
import { SqlBool, sql } from 'kysely'
|
|
2
2
|
import { InvalidRequestError } from '@atproto/xrpc-server'
|
|
3
3
|
import { AnyQb, DbRef } from './util.js'
|
|
4
4
|
|
|
@@ -66,16 +66,16 @@ export abstract class GenericKeyset<R, LR extends LabeledResult> {
|
|
|
66
66
|
if (tryIndex) {
|
|
67
67
|
// The tryIndex param will likely disappear and become the default implementation: here for now for gradual rollout query-by-query.
|
|
68
68
|
if (direction === 'asc') {
|
|
69
|
-
return sql
|
|
69
|
+
return sql<SqlBool>`((${this.primary}, ${this.secondary}) > (${labeled.primary}, ${labeled.secondary}))`
|
|
70
70
|
} else {
|
|
71
|
-
return sql
|
|
71
|
+
return sql<SqlBool>`((${this.primary}, ${this.secondary}) < (${labeled.primary}, ${labeled.secondary}))`
|
|
72
72
|
}
|
|
73
73
|
} else {
|
|
74
74
|
// @NOTE this implementation can struggle to use an index on (primary, secondary) for pagination due to the "or" usage.
|
|
75
75
|
if (direction === 'asc') {
|
|
76
|
-
return sql
|
|
76
|
+
return sql<SqlBool>`((${this.primary} > ${labeled.primary}) or (${this.primary} = ${labeled.primary} and ${this.secondary} > ${labeled.secondary}))`
|
|
77
77
|
} else {
|
|
78
|
-
return sql
|
|
78
|
+
return sql<SqlBool>`((${this.primary} < ${labeled.primary}) or (${this.primary} = ${labeled.primary} and ${this.secondary} < ${labeled.secondary}))`
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
}
|
|
@@ -125,8 +125,8 @@ export const paginate = <
|
|
|
125
125
|
const { limit, cursor, keyset, direction = 'desc', tryIndex } = opts
|
|
126
126
|
const keysetSql = keyset.getSql(keyset.unpack(cursor), direction, tryIndex)
|
|
127
127
|
return qb
|
|
128
|
-
|
|
128
|
+
.$if(!!limit, (q) => q.limit(limit as number))
|
|
129
129
|
.orderBy(keyset.primary, direction)
|
|
130
130
|
.orderBy(keyset.secondary, direction)
|
|
131
|
-
|
|
131
|
+
.$if(!!keysetSql, (qb) => (keysetSql ? qb.where(keysetSql) : qb)) as QB
|
|
132
132
|
}
|
package/src/db/util.ts
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
RawBuilder,
|
|
6
6
|
ReferenceExpression,
|
|
7
7
|
SelectQueryBuilder,
|
|
8
|
+
SqlBool,
|
|
8
9
|
SqliteAdapter,
|
|
9
10
|
SqliteIntrospector,
|
|
10
11
|
SqliteQueryCompiler,
|
|
@@ -14,7 +15,7 @@ import { retry } from '@atproto/common'
|
|
|
14
15
|
|
|
15
16
|
// Applies to repo_root or record table
|
|
16
17
|
export const notSoftDeletedClause = (alias: DbRef) => {
|
|
17
|
-
return sql
|
|
18
|
+
return sql<SqlBool>`${alias}."takedownRef" is null`
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
export const softDeleted = (repoOrRecord: { takedownRef: string | null }) => {
|
|
@@ -92,7 +93,9 @@ const RETRY_ERRORS = new Set([
|
|
|
92
93
|
|
|
93
94
|
export type Ref = ReferenceExpression<any, any>
|
|
94
95
|
|
|
95
|
-
export type DbRef =
|
|
96
|
+
export type DbRef =
|
|
97
|
+
| RawBuilder<unknown>
|
|
98
|
+
| ReturnType<DynamicModule<unknown>['ref']>
|
|
96
99
|
|
|
97
100
|
export type AnyQb = SelectQueryBuilder<any, any, any>
|
|
98
101
|
|
package/src/index.ts
CHANGED
|
@@ -9,11 +9,8 @@ import http from 'node:http'
|
|
|
9
9
|
import { PlcClientError } from '@did-plc/lib'
|
|
10
10
|
import cors from 'cors'
|
|
11
11
|
import express from 'express'
|
|
12
|
-
// eslint-disable-next-line import/default
|
|
12
|
+
// eslint-disable-next-line import/default
|
|
13
13
|
import httpTerminator from 'http-terminator'
|
|
14
|
-
// eslint-disable-next-line import/no-named-as-default-member
|
|
15
|
-
const { createHttpTerminator } = httpTerminator
|
|
16
|
-
type HttpTerminator = ReturnType<typeof createHttpTerminator>
|
|
17
14
|
import { DAY, SECOND } from '@atproto/common'
|
|
18
15
|
import {
|
|
19
16
|
MethodHandler,
|
|
@@ -64,7 +61,7 @@ export class PDS {
|
|
|
64
61
|
public ctx: AppContext
|
|
65
62
|
public app: express.Application
|
|
66
63
|
public server?: http.Server
|
|
67
|
-
private terminator?: HttpTerminator
|
|
64
|
+
private terminator?: httpTerminator.HttpTerminator
|
|
68
65
|
private dbStatsInterval?: NodeJS.Timeout
|
|
69
66
|
private sequencerStatsInterval?: NodeJS.Timeout
|
|
70
67
|
|
|
@@ -145,21 +142,42 @@ export class PDS {
|
|
|
145
142
|
await this.ctx.sequencer.start()
|
|
146
143
|
const server = this.app.listen(this.ctx.cfg.service.port)
|
|
147
144
|
this.server = server
|
|
148
|
-
this.server.keepAliveTimeout =
|
|
149
|
-
this.terminator = createHttpTerminator({ server })
|
|
145
|
+
this.server.keepAliveTimeout = 90_000
|
|
146
|
+
this.terminator = httpTerminator.createHttpTerminator({ server })
|
|
150
147
|
await events.once(server, 'listening')
|
|
151
148
|
return server
|
|
152
149
|
}
|
|
153
150
|
|
|
154
151
|
async destroy(): Promise<void> {
|
|
155
|
-
await this.ctx.sequencer.destroy()
|
|
156
|
-
await this.terminator?.terminate()
|
|
157
|
-
await this.ctx.backgroundQueue.destroy()
|
|
158
|
-
await this.ctx.accountManager.close()
|
|
159
|
-
await this.ctx.redisScratch?.quit()
|
|
160
|
-
await this.ctx.proxyAgent.destroy()
|
|
161
152
|
clearInterval(this.dbStatsInterval)
|
|
162
153
|
clearInterval(this.sequencerStatsInterval)
|
|
154
|
+
|
|
155
|
+
// @TODO Use disposable stack when it becomes available (Node24+)
|
|
156
|
+
try {
|
|
157
|
+
await this.terminator?.terminate()
|
|
158
|
+
} finally {
|
|
159
|
+
try {
|
|
160
|
+
await this.ctx.backgroundQueue.destroy()
|
|
161
|
+
} finally {
|
|
162
|
+
try {
|
|
163
|
+
await this.ctx.sequencer.destroy()
|
|
164
|
+
} finally {
|
|
165
|
+
try {
|
|
166
|
+
await this.ctx.accountManager.close()
|
|
167
|
+
} finally {
|
|
168
|
+
try {
|
|
169
|
+
await this.ctx.redisScratch?.quit()
|
|
170
|
+
} finally {
|
|
171
|
+
await this.ctx.proxyAgent.destroy()
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
async [Symbol.asyncDispose]() {
|
|
180
|
+
await this.destroy()
|
|
163
181
|
}
|
|
164
182
|
}
|
|
165
183
|
|
package/src/mailer/index.ts
CHANGED
|
@@ -36,9 +36,10 @@ export class ServerMailer {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
async sendResetPassword(
|
|
39
|
-
params: { handle: string; token: string },
|
|
39
|
+
params: { handle: string; token: string; locale?: string },
|
|
40
40
|
mailOpts: SendMailOptions,
|
|
41
41
|
) {
|
|
42
|
+
// @TODO (later) handle locale in the template
|
|
42
43
|
await this.sendTemplate('resetPassword', params, {
|
|
43
44
|
subject: 'Password Reset Requested',
|
|
44
45
|
...mailOpts,
|
|
@@ -46,9 +47,10 @@ export class ServerMailer {
|
|
|
46
47
|
}
|
|
47
48
|
|
|
48
49
|
async sendAccountDelete(
|
|
49
|
-
params: { token: string },
|
|
50
|
+
params: { token: string; locale?: string },
|
|
50
51
|
mailOpts: SendMailOptions,
|
|
51
52
|
) {
|
|
53
|
+
// @TODO (later) handle locale in the template
|
|
52
54
|
await this.sendTemplate('deleteAccount', params, {
|
|
53
55
|
subject: 'Account Deletion Requested',
|
|
54
56
|
...mailOpts,
|
package/src/pipethrough.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { IncomingHttpHeaders, ServerResponse } from 'node:http'
|
|
2
2
|
import { PassThrough, Readable, finished } from 'node:stream'
|
|
3
3
|
import { Request } from 'express'
|
|
4
|
-
import { Dispatcher } from 'undici'
|
|
4
|
+
import { Agent, Dispatcher, Pool, interceptors } from 'undici'
|
|
5
5
|
import {
|
|
6
6
|
decodeStream,
|
|
7
7
|
getServiceEndpoint,
|
|
@@ -20,12 +20,49 @@ import {
|
|
|
20
20
|
excludeErrorResult,
|
|
21
21
|
parseReqNsid,
|
|
22
22
|
} from '@atproto/xrpc-server'
|
|
23
|
+
import { isUnicastIp, unicastLookup } from '@atproto-labs/fetch-node'
|
|
23
24
|
import { buildProxiedContentEncoding } from '@atproto-labs/xrpc-utils'
|
|
24
25
|
import { isAccessPrivileged } from './auth-scope.js'
|
|
26
|
+
import { ProxyConfig } from './config/config.js'
|
|
25
27
|
import { AppContext } from './context.js'
|
|
26
28
|
import { chat, com, tools } from './lexicons/index.js'
|
|
27
29
|
import { httpLogger } from './logger.js'
|
|
28
30
|
|
|
31
|
+
export function buildProxyAgent(cfg: ProxyConfig): Dispatcher {
|
|
32
|
+
const agent = new Agent({
|
|
33
|
+
allowH2: cfg.allowHTTP2,
|
|
34
|
+
headersTimeout: cfg.headersTimeout,
|
|
35
|
+
maxResponseSize: cfg.maxResponseSize,
|
|
36
|
+
bodyTimeout: cfg.bodyTimeout,
|
|
37
|
+
factory: cfg.disableSsrfProtection
|
|
38
|
+
? undefined
|
|
39
|
+
: (origin, opts) => {
|
|
40
|
+
const { protocol, hostname } =
|
|
41
|
+
origin instanceof URL ? origin : new URL(origin)
|
|
42
|
+
if (protocol !== 'https:') {
|
|
43
|
+
throw new Error(`Forbidden protocol "${protocol}"`)
|
|
44
|
+
}
|
|
45
|
+
if (isUnicastIp(hostname) === false) {
|
|
46
|
+
throw new Error('Hostname resolved to non-unicast address')
|
|
47
|
+
}
|
|
48
|
+
return new Pool(origin, opts)
|
|
49
|
+
},
|
|
50
|
+
connect: {
|
|
51
|
+
lookup: cfg.disableSsrfProtection ? undefined : unicastLookup,
|
|
52
|
+
},
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
return agent.compose(
|
|
56
|
+
cfg.maxRetries > 0
|
|
57
|
+
? interceptors.retry({
|
|
58
|
+
statusCodes: [], // Only retry on socket errors
|
|
59
|
+
methods: ['GET', 'HEAD'],
|
|
60
|
+
maxRetries: cfg.maxRetries,
|
|
61
|
+
})
|
|
62
|
+
: (dispatch) => dispatch,
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
|
|
29
66
|
export const proxyHandler = (ctx: AppContext): CatchallHandler => {
|
|
30
67
|
const performAuth = ctx.authVerifier.authorization<RpcPermissionMatch>({
|
|
31
68
|
authorize: (permissions, { params }) => permissions.assertRpc(params),
|
|
@@ -35,7 +35,7 @@ export const getAndMigrateRecoveryDb = async (
|
|
|
35
35
|
const pragmas: Record<string, string> = disableWalAutoCheckpoint
|
|
36
36
|
? { wal_autocheckpoint: '0' }
|
|
37
37
|
: {}
|
|
38
|
-
const db = Database.sqlite(location, pragmas)
|
|
38
|
+
const db = Database.sqlite<RecoveryDbSchema>(location, pragmas)
|
|
39
39
|
const migrator = new Migrator(db.db, migrations)
|
|
40
40
|
await migrator.migrateToLatestOrThrow()
|
|
41
41
|
return db
|
package/src/sequencer/events.ts
CHANGED
|
@@ -83,12 +83,10 @@ export const formatSeqIdentityEvt = async (
|
|
|
83
83
|
did: DidString,
|
|
84
84
|
handle?: HandleString,
|
|
85
85
|
): Promise<RepoSeqInsert> => {
|
|
86
|
-
const evt: IdentityEvt =
|
|
87
|
-
did,
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
evt.handle = handle
|
|
91
|
-
}
|
|
86
|
+
const evt: IdentityEvt = handle //
|
|
87
|
+
? { did, handle }
|
|
88
|
+
: { did }
|
|
89
|
+
|
|
92
90
|
return {
|
|
93
91
|
did,
|
|
94
92
|
eventType: 'identity',
|
|
@@ -101,13 +99,10 @@ export const formatSeqAccountEvt = async (
|
|
|
101
99
|
did: DidString,
|
|
102
100
|
status: AccountStatus,
|
|
103
101
|
): Promise<RepoSeqInsert> => {
|
|
104
|
-
const evt: AccountEvt =
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
if (status !== AccountStatus.Active) {
|
|
109
|
-
evt.status = status
|
|
110
|
-
}
|
|
102
|
+
const evt: AccountEvt =
|
|
103
|
+
status === AccountStatus.Active
|
|
104
|
+
? { did, active: true }
|
|
105
|
+
: { did, active: false, status }
|
|
111
106
|
|
|
112
107
|
return {
|
|
113
108
|
did,
|