@atproto/pds 0.5.12 → 0.5.15
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 +53 -0
- package/dist/api/app/bsky/notification/index.d.ts.map +1 -1
- package/dist/api/app/bsky/notification/index.js +2 -0
- package/dist/api/app/bsky/notification/index.js.map +1 -1
- package/dist/api/app/bsky/notification/unregisterPush.d.ts +4 -0
- package/dist/api/app/bsky/notification/unregisterPush.d.ts.map +1 -0
- package/dist/api/app/bsky/notification/unregisterPush.js +48 -0
- package/dist/api/app/bsky/notification/unregisterPush.js.map +1 -0
- package/dist/lexicons/app/bsky/actor/defs.defs.d.ts +6 -0
- package/dist/lexicons/app/bsky/actor/defs.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/actor/defs.defs.js +1 -0
- package/dist/lexicons/app/bsky/actor/defs.defs.js.map +1 -1
- package/package.json +42 -38
- package/build.templates.cjs +0 -22
- package/example.env +0 -42
- package/jest.config.cjs +0 -27
- package/src/account-manager/account-manager.ts +0 -916
- package/src/account-manager/db/index.ts +0 -21
- package/src/account-manager/db/migrations/001-init.ts +0 -115
- package/src/account-manager/db/migrations/002-account-deactivation.ts +0 -17
- package/src/account-manager/db/migrations/003-privileged-app-passwords.ts +0 -12
- package/src/account-manager/db/migrations/004-oauth.ts +0 -122
- package/src/account-manager/db/migrations/005-oauth-account-management.ts +0 -136
- package/src/account-manager/db/migrations/006-oauth-permission-sets.ts +0 -20
- package/src/account-manager/db/migrations/007-lexicon-failures-index.ts +0 -14
- package/src/account-manager/db/migrations/index.ts +0 -17
- package/src/account-manager/db/schema/account-device.ts +0 -14
- package/src/account-manager/db/schema/account.ts +0 -16
- package/src/account-manager/db/schema/actor.ts +0 -17
- package/src/account-manager/db/schema/app-password.ts +0 -13
- package/src/account-manager/db/schema/authorization-request.ts +0 -30
- package/src/account-manager/db/schema/authorized-client.ts +0 -23
- package/src/account-manager/db/schema/device.ts +0 -18
- package/src/account-manager/db/schema/email-token.ts +0 -19
- package/src/account-manager/db/schema/index.ts +0 -43
- package/src/account-manager/db/schema/invite-code.ts +0 -24
- package/src/account-manager/db/schema/lexicon.ts +0 -15
- package/src/account-manager/db/schema/refresh-token.ts +0 -11
- package/src/account-manager/db/schema/repo-root.ts +0 -12
- package/src/account-manager/db/schema/token.ts +0 -38
- package/src/account-manager/db/schema/used-refresh-token.ts +0 -13
- package/src/account-manager/helpers/account-device.ts +0 -63
- package/src/account-manager/helpers/account.ts +0 -355
- package/src/account-manager/helpers/auth.ts +0 -222
- package/src/account-manager/helpers/authorization-request.ts +0 -90
- package/src/account-manager/helpers/authorized-client.ts +0 -75
- package/src/account-manager/helpers/device.ts +0 -47
- package/src/account-manager/helpers/email-token.ts +0 -87
- package/src/account-manager/helpers/invite.ts +0 -263
- package/src/account-manager/helpers/lexicon.ts +0 -67
- package/src/account-manager/helpers/password.ts +0 -136
- package/src/account-manager/helpers/repo.ts +0 -24
- package/src/account-manager/helpers/scrypt.ts +0 -53
- package/src/account-manager/helpers/token.ts +0 -158
- package/src/account-manager/helpers/used-refresh-token.ts +0 -30
- package/src/account-manager/oauth-store.ts +0 -880
- package/src/account-manager/scope-reference-getter.ts +0 -106
- package/src/actor-store/actor-store-reader.ts +0 -45
- package/src/actor-store/actor-store-resources.ts +0 -8
- package/src/actor-store/actor-store-transactor.ts +0 -31
- package/src/actor-store/actor-store-writer.ts +0 -17
- package/src/actor-store/actor-store.ts +0 -210
- package/src/actor-store/blob/reader.ts +0 -160
- package/src/actor-store/blob/transactor.ts +0 -383
- package/src/actor-store/db/index.ts +0 -20
- package/src/actor-store/db/migrations/001-init.ts +0 -105
- package/src/actor-store/db/migrations/index.ts +0 -5
- package/src/actor-store/db/schema/account-pref.ts +0 -11
- package/src/actor-store/db/schema/backlink.ts +0 -9
- package/src/actor-store/db/schema/blob.ts +0 -14
- package/src/actor-store/db/schema/index.ts +0 -23
- package/src/actor-store/db/schema/record-blob.ts +0 -8
- package/src/actor-store/db/schema/record.ts +0 -14
- package/src/actor-store/db/schema/repo-block.ts +0 -10
- package/src/actor-store/db/schema/repo-root.ts +0 -10
- package/src/actor-store/migrate.ts +0 -39
- package/src/actor-store/preference/reader.ts +0 -48
- package/src/actor-store/preference/transactor.ts +0 -55
- package/src/actor-store/preference/util.ts +0 -39
- package/src/actor-store/record/reader.ts +0 -374
- package/src/actor-store/record/transactor.ts +0 -111
- package/src/actor-store/repo/reader.ts +0 -31
- package/src/actor-store/repo/sql-repo-reader.ts +0 -150
- package/src/actor-store/repo/sql-repo-transactor.ts +0 -105
- package/src/actor-store/repo/transactor.ts +0 -227
- package/src/api/app/bsky/actor/getPreferences.ts +0 -57
- package/src/api/app/bsky/actor/getProfile.ts +0 -41
- package/src/api/app/bsky/actor/getProfiles.ts +0 -51
- package/src/api/app/bsky/actor/index.ts +0 -13
- package/src/api/app/bsky/actor/putPreferences.ts +0 -62
- package/src/api/app/bsky/feed/getActorLikes.ts +0 -63
- package/src/api/app/bsky/feed/getAuthorFeed.ts +0 -84
- package/src/api/app/bsky/feed/getFeed.ts +0 -47
- package/src/api/app/bsky/feed/getPostThread.ts +0 -251
- package/src/api/app/bsky/feed/getTimeline.ts +0 -50
- package/src/api/app/bsky/feed/index.ts +0 -15
- package/src/api/app/bsky/index.ts +0 -11
- package/src/api/app/bsky/notification/index.ts +0 -7
- package/src/api/app/bsky/notification/registerPush.ts +0 -71
- package/src/api/app/bsky/util/resolver.ts +0 -20
- package/src/api/com/atproto/admin/deleteAccount.ts +0 -22
- package/src/api/com/atproto/admin/disableAccountInvites.ts +0 -18
- package/src/api/com/atproto/admin/disableInviteCodes.ts +0 -21
- package/src/api/com/atproto/admin/enableAccountInvites.ts +0 -18
- package/src/api/com/atproto/admin/getAccountInfo.ts +0 -32
- package/src/api/com/atproto/admin/getAccountInfos.ts +0 -34
- package/src/api/com/atproto/admin/getInviteCodes.ts +0 -126
- package/src/api/com/atproto/admin/getSubjectStatus.ts +0 -76
- package/src/api/com/atproto/admin/index.ts +0 -31
- package/src/api/com/atproto/admin/sendEmail.ts +0 -47
- package/src/api/com/atproto/admin/updateAccountEmail.ts +0 -32
- package/src/api/com/atproto/admin/updateAccountHandle.ts +0 -47
- package/src/api/com/atproto/admin/updateAccountPassword.ts +0 -34
- package/src/api/com/atproto/admin/updateSubjectStatus.ts +0 -68
- package/src/api/com/atproto/admin/util.ts +0 -66
- package/src/api/com/atproto/identity/getRecommendedDidCredentials.ts +0 -50
- package/src/api/com/atproto/identity/index.ts +0 -17
- package/src/api/com/atproto/identity/requestPlcOperationSignature.ts +0 -59
- package/src/api/com/atproto/identity/resolveHandle.ts +0 -50
- package/src/api/com/atproto/identity/signPlcOperation.ts +0 -85
- package/src/api/com/atproto/identity/submitPlcOperation.ts +0 -65
- package/src/api/com/atproto/identity/updateHandle.ts +0 -66
- package/src/api/com/atproto/index.ts +0 -19
- package/src/api/com/atproto/moderation/createReport.ts +0 -41
- package/src/api/com/atproto/moderation/index.ts +0 -7
- package/src/api/com/atproto/repo/applyWrites.ts +0 -226
- package/src/api/com/atproto/repo/createRecord.ts +0 -143
- package/src/api/com/atproto/repo/deleteRecord.ts +0 -122
- package/src/api/com/atproto/repo/describeRepo.ts +0 -43
- package/src/api/com/atproto/repo/getRecord.ts +0 -40
- package/src/api/com/atproto/repo/importRepo.ts +0 -101
- package/src/api/com/atproto/repo/index.ts +0 -25
- package/src/api/com/atproto/repo/listMissingBlobs.ts +0 -29
- package/src/api/com/atproto/repo/listRecords.ts +0 -36
- package/src/api/com/atproto/repo/putRecord.ts +0 -211
- package/src/api/com/atproto/repo/uploadBlob.ts +0 -60
- package/src/api/com/atproto/server/activateAccount.ts +0 -37
- package/src/api/com/atproto/server/checkAccountStatus.ts +0 -51
- package/src/api/com/atproto/server/confirmEmail.ts +0 -39
- package/src/api/com/atproto/server/createAccount.ts +0 -327
- package/src/api/com/atproto/server/createAppPassword.ts +0 -53
- package/src/api/com/atproto/server/createInviteCode.ts +0 -38
- package/src/api/com/atproto/server/createInviteCodes.ts +0 -42
- package/src/api/com/atproto/server/createSession.ts +0 -97
- package/src/api/com/atproto/server/deactivateAccount.ts +0 -41
- package/src/api/com/atproto/server/deleteAccount.ts +0 -85
- package/src/api/com/atproto/server/deleteSession.ts +0 -23
- package/src/api/com/atproto/server/describeServer.ts +0 -29
- package/src/api/com/atproto/server/getAccountInviteCodes.ts +0 -142
- package/src/api/com/atproto/server/getServiceAuth.ts +0 -111
- package/src/api/com/atproto/server/getSession.ts +0 -80
- package/src/api/com/atproto/server/index.ts +0 -55
- package/src/api/com/atproto/server/listAppPasswords.ts +0 -45
- package/src/api/com/atproto/server/refreshSession.ts +0 -72
- package/src/api/com/atproto/server/requestAccountDelete.ts +0 -66
- package/src/api/com/atproto/server/requestEmailConfirmation.ts +0 -68
- package/src/api/com/atproto/server/requestEmailUpdate.ts +0 -86
- package/src/api/com/atproto/server/requestPasswordReset.ts +0 -52
- package/src/api/com/atproto/server/reserveSigningKey.ts +0 -15
- package/src/api/com/atproto/server/resetPassword.ts +0 -50
- package/src/api/com/atproto/server/revokeAppPassword.ts +0 -42
- package/src/api/com/atproto/server/updateEmail.ts +0 -52
- package/src/api/com/atproto/server/util.ts +0 -136
- package/src/api/com/atproto/sync/deprecated/getCheckout.ts +0 -27
- package/src/api/com/atproto/sync/deprecated/getHead.ts +0 -33
- package/src/api/com/atproto/sync/getBlob.ts +0 -61
- package/src/api/com/atproto/sync/getBlocks.ts +0 -37
- package/src/api/com/atproto/sync/getLatestCommit.ts +0 -33
- package/src/api/com/atproto/sync/getRecord.ts +0 -49
- package/src/api/com/atproto/sync/getRepo.ts +0 -75
- package/src/api/com/atproto/sync/getRepoStatus.ts +0 -34
- package/src/api/com/atproto/sync/index.ts +0 -27
- package/src/api/com/atproto/sync/listBlobs.ts +0 -33
- package/src/api/com/atproto/sync/listRepos.ts +0 -74
- package/src/api/com/atproto/sync/subscribeRepos.ts +0 -73
- package/src/api/com/atproto/sync/util.ts +0 -37
- package/src/api/com/atproto/temp/checkSignupQueue.ts +0 -34
- package/src/api/com/atproto/temp/index.ts +0 -7
- package/src/api/index.ts +0 -10
- package/src/api/proxy.ts +0 -44
- package/src/app-view.ts +0 -24
- package/src/auth-output.ts +0 -52
- package/src/auth-routes.ts +0 -64
- package/src/auth-scope.ts +0 -40
- package/src/auth-verifier.ts +0 -668
- package/src/background.ts +0 -65
- package/src/basic-routes.ts +0 -52
- package/src/bsky-app-view.ts +0 -33
- package/src/config/config.ts +0 -553
- package/src/config/env.ts +0 -167
- package/src/config/index.ts +0 -3
- package/src/config/secrets.ts +0 -54
- package/src/context.ts +0 -523
- package/src/crawlers.ts +0 -46
- package/src/db/cast.ts +0 -52
- package/src/db/db.ts +0 -140
- package/src/db/index.ts +0 -4
- package/src/db/migrator.ts +0 -40
- package/src/db/pagination.ts +0 -132
- package/src/db/tables/moderation.ts +0 -80
- package/src/db/util.ts +0 -108
- package/src/did-cache/db/index.ts +0 -21
- package/src/did-cache/db/migrations.ts +0 -17
- package/src/did-cache/db/schema.ts +0 -9
- package/src/did-cache/index.ts +0 -131
- package/src/disk-blobstore.ts +0 -172
- package/src/error.ts +0 -19
- package/src/handle/explicit-slurs.ts +0 -22
- package/src/handle/index.ts +0 -49
- package/src/handle/reserved.ts +0 -1059
- package/src/image/image-url-builder.ts +0 -16
- package/src/index.ts +0 -189
- package/src/lexicons.ts +0 -4
- package/src/logger.ts +0 -35
- package/src/mailer/index.ts +0 -111
- package/src/mailer/moderation.ts +0 -33
- package/src/mailer/templates/confirm-email.d.ts +0 -4
- package/src/mailer/templates/confirm-email.hbs +0 -158
- package/src/mailer/templates/delete-account.d.ts +0 -4
- package/src/mailer/templates/delete-account.hbs +0 -156
- package/src/mailer/templates/plc-operation.d.ts +0 -4
- package/src/mailer/templates/plc-operation.hbs +0 -153
- package/src/mailer/templates/reset-password.d.ts +0 -4
- package/src/mailer/templates/reset-password.hbs +0 -154
- package/src/mailer/templates/update-email.d.ts +0 -4
- package/src/mailer/templates/update-email.hbs +0 -153
- package/src/mailer/templates.ts +0 -17
- package/src/pipethrough.ts +0 -716
- package/src/rate-limits.ts +0 -59
- package/src/read-after-write/index.ts +0 -3
- package/src/read-after-write/types.ts +0 -35
- package/src/read-after-write/util.ts +0 -101
- package/src/read-after-write/viewer.ts +0 -290
- package/src/redis.ts +0 -25
- package/src/repo/index.ts +0 -2
- package/src/repo/prepare.ts +0 -266
- package/src/repo/types.ts +0 -65
- package/src/scripts/README.md +0 -40
- package/src/scripts/index.ts +0 -20
- package/src/scripts/publish-identity.ts +0 -60
- package/src/scripts/rebuild-repo.ts +0 -119
- package/src/scripts/rotate-keys.ts +0 -146
- package/src/scripts/sequencer-recovery/index.ts +0 -23
- package/src/scripts/sequencer-recovery/recoverer.ts +0 -297
- package/src/scripts/sequencer-recovery/recovery-db.ts +0 -65
- package/src/scripts/sequencer-recovery/repair-repos.ts +0 -49
- package/src/scripts/sequencer-recovery/user-queues.ts +0 -44
- package/src/scripts/util.ts +0 -7
- package/src/sequencer/db/index.ts +0 -21
- package/src/sequencer/db/migrations/001-init.ts +0 -35
- package/src/sequencer/db/migrations/index.ts +0 -5
- package/src/sequencer/db/schema.ts +0 -19
- package/src/sequencer/events.ts +0 -199
- package/src/sequencer/index.ts +0 -3
- package/src/sequencer/outbox.ts +0 -123
- package/src/sequencer/sequencer.ts +0 -290
- package/src/util/compression.ts +0 -16
- package/src/util/debug.ts +0 -10
- package/src/util/http.ts +0 -31
- package/src/util/types.ts +0 -7
- package/src/well-known.ts +0 -30
- package/test.env +0 -2
- package/tests/__snapshots__/takedown-appeal.test.ts.snap +0 -43
- package/tests/_oauth_client_assets_middleware.ts +0 -23
- package/tests/_puppeteer.ts +0 -147
- package/tests/_types.d.ts +0 -16
- package/tests/_util.ts +0 -191
- package/tests/account-deactivation.test.ts +0 -204
- package/tests/account-deletion.test.ts +0 -300
- package/tests/account-manager.test.ts +0 -462
- package/tests/account-migration.test.ts +0 -221
- package/tests/account-status.test.ts +0 -206
- package/tests/account.test.ts +0 -595
- package/tests/app-passwords.test.ts +0 -262
- package/tests/auth.test.ts +0 -405
- package/tests/blob-deletes.test.ts +0 -204
- package/tests/create-post.test.ts +0 -79
- package/tests/crud.test.ts +0 -1595
- package/tests/db.test.ts +0 -170
- package/tests/email-confirmation.test.ts +0 -227
- package/tests/entryway-mock.ts +0 -323
- package/tests/entryway.test.ts +0 -145
- package/tests/file-uploads.test.ts +0 -301
- package/tests/get-service-auth.test.ts +0 -81
- package/tests/handle-validation.test.ts +0 -56
- package/tests/handles.test.ts +0 -274
- package/tests/invite-codes.test.ts +0 -367
- package/tests/invites-admin.test.ts +0 -252
- package/tests/moderation.test.ts +0 -280
- package/tests/moderator-auth.test.ts +0 -177
- package/tests/oauth.test.ts +0 -334
- package/tests/plc-operations.test.ts +0 -239
- package/tests/preferences.test.ts +0 -352
- package/tests/proxied/__snapshots__/admin.test.ts.snap +0 -516
- package/tests/proxied/__snapshots__/feedgen.test.ts.snap +0 -215
- package/tests/proxied/__snapshots__/views.test.ts.snap +0 -4456
- package/tests/proxied/admin.test.ts +0 -340
- package/tests/proxied/feedgen.test.ts +0 -66
- package/tests/proxied/notif.test.ts +0 -85
- package/tests/proxied/procedures.test.ts +0 -175
- package/tests/proxied/proxy-catchall.test.ts +0 -256
- package/tests/proxied/proxy-header.test.ts +0 -239
- package/tests/proxied/proxy-oauth-aud.test.ts +0 -182
- package/tests/proxied/read-after-write.test.ts +0 -382
- package/tests/proxied/views.test.ts +0 -608
- package/tests/races.test.ts +0 -89
- package/tests/rate-limits.test.ts +0 -70
- package/tests/recovery.test.ts +0 -180
- package/tests/seeds/basic.ts +0 -165
- package/tests/seeds/follows.ts +0 -57
- package/tests/seeds/likes.ts +0 -14
- package/tests/seeds/reposts.ts +0 -18
- package/tests/seeds/thread.ts +0 -40
- package/tests/seeds/users-bulk.ts +0 -246
- package/tests/seeds/users.ts +0 -67
- package/tests/sequencer.test.ts +0 -251
- package/tests/server.test.ts +0 -151
- package/tests/sync/invertible-ops.test.ts +0 -99
- package/tests/sync/list.test.ts +0 -43
- package/tests/sync/subscribe-repos.test.ts +0 -672
- package/tests/sync/sync.test.ts +0 -316
- package/tests/takedown-appeal.test.ts +0 -166
- package/tsconfig.build.json +0 -9
- package/tsconfig.build.tsbuildinfo +0 -1
- package/tsconfig.json +0 -7
- package/tsconfig.tests.json +0 -8
|
@@ -1,672 +0,0 @@
|
|
|
1
|
-
import { WebSocket } from 'ws'
|
|
2
|
-
import { AtpAgent } from '@atproto/api'
|
|
3
|
-
import {
|
|
4
|
-
HOUR,
|
|
5
|
-
MINUTE,
|
|
6
|
-
cborDecode,
|
|
7
|
-
readFromGenerator,
|
|
8
|
-
wait,
|
|
9
|
-
} from '@atproto/common'
|
|
10
|
-
import { randomStr } from '@atproto/crypto'
|
|
11
|
-
import { SeedClient, TestNetworkNoAppView } from '@atproto/dev-env'
|
|
12
|
-
import { Cid } from '@atproto/lex-data'
|
|
13
|
-
import * as repo from '@atproto/repo'
|
|
14
|
-
import { readCar } from '@atproto/repo'
|
|
15
|
-
import type { DidString } from '@atproto/syntax'
|
|
16
|
-
import { ErrorFrame, Frame, MessageFrame, byFrame } from '@atproto/xrpc-server'
|
|
17
|
-
import { AccountStatus } from '../../src/account-manager/account-manager.js'
|
|
18
|
-
import { AppContext } from '../../src/index.js'
|
|
19
|
-
import { com } from '../../src/lexicons.js'
|
|
20
|
-
import basicSeed from '../seeds/basic.js'
|
|
21
|
-
|
|
22
|
-
describe('repo subscribe repos', () => {
|
|
23
|
-
let serverHost: string
|
|
24
|
-
|
|
25
|
-
let network: TestNetworkNoAppView
|
|
26
|
-
let ctx: AppContext
|
|
27
|
-
|
|
28
|
-
let agent: AtpAgent
|
|
29
|
-
let sc: SeedClient
|
|
30
|
-
let alice: DidString
|
|
31
|
-
let bob: DidString
|
|
32
|
-
let carol: DidString
|
|
33
|
-
let dan: DidString
|
|
34
|
-
|
|
35
|
-
beforeAll(async () => {
|
|
36
|
-
network = await TestNetworkNoAppView.create({
|
|
37
|
-
dbPostgresSchema: 'repo_subscribe_repos',
|
|
38
|
-
pds: {
|
|
39
|
-
repoBackfillLimitMs: HOUR,
|
|
40
|
-
},
|
|
41
|
-
})
|
|
42
|
-
serverHost = network.pds.url.replace('http://', '')
|
|
43
|
-
// @ts-expect-error Error due to circular dependency with the dev-env package
|
|
44
|
-
ctx = network.pds.ctx
|
|
45
|
-
agent = network.pds.getAgent()
|
|
46
|
-
sc = network.getSeedClient()
|
|
47
|
-
await basicSeed(sc)
|
|
48
|
-
alice = sc.dids.alice
|
|
49
|
-
bob = sc.dids.bob
|
|
50
|
-
carol = sc.dids.carol
|
|
51
|
-
dan = sc.dids.dan
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
afterAll(async () => {
|
|
55
|
-
await network?.close()
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
const getRepo = async (did: string): Promise<repo.VerifiedRepo> => {
|
|
59
|
-
const carRes = await agent.api.com.atproto.sync.getRepo({ did })
|
|
60
|
-
const car = await repo.readCarWithRoot(carRes.data)
|
|
61
|
-
const signingKey = await network.pds.ctx.actorStore.keypair(did)
|
|
62
|
-
return repo.verifyRepo(car.blocks, car.root, did, signingKey.did())
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const getAllEvents = (userDid: string, frames: Frame[]) => {
|
|
66
|
-
const types: unknown[] = []
|
|
67
|
-
for (const frame of frames) {
|
|
68
|
-
if (frame instanceof MessageFrame) {
|
|
69
|
-
if (
|
|
70
|
-
(frame.header.t === '#commit' &&
|
|
71
|
-
(frame.body as com.atproto.sync.subscribeRepos.Commit).repo ===
|
|
72
|
-
userDid) ||
|
|
73
|
-
(frame.header.t === '#sync' &&
|
|
74
|
-
(frame.body as com.atproto.sync.subscribeRepos.Sync).did ===
|
|
75
|
-
userDid) ||
|
|
76
|
-
(frame.header.t === '#identity' &&
|
|
77
|
-
(frame.body as com.atproto.sync.subscribeRepos.Identity).did ===
|
|
78
|
-
userDid) ||
|
|
79
|
-
(frame.header.t === '#account' &&
|
|
80
|
-
(frame.body as com.atproto.sync.subscribeRepos.Account).did ===
|
|
81
|
-
userDid)
|
|
82
|
-
) {
|
|
83
|
-
types.push(frame.body)
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
return types
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const getEventType = <T>(frames: Frame[], type: string): T[] => {
|
|
91
|
-
const evts: T[] = []
|
|
92
|
-
for (const frame of frames) {
|
|
93
|
-
if (frame instanceof MessageFrame && frame.header.t === type) {
|
|
94
|
-
evts.push(frame.body)
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
return evts
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const getSyncEvts = (
|
|
101
|
-
frames: Frame[],
|
|
102
|
-
): com.atproto.sync.subscribeRepos.Sync[] => {
|
|
103
|
-
return getEventType(frames, '#sync')
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const getAccountEvts = (
|
|
107
|
-
frames: Frame[],
|
|
108
|
-
): com.atproto.sync.subscribeRepos.Account[] => {
|
|
109
|
-
return getEventType(frames, '#account')
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const getIdentityEvts = (
|
|
113
|
-
frames: Frame[],
|
|
114
|
-
): com.atproto.sync.subscribeRepos.Identity[] => {
|
|
115
|
-
return getEventType(frames, '#identity')
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const getCommitEvents = (
|
|
119
|
-
frames: Frame[],
|
|
120
|
-
): com.atproto.sync.subscribeRepos.Commit[] => {
|
|
121
|
-
return getEventType(frames, '#commit')
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const verifyIdentityEvent = (
|
|
125
|
-
evt: com.atproto.sync.subscribeRepos.Identity,
|
|
126
|
-
did: string,
|
|
127
|
-
handle?: string,
|
|
128
|
-
) => {
|
|
129
|
-
expect(typeof evt.seq).toBe('number')
|
|
130
|
-
expect(evt.did).toBe(did)
|
|
131
|
-
expect(typeof evt.time).toBe('string')
|
|
132
|
-
expect(evt.handle).toEqual(handle)
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
const verifyAccountEvent = (
|
|
136
|
-
evt: com.atproto.sync.subscribeRepos.Account,
|
|
137
|
-
did: string,
|
|
138
|
-
active: boolean,
|
|
139
|
-
status?: AccountStatus,
|
|
140
|
-
) => {
|
|
141
|
-
expect(typeof evt.seq).toBe('number')
|
|
142
|
-
expect(evt.did).toBe(did)
|
|
143
|
-
expect(typeof evt.time).toBe('string')
|
|
144
|
-
expect(evt.active).toBe(active)
|
|
145
|
-
expect(evt.status).toBe(status)
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
const verifySyncEvent = async (
|
|
149
|
-
evt: com.atproto.sync.subscribeRepos.Sync,
|
|
150
|
-
did: string,
|
|
151
|
-
commit: Cid,
|
|
152
|
-
rev: string,
|
|
153
|
-
) => {
|
|
154
|
-
expect(typeof evt.seq).toBe('number')
|
|
155
|
-
expect(evt.did).toBe(did)
|
|
156
|
-
expect(typeof evt.time).toBe('string')
|
|
157
|
-
expect(evt.rev).toBe(rev)
|
|
158
|
-
const car = await repo.readCarWithRoot(evt.blocks)
|
|
159
|
-
expect(car.root.equals(commit)).toBe(true)
|
|
160
|
-
expect(car.blocks.size).toBe(1)
|
|
161
|
-
expect(car.blocks.has(car.root)).toBe(true)
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
const verifyCommitEvents = async (frames: Frame[]) => {
|
|
165
|
-
const forUser =
|
|
166
|
-
(user: string) => (commit: com.atproto.sync.subscribeRepos.Commit) =>
|
|
167
|
-
commit.repo === user
|
|
168
|
-
const commits = getCommitEvents(frames)
|
|
169
|
-
await verifyRepo(alice, commits.filter(forUser(alice)))
|
|
170
|
-
await verifyRepo(bob, commits.filter(forUser(bob)))
|
|
171
|
-
await verifyRepo(carol, commits.filter(forUser(carol)))
|
|
172
|
-
await verifyRepo(dan, commits.filter(forUser(dan)))
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
const verifyRepo = async (
|
|
176
|
-
did: string,
|
|
177
|
-
evts: com.atproto.sync.subscribeRepos.Commit[],
|
|
178
|
-
) => {
|
|
179
|
-
const fromRpc = await getRepo(did)
|
|
180
|
-
const contents = {} as Record<string, Record<string, Cid>>
|
|
181
|
-
const allBlocks = new repo.BlockMap()
|
|
182
|
-
for (const evt of evts) {
|
|
183
|
-
const car = await readCar(evt.blocks)
|
|
184
|
-
allBlocks.addMap(car.blocks)
|
|
185
|
-
for (const op of evt.ops) {
|
|
186
|
-
const { collection, rkey } = repo.parseDataKey(op.path)
|
|
187
|
-
if (op.action === 'delete') {
|
|
188
|
-
delete contents[collection][rkey]
|
|
189
|
-
} else {
|
|
190
|
-
if (op.cid) {
|
|
191
|
-
contents[collection] ??= {}
|
|
192
|
-
contents[collection][rkey] ??= op.cid
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
for (const write of fromRpc.creates) {
|
|
198
|
-
expect(contents[write.collection][write.rkey].equals(write.cid)).toBe(
|
|
199
|
-
true,
|
|
200
|
-
)
|
|
201
|
-
}
|
|
202
|
-
const lastCommit = evts.at(-1)?.commit
|
|
203
|
-
if (!lastCommit) {
|
|
204
|
-
throw new Error('no last commit')
|
|
205
|
-
}
|
|
206
|
-
const signingKey = await network.pds.ctx.actorStore.keypair(did)
|
|
207
|
-
const fromStream = await repo.verifyRepo(
|
|
208
|
-
allBlocks,
|
|
209
|
-
lastCommit,
|
|
210
|
-
did,
|
|
211
|
-
signingKey.did(),
|
|
212
|
-
)
|
|
213
|
-
const fromRpcOps = fromRpc.creates
|
|
214
|
-
const fromStreamOps = fromStream.creates
|
|
215
|
-
expect(fromStreamOps.length).toEqual(fromRpcOps.length)
|
|
216
|
-
for (let i = 0; i < fromRpcOps.length; i++) {
|
|
217
|
-
expect(fromStreamOps[i].collection).toEqual(fromRpcOps[i].collection)
|
|
218
|
-
expect(fromStreamOps[i].rkey).toEqual(fromRpcOps[i].rkey)
|
|
219
|
-
expect(fromStreamOps[i].cid).toEqual(fromRpcOps[i].cid)
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
const randomPost = (by: DidString) => sc.post(by, randomStr(8, 'base32'))
|
|
224
|
-
const makePosts = async () => {
|
|
225
|
-
for (let i = 0; i < 10; i++) {
|
|
226
|
-
await Promise.all([
|
|
227
|
-
randomPost(alice),
|
|
228
|
-
randomPost(bob),
|
|
229
|
-
randomPost(carol),
|
|
230
|
-
randomPost(dan),
|
|
231
|
-
])
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
const readTillCaughtUp = async <T>(
|
|
236
|
-
gen: AsyncGenerator<T>,
|
|
237
|
-
waitFor?: Promise<unknown>,
|
|
238
|
-
) => {
|
|
239
|
-
const isDone = async (evt: any) => {
|
|
240
|
-
if (evt === undefined) return false
|
|
241
|
-
if (evt instanceof ErrorFrame) return true
|
|
242
|
-
const curr = await ctx.sequencer.curr()
|
|
243
|
-
return evt.body.seq === curr
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
return readFromGenerator(gen, isDone, waitFor)
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
it('emits sync event on account creation, matching temporary commit event.', async () => {
|
|
250
|
-
const ws = new WebSocket(
|
|
251
|
-
`ws://${serverHost}/xrpc/com.atproto.sync.subscribeRepos?cursor=${-1}`,
|
|
252
|
-
)
|
|
253
|
-
|
|
254
|
-
const gen = byFrame(ws)
|
|
255
|
-
const evts = await readTillCaughtUp(gen)
|
|
256
|
-
ws.terminate()
|
|
257
|
-
|
|
258
|
-
const syncEvts = getSyncEvts(evts)
|
|
259
|
-
const commitEvts = getCommitEvents(evts).slice(0, 4)
|
|
260
|
-
expect(syncEvts.length).toBe(4)
|
|
261
|
-
|
|
262
|
-
let i = 0
|
|
263
|
-
for (const did of [alice, bob, carol, dan]) {
|
|
264
|
-
const syncEvt = syncEvts[i]
|
|
265
|
-
const commitEvt = commitEvts[i]
|
|
266
|
-
await verifySyncEvent(syncEvt, did, commitEvt.commit, commitEvt.rev)
|
|
267
|
-
i++
|
|
268
|
-
}
|
|
269
|
-
})
|
|
270
|
-
|
|
271
|
-
it('sync backfilled events', async () => {
|
|
272
|
-
const ws = new WebSocket(
|
|
273
|
-
`ws://${serverHost}/xrpc/com.atproto.sync.subscribeRepos?cursor=${-1}`,
|
|
274
|
-
)
|
|
275
|
-
|
|
276
|
-
const gen = byFrame(ws)
|
|
277
|
-
const evts = await readTillCaughtUp(gen)
|
|
278
|
-
ws.terminate()
|
|
279
|
-
|
|
280
|
-
await verifyCommitEvents(evts)
|
|
281
|
-
|
|
282
|
-
const accountEvts = getAccountEvts(evts)
|
|
283
|
-
expect(accountEvts.length).toBe(4)
|
|
284
|
-
verifyAccountEvent(accountEvts[0], alice, true)
|
|
285
|
-
verifyAccountEvent(accountEvts[1], bob, true)
|
|
286
|
-
verifyAccountEvent(accountEvts[2], carol, true)
|
|
287
|
-
verifyAccountEvent(accountEvts[3], dan, true)
|
|
288
|
-
const identityEvts = getIdentityEvts(evts)
|
|
289
|
-
expect(identityEvts.length).toBe(4)
|
|
290
|
-
verifyIdentityEvent(identityEvts[0], alice, 'alice.test')
|
|
291
|
-
verifyIdentityEvent(identityEvts[1], bob, 'bob.test')
|
|
292
|
-
verifyIdentityEvent(identityEvts[2], carol, 'carol.test')
|
|
293
|
-
verifyIdentityEvent(identityEvts[3], dan, 'dan.test')
|
|
294
|
-
})
|
|
295
|
-
|
|
296
|
-
it('syncs new events', async () => {
|
|
297
|
-
const postPromise = makePosts()
|
|
298
|
-
|
|
299
|
-
const readAfterDelay = async () => {
|
|
300
|
-
await wait(200) // wait just a hair so that we catch it during cutover
|
|
301
|
-
const ws = new WebSocket(
|
|
302
|
-
`ws://${serverHost}/xrpc/com.atproto.sync.subscribeRepos?cursor=${-1}`,
|
|
303
|
-
)
|
|
304
|
-
const evts = await readTillCaughtUp(byFrame(ws), postPromise)
|
|
305
|
-
ws.terminate()
|
|
306
|
-
return evts
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
const [evts] = await Promise.all([readAfterDelay(), postPromise])
|
|
310
|
-
|
|
311
|
-
await verifyCommitEvents(evts)
|
|
312
|
-
})
|
|
313
|
-
|
|
314
|
-
it('handles no backfill', async () => {
|
|
315
|
-
const ws = new WebSocket(
|
|
316
|
-
`ws://${serverHost}/xrpc/com.atproto.sync.subscribeRepos`,
|
|
317
|
-
)
|
|
318
|
-
|
|
319
|
-
const makePostsAfterWait = async () => {
|
|
320
|
-
// give them just a second to get subscriptions set up
|
|
321
|
-
await wait(200)
|
|
322
|
-
await makePosts()
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
const postPromise = makePostsAfterWait()
|
|
326
|
-
|
|
327
|
-
const [evts] = await Promise.all([
|
|
328
|
-
readTillCaughtUp(byFrame(ws), postPromise),
|
|
329
|
-
postPromise,
|
|
330
|
-
])
|
|
331
|
-
|
|
332
|
-
ws.terminate()
|
|
333
|
-
|
|
334
|
-
expect(evts.length).toBe(40)
|
|
335
|
-
|
|
336
|
-
await wait(100) // Let cleanup occur on server
|
|
337
|
-
expect(ctx.sequencer.listeners('events').length).toEqual(0)
|
|
338
|
-
})
|
|
339
|
-
|
|
340
|
-
it('backfills only from provided cursor', async () => {
|
|
341
|
-
const seqs = await ctx.sequencer.db.db
|
|
342
|
-
.selectFrom('repo_seq')
|
|
343
|
-
.selectAll()
|
|
344
|
-
.orderBy('seq', 'asc')
|
|
345
|
-
.execute()
|
|
346
|
-
const midPoint = Math.floor(seqs.length / 2)
|
|
347
|
-
const midPointSeq = seqs[midPoint].seq
|
|
348
|
-
|
|
349
|
-
const ws = new WebSocket(
|
|
350
|
-
`ws://${serverHost}/xrpc/com.atproto.sync.subscribeRepos?cursor=${midPointSeq}`,
|
|
351
|
-
)
|
|
352
|
-
const evts = await readTillCaughtUp(byFrame(ws))
|
|
353
|
-
ws.terminate()
|
|
354
|
-
const seqSlice = seqs.slice(midPoint + 1)
|
|
355
|
-
expect(evts.length).toBe(seqSlice.length)
|
|
356
|
-
for (let i = 0; i < evts.length; i++) {
|
|
357
|
-
const evt = evts[i]
|
|
358
|
-
.body as unknown as com.atproto.sync.subscribeRepos.Commit
|
|
359
|
-
const seq = seqSlice[i]
|
|
360
|
-
const seqEvt = cborDecode(seq.event) as { commit: Cid }
|
|
361
|
-
expect(evt.time).toEqual(seq.sequencedAt)
|
|
362
|
-
expect(evt.commit.equals(seqEvt.commit)).toBeTruthy()
|
|
363
|
-
expect(evt.repo).toEqual(seq.did)
|
|
364
|
-
}
|
|
365
|
-
})
|
|
366
|
-
|
|
367
|
-
it('syncs handle changes (identity evts)', async () => {
|
|
368
|
-
await sc.updateHandle(alice, 'alice2.test')
|
|
369
|
-
await sc.updateHandle(bob, 'bob2.test')
|
|
370
|
-
await sc.updateHandle(bob, 'bob2.test') // idempotent update re-sends
|
|
371
|
-
|
|
372
|
-
const ws = new WebSocket(
|
|
373
|
-
`ws://${serverHost}/xrpc/com.atproto.sync.subscribeRepos?cursor=${-1}`,
|
|
374
|
-
)
|
|
375
|
-
|
|
376
|
-
const gen = byFrame(ws)
|
|
377
|
-
const evts = await readTillCaughtUp(gen)
|
|
378
|
-
ws.terminate()
|
|
379
|
-
|
|
380
|
-
await verifyCommitEvents(evts)
|
|
381
|
-
|
|
382
|
-
const identityEvts = getIdentityEvts(evts.slice(-3))
|
|
383
|
-
expect(identityEvts.length).toBe(3)
|
|
384
|
-
verifyIdentityEvent(identityEvts[0], alice, 'alice2.test')
|
|
385
|
-
verifyIdentityEvent(identityEvts[1], bob, 'bob2.test')
|
|
386
|
-
verifyIdentityEvent(identityEvts[2], bob, 'bob2.test')
|
|
387
|
-
})
|
|
388
|
-
|
|
389
|
-
it('resends identity events on idempotent updates', async () => {
|
|
390
|
-
const update = sc.updateHandle(bob, 'bob2.test')
|
|
391
|
-
|
|
392
|
-
const ws = new WebSocket(
|
|
393
|
-
`ws://${serverHost}/xrpc/com.atproto.sync.subscribeRepos`,
|
|
394
|
-
)
|
|
395
|
-
|
|
396
|
-
const gen = byFrame(ws)
|
|
397
|
-
const evts = await readTillCaughtUp(gen, update)
|
|
398
|
-
ws.terminate()
|
|
399
|
-
|
|
400
|
-
const identityEvts = getIdentityEvts(evts.slice(-1))
|
|
401
|
-
verifyIdentityEvent(identityEvts[0], bob, 'bob2.test')
|
|
402
|
-
})
|
|
403
|
-
|
|
404
|
-
it('syncs account events', async () => {
|
|
405
|
-
// deactivate then reactivate alice
|
|
406
|
-
await agent.api.com.atproto.server.deactivateAccount(
|
|
407
|
-
{},
|
|
408
|
-
{
|
|
409
|
-
encoding: 'application/json',
|
|
410
|
-
headers: sc.getHeaders(alice),
|
|
411
|
-
},
|
|
412
|
-
)
|
|
413
|
-
await agent.api.com.atproto.server.activateAccount(undefined, {
|
|
414
|
-
headers: sc.getHeaders(alice),
|
|
415
|
-
})
|
|
416
|
-
|
|
417
|
-
// takedown then restore bob
|
|
418
|
-
await agent.api.com.atproto.admin.updateSubjectStatus(
|
|
419
|
-
{
|
|
420
|
-
subject: {
|
|
421
|
-
$type: 'com.atproto.admin.defs#repoRef',
|
|
422
|
-
did: bob,
|
|
423
|
-
},
|
|
424
|
-
takedown: { applied: true },
|
|
425
|
-
},
|
|
426
|
-
{
|
|
427
|
-
encoding: 'application/json',
|
|
428
|
-
headers: network.pds.adminAuthHeaders(),
|
|
429
|
-
},
|
|
430
|
-
)
|
|
431
|
-
await agent.api.com.atproto.admin.updateSubjectStatus(
|
|
432
|
-
{
|
|
433
|
-
subject: {
|
|
434
|
-
$type: 'com.atproto.admin.defs#repoRef',
|
|
435
|
-
did: bob,
|
|
436
|
-
},
|
|
437
|
-
takedown: { applied: false },
|
|
438
|
-
},
|
|
439
|
-
{
|
|
440
|
-
encoding: 'application/json',
|
|
441
|
-
headers: network.pds.adminAuthHeaders(),
|
|
442
|
-
},
|
|
443
|
-
)
|
|
444
|
-
|
|
445
|
-
const ws = new WebSocket(
|
|
446
|
-
`ws://${serverHost}/xrpc/com.atproto.sync.subscribeRepos?cursor=${-1}`,
|
|
447
|
-
)
|
|
448
|
-
|
|
449
|
-
const gen = byFrame(ws)
|
|
450
|
-
const evts = await readTillCaughtUp(gen)
|
|
451
|
-
ws.terminate()
|
|
452
|
-
|
|
453
|
-
// @NOTE requires a larger slice because of over-emission on activateAccount - see note on route
|
|
454
|
-
const accountEvts = getAccountEvts(evts.slice(-6))
|
|
455
|
-
expect(accountEvts.length).toBe(4)
|
|
456
|
-
verifyAccountEvent(accountEvts[0], alice, false, AccountStatus.Deactivated)
|
|
457
|
-
verifyAccountEvent(accountEvts[1], alice, true)
|
|
458
|
-
verifyAccountEvent(accountEvts[2], bob, false, AccountStatus.Takendown)
|
|
459
|
-
verifyAccountEvent(accountEvts[3], bob, true)
|
|
460
|
-
})
|
|
461
|
-
|
|
462
|
-
it('syncs interleaved account events', async () => {
|
|
463
|
-
// deactivate -> takedown -> restore -> activate
|
|
464
|
-
// deactivate then reactivate alice
|
|
465
|
-
await agent.api.com.atproto.server.deactivateAccount(
|
|
466
|
-
{},
|
|
467
|
-
{
|
|
468
|
-
encoding: 'application/json',
|
|
469
|
-
headers: sc.getHeaders(alice),
|
|
470
|
-
},
|
|
471
|
-
)
|
|
472
|
-
await agent.api.com.atproto.admin.updateSubjectStatus(
|
|
473
|
-
{
|
|
474
|
-
subject: {
|
|
475
|
-
$type: 'com.atproto.admin.defs#repoRef',
|
|
476
|
-
did: alice,
|
|
477
|
-
},
|
|
478
|
-
takedown: { applied: true },
|
|
479
|
-
},
|
|
480
|
-
{
|
|
481
|
-
encoding: 'application/json',
|
|
482
|
-
headers: network.pds.adminAuthHeaders(),
|
|
483
|
-
},
|
|
484
|
-
)
|
|
485
|
-
await agent.api.com.atproto.admin.updateSubjectStatus(
|
|
486
|
-
{
|
|
487
|
-
subject: {
|
|
488
|
-
$type: 'com.atproto.admin.defs#repoRef',
|
|
489
|
-
did: alice,
|
|
490
|
-
},
|
|
491
|
-
takedown: { applied: false },
|
|
492
|
-
},
|
|
493
|
-
{
|
|
494
|
-
encoding: 'application/json',
|
|
495
|
-
headers: network.pds.adminAuthHeaders(),
|
|
496
|
-
},
|
|
497
|
-
)
|
|
498
|
-
await agent.api.com.atproto.server.activateAccount(undefined, {
|
|
499
|
-
headers: sc.getHeaders(alice),
|
|
500
|
-
})
|
|
501
|
-
|
|
502
|
-
const ws = new WebSocket(
|
|
503
|
-
`ws://${serverHost}/xrpc/com.atproto.sync.subscribeRepos?cursor=${-1}`,
|
|
504
|
-
)
|
|
505
|
-
|
|
506
|
-
const gen = byFrame(ws)
|
|
507
|
-
const evts = await readTillCaughtUp(gen)
|
|
508
|
-
ws.terminate()
|
|
509
|
-
|
|
510
|
-
// @NOTE requires a larger slice because of over-emission on activateAccount - see note on route
|
|
511
|
-
const accountEvts = getAccountEvts(evts.slice(-6))
|
|
512
|
-
expect(accountEvts.length).toBe(4)
|
|
513
|
-
verifyAccountEvent(accountEvts[0], alice, false, AccountStatus.Deactivated)
|
|
514
|
-
verifyAccountEvent(accountEvts[1], alice, false, AccountStatus.Takendown)
|
|
515
|
-
verifyAccountEvent(accountEvts[2], alice, false, AccountStatus.Deactivated)
|
|
516
|
-
verifyAccountEvent(accountEvts[3], alice, true)
|
|
517
|
-
})
|
|
518
|
-
|
|
519
|
-
it('emits sync event on account activation', async () => {
|
|
520
|
-
await agent.api.com.atproto.server.deactivateAccount(
|
|
521
|
-
{},
|
|
522
|
-
{
|
|
523
|
-
encoding: 'application/json',
|
|
524
|
-
headers: sc.getHeaders(alice),
|
|
525
|
-
},
|
|
526
|
-
)
|
|
527
|
-
await agent.api.com.atproto.server.activateAccount(undefined, {
|
|
528
|
-
headers: sc.getHeaders(alice),
|
|
529
|
-
})
|
|
530
|
-
|
|
531
|
-
const ws = new WebSocket(
|
|
532
|
-
`ws://${serverHost}/xrpc/com.atproto.sync.subscribeRepos?cursor=${-1}`,
|
|
533
|
-
)
|
|
534
|
-
|
|
535
|
-
const gen = byFrame(ws)
|
|
536
|
-
const evts = await readTillCaughtUp(gen)
|
|
537
|
-
ws.terminate()
|
|
538
|
-
|
|
539
|
-
const syncEvts = getSyncEvts(evts.slice(-1))
|
|
540
|
-
expect(syncEvts.length).toBe(1)
|
|
541
|
-
const root = await ctx.actorStore.read(alice, (store) =>
|
|
542
|
-
store.repo.storage.getRootDetailed(),
|
|
543
|
-
)
|
|
544
|
-
await verifySyncEvent(syncEvts[0], alice, root.cid, root.rev)
|
|
545
|
-
})
|
|
546
|
-
|
|
547
|
-
it('syncs account deletions (account evt)', async () => {
|
|
548
|
-
const baddie1 = (
|
|
549
|
-
await sc.createAccount('baddie1.test', {
|
|
550
|
-
email: 'baddie1@test.com',
|
|
551
|
-
handle: 'baddie1.test',
|
|
552
|
-
password: 'baddie1-pass',
|
|
553
|
-
})
|
|
554
|
-
).did
|
|
555
|
-
const baddie2 = (
|
|
556
|
-
await sc.createAccount('baddie2.test', {
|
|
557
|
-
email: 'baddie2@test.com',
|
|
558
|
-
handle: 'baddie2.test',
|
|
559
|
-
password: 'baddie2-pass',
|
|
560
|
-
})
|
|
561
|
-
).did
|
|
562
|
-
const deleteToken = await ctx.accountManager.createEmailToken(
|
|
563
|
-
baddie1,
|
|
564
|
-
'delete_account',
|
|
565
|
-
)
|
|
566
|
-
await agent.api.com.atproto.server.deleteAccount({
|
|
567
|
-
did: baddie1,
|
|
568
|
-
password: 'baddie1-pass',
|
|
569
|
-
token: deleteToken,
|
|
570
|
-
})
|
|
571
|
-
await agent.api.com.atproto.admin.deleteAccount(
|
|
572
|
-
{
|
|
573
|
-
did: baddie2,
|
|
574
|
-
},
|
|
575
|
-
{
|
|
576
|
-
encoding: 'application/json',
|
|
577
|
-
headers: network.pds.adminAuthHeaders(),
|
|
578
|
-
},
|
|
579
|
-
)
|
|
580
|
-
|
|
581
|
-
const ws = new WebSocket(
|
|
582
|
-
`ws://${serverHost}/xrpc/com.atproto.sync.subscribeRepos?cursor=${-1}`,
|
|
583
|
-
)
|
|
584
|
-
|
|
585
|
-
const gen = byFrame(ws)
|
|
586
|
-
const evts = await readTillCaughtUp(gen)
|
|
587
|
-
ws.terminate()
|
|
588
|
-
|
|
589
|
-
const accountEvts = getAccountEvts(evts.slice(-2))
|
|
590
|
-
expect(accountEvts.length).toBe(2)
|
|
591
|
-
verifyAccountEvent(accountEvts[0], baddie1, false, AccountStatus.Deleted)
|
|
592
|
-
verifyAccountEvent(accountEvts[1], baddie2, false, AccountStatus.Deleted)
|
|
593
|
-
})
|
|
594
|
-
|
|
595
|
-
it('account deletions invalidate all seq ops', async () => {
|
|
596
|
-
const baddie3 = (
|
|
597
|
-
await sc.createAccount('baddie3', {
|
|
598
|
-
email: 'baddie3@test.com',
|
|
599
|
-
handle: 'baddie3.test',
|
|
600
|
-
password: 'baddie3-pass',
|
|
601
|
-
})
|
|
602
|
-
).did
|
|
603
|
-
|
|
604
|
-
await randomPost(baddie3)
|
|
605
|
-
await sc.updateHandle(baddie3, 'baddie3-update.test')
|
|
606
|
-
const token = await network.pds.ctx.accountManager.createEmailToken(
|
|
607
|
-
baddie3,
|
|
608
|
-
'delete_account',
|
|
609
|
-
)
|
|
610
|
-
await agent.api.com.atproto.server.deleteAccount({
|
|
611
|
-
token,
|
|
612
|
-
did: baddie3,
|
|
613
|
-
password: sc.accounts[baddie3].password,
|
|
614
|
-
})
|
|
615
|
-
|
|
616
|
-
const ws = new WebSocket(
|
|
617
|
-
`ws://${serverHost}/xrpc/com.atproto.sync.subscribeRepos?cursor=${-1}`,
|
|
618
|
-
)
|
|
619
|
-
|
|
620
|
-
const gen = byFrame(ws)
|
|
621
|
-
const evts = await readTillCaughtUp(gen)
|
|
622
|
-
ws.terminate()
|
|
623
|
-
|
|
624
|
-
const didEvts = getAllEvents(baddie3, evts)
|
|
625
|
-
expect(didEvts.length).toBe(1)
|
|
626
|
-
verifyAccountEvent(
|
|
627
|
-
didEvts[0] as com.atproto.sync.subscribeRepos.Account,
|
|
628
|
-
baddie3,
|
|
629
|
-
false,
|
|
630
|
-
AccountStatus.Deleted,
|
|
631
|
-
)
|
|
632
|
-
})
|
|
633
|
-
|
|
634
|
-
it('sends info frame on out of date cursor', async () => {
|
|
635
|
-
// we rewrite the sequenceAt time for existing seqs to be past the backfill cutoff
|
|
636
|
-
// then we create some new posts
|
|
637
|
-
const overAnHourAgo = new Date(Date.now() - HOUR - MINUTE).toISOString()
|
|
638
|
-
await ctx.sequencer.db.db
|
|
639
|
-
.updateTable('repo_seq')
|
|
640
|
-
.set({ sequencedAt: overAnHourAgo })
|
|
641
|
-
.execute()
|
|
642
|
-
|
|
643
|
-
await makePosts()
|
|
644
|
-
|
|
645
|
-
const ws = new WebSocket(
|
|
646
|
-
`ws://${serverHost}/xrpc/com.atproto.sync.subscribeRepos?cursor=${-1}`,
|
|
647
|
-
)
|
|
648
|
-
const [info, ...evts] = await readTillCaughtUp(byFrame(ws))
|
|
649
|
-
ws.terminate()
|
|
650
|
-
|
|
651
|
-
if (!(info instanceof MessageFrame)) {
|
|
652
|
-
throw new Error('Expected first frame to be a MessageFrame')
|
|
653
|
-
}
|
|
654
|
-
expect(info.header.t).toBe('#info')
|
|
655
|
-
const body = info.body as Record<string, unknown>
|
|
656
|
-
expect(body.name).toEqual('OutdatedCursor')
|
|
657
|
-
expect(evts.length).toBe(40)
|
|
658
|
-
})
|
|
659
|
-
|
|
660
|
-
it('errors on future cursor', async () => {
|
|
661
|
-
const ws = new WebSocket(
|
|
662
|
-
`ws://${serverHost}/xrpc/com.atproto.sync.subscribeRepos?cursor=${100000}`,
|
|
663
|
-
)
|
|
664
|
-
const frames = await readTillCaughtUp(byFrame(ws))
|
|
665
|
-
ws.terminate()
|
|
666
|
-
expect(frames.length).toBe(1)
|
|
667
|
-
if (!(frames[0] instanceof ErrorFrame)) {
|
|
668
|
-
throw new Error('Expected ErrorFrame')
|
|
669
|
-
}
|
|
670
|
-
expect(frames[0].body.error).toBe('FutureCursor')
|
|
671
|
-
})
|
|
672
|
-
})
|