Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Account Manager #1769

Merged
merged 29 commits into from
Nov 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
fe3f815
wip
dholms Oct 25, 2023
ab8d346
wrap up accoutn manager
dholms Oct 25, 2023
db8abbb
tidy
dholms Oct 25, 2023
aa2e7fb
tidy
dholms Oct 25, 2023
c04a28b
fix tests
dholms Oct 25, 2023
6861596
fix disabled codes
dholms Oct 26, 2023
91591fd
fix appview tests
dholms Oct 26, 2023
135553c
add note
dholms Oct 26, 2023
93dfedc
Merge branch 'pds-sqlite-refactor' into account-manager
dholms Oct 26, 2023
9212f81
tidy account manager getDb
dholms Oct 26, 2023
5c418c1
Merge branch 'pds-sqlite-refactor' into account-manager
dholms Oct 26, 2023
32b3277
Merge branch 'pds-sqlite-refactor' into account-manager
dholms Oct 26, 2023
fc47e45
merge
dholms Oct 26, 2023
0d7d228
split account table into two
dholms Oct 30, 2023
e9c2464
merge
dholms Oct 30, 2023
89fba41
Merge branch 'pds-sqlite-refactor' into account-manager
dholms Oct 30, 2023
2cb2757
merge
dholms Oct 31, 2023
24cec0c
Merge branch 'pds-sqlite-refactor' into account-manager
dholms Oct 31, 2023
55c76bf
tidy delete tokens
dholms Oct 31, 2023
7e879f9
tidy account getters
dholms Oct 31, 2023
f292090
tidy
dholms Oct 31, 2023
2f2c7ee
Merge branch 'pds-sqlite-refactor' into account-manager
dholms Oct 31, 2023
be67392
handle racing refreshes
dholms Oct 31, 2023
889adf6
clean up actor store on create account failure
dholms Nov 1, 2023
a15a165
Merge branch 'pds-sqlite-refactor' into account-manager
dholms Nov 1, 2023
252a529
prevent invite code races on createAccount
dholms Nov 1, 2023
698cc20
rm note
dholms Nov 1, 2023
693d66f
add back in race protection on getAccountInviteCodes
dholms Nov 1, 2023
09f8837
merge
dholms Nov 1, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions packages/bsky/tests/handle-invalidation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,7 @@ describe('handle invalidation', () => {
it('deals with handle contention', async () => {
await backdateIndexedAt(bob)
// update alices handle so that the pds will let bob take her old handle
await network.pds.ctx.db.db
.updateTable('account')
.where('did', '=', alice)
.set({ handle: 'not-alice.test' })
.execute()
await network.pds.ctx.accountManager.updateHandle(alice, 'not-alice.test')

await pdsAgent.api.com.atproto.identity.updateHandle(
{
Expand Down
24 changes: 11 additions & 13 deletions packages/bsky/tests/indexing.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,8 @@ describe('indexing', () => {

it('skips invalid records.', async () => {
const { db, services } = network.bsky.indexer.ctx
const { db: pdsDb, services: pdsServices } = network.pds.ctx
const { accountManager } = network.pds.ctx
// const { db: pdsDb, services: pdsServices } = network.pds.ctx
// Create a good and a bad post record
const writes = await Promise.all([
pdsRepo.prepareCreate({
Expand All @@ -517,9 +518,11 @@ describe('indexing', () => {
sc.dids.alice,
(store) => store.repo.processWrites(writes),
)
await pdsServices
.account(pdsDb)
.updateRepoRoot(sc.dids.alice, writeCommit.cid, writeCommit.rev)
await accountManager.updateRepoRoot(
sc.dids.alice,
writeCommit.cid,
writeCommit.rev,
)
await network.pds.ctx.sequencer.sequenceCommit(
sc.dids.alice,
writeCommit,
Expand Down Expand Up @@ -652,15 +655,10 @@ describe('indexing', () => {
)
await expect(getProfileBefore).resolves.toBeDefined()
// Delete account on pds
await pdsAgent.api.com.atproto.server.requestAccountDelete(undefined, {
headers: sc.getHeaders(alice),
})
const { token } = await network.pds.ctx.db.db
.selectFrom('email_token')
.selectAll()
.where('purpose', '=', 'delete_account')
.where('did', '=', alice)
.executeTakeFirstOrThrow()
const token = await network.pds.ctx.accountManager.createEmailToken(
alice,
'delete_account',
)
await pdsAgent.api.com.atproto.server.deleteAccount({
token,
did: alice,
Expand Down
1 change: 1 addition & 0 deletions packages/dev-env/src/const.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export const ADMIN_PASSWORD = 'admin-pass'
export const MOD_PASSWORD = 'mod-pass'
export const TRIAGE_PASSWORD = 'triage-pass'
export const JWT_SECRET = 'jwt-secret'
19 changes: 11 additions & 8 deletions packages/dev-env/src/pds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@ import fs from 'node:fs/promises'
import getPort from 'get-port'
import * as ui8 from 'uint8arrays'
import * as pds from '@atproto/pds'
import { getMigrator } from '@atproto/pds/src/service-db'
import { Secp256k1Keypair, randomStr } from '@atproto/crypto'
import { AtpAgent } from '@atproto/api'
import { PdsConfig } from './types'
import { ADMIN_PASSWORD, MOD_PASSWORD, TRIAGE_PASSWORD } from './const'
import {
ADMIN_PASSWORD,
JWT_SECRET,
MOD_PASSWORD,
TRIAGE_PASSWORD,
} from './const'

export class TestPds {
constructor(
Expand Down Expand Up @@ -37,7 +41,7 @@ export class TestPds {
adminPassword: ADMIN_PASSWORD,
moderatorPassword: MOD_PASSWORD,
triagePassword: TRIAGE_PASSWORD,
jwtSecret: 'jwt-secret',
jwtSecret: JWT_SECRET,
serviceHandleDomains: ['.test'],
bskyAppViewUrl: 'https://appview.invalid',
bskyAppViewDid: 'did:example:invalid',
Expand All @@ -51,11 +55,6 @@ export class TestPds {

const server = await pds.PDS.create(cfg, secrets)

// Separate migration db on postgres in case migration changes some
// connection state that we need in the tests, e.g. "alter database ... set ..."
const migrator = getMigrator(server.ctx.db)
await migrator.migrateToLatestOrThrow()

await server.start()

return new TestPds(url, port, server)
Expand Down Expand Up @@ -88,6 +87,10 @@ export class TestPds {
}
}

jwtSecret() {
return JWT_SECRET
}

async processAll() {
await this.ctx.backgroundQueue.processAll()
}
Expand Down
15 changes: 15 additions & 0 deletions packages/pds/src/account-manager/db/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Database, Migrator } from '../../db'
import { DatabaseSchema } from './schema'
import migrations from './migrations'

export * from './schema'

export type AccountDb = Database<DatabaseSchema>

export const getDb = (location: string): AccountDb => {
return Database.sqlite(location)
}

export const getMigrator = (db: AccountDb) => {
return new Migrator(db.db, migrations)
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,32 +56,37 @@ export async function up(db: Kysely<unknown>): Promise<void> {
.execute()

await db.schema
.createTable('account')
.createTable('actor')
.addColumn('did', 'varchar', (col) => col.primaryKey())
.addColumn('handle', 'varchar')
.addColumn('email', 'varchar', (col) => col.notNull())
.addColumn('passwordScrypt', 'varchar', (col) => col.notNull())
.addColumn('createdAt', 'varchar', (col) => col.notNull())
.addColumn('emailConfirmedAt', 'varchar')
.addColumn('invitesDisabled', 'int2', (col) => col.notNull().defaultTo(0))
.addColumn('takedownRef', 'varchar')
.execute()
await db.schema
.createIndex(`account_email_lower_idx`)
.createIndex(`actor_handle_lower_idx`)
.unique()
.on('account')
.expression(sql`lower("email")`)
.on('actor')
.expression(sql`lower("handle")`)
.execute()
await db.schema
.createIndex(`account_handle_lower_idx`)
.unique()
.on('account')
.expression(sql`lower("handle")`)
.createIndex('actor_cursor_idx')
.on('actor')
.columns(['createdAt', 'did'])
.execute()

await db.schema
.createIndex('account_cursor_idx')
.createTable('account')
.addColumn('did', 'varchar', (col) => col.primaryKey())
.addColumn('email', 'varchar', (col) => col.notNull())
.addColumn('passwordScrypt', 'varchar', (col) => col.notNull())
.addColumn('emailConfirmedAt', 'varchar')
.addColumn('invitesDisabled', 'int2', (col) => col.notNull().defaultTo(0))
.execute()
await db.schema
.createIndex(`account_email_lower_idx`)
.unique()
.on('account')
.columns(['createdAt', 'did'])
.expression(sql`lower("email")`)
.execute()

await db.schema
Expand All @@ -101,6 +106,7 @@ export async function up(db: Kysely<unknown>): Promise<void> {
export async function down(db: Kysely<unknown>): Promise<void> {
await db.schema.dropTable('email_token').execute()
await db.schema.dropTable('account').execute()
await db.schema.dropTable('actor').execute()
await db.schema.dropTable('repo_root').execute()
await db.schema.dropTable('refresh_token').execute()
await db.schema.dropTable('invite_code_use').execute()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,10 @@ import { Generated, Selectable } from 'kysely'

export interface Account {
did: string
handle: string | null
email: string
passwordScrypt: string
createdAt: string
emailConfirmedAt: string | null
invitesDisabled: Generated<0 | 1>
takedownRef: string | null
}

export type AccountEntry = Selectable<Account>
Expand Down
14 changes: 14 additions & 0 deletions packages/pds/src/account-manager/db/schema/actor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Selectable } from 'kysely'

export interface Actor {
did: string
handle: string | null
createdAt: string
takedownRef: string | null
}

export type ActorEntry = Selectable<Actor>

export const tableName = 'actor'

export type PartialDB = { [tableName]: Actor }
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import * as actor from './actor'
import * as account from './account'
import * as repoRoot from './repo-root'
import * as refreshToken from './refresh-token'
import * as appPassword from './app-password'
import * as inviteCode from './invite-code'
import * as emailToken from './email-token'

export type DatabaseSchema = account.PartialDB &
export type DatabaseSchema = actor.PartialDB &
account.PartialDB &
refreshToken.PartialDB &
appPassword.PartialDB &
repoRoot.PartialDB &
inviteCode.PartialDB &
emailToken.PartialDB

export type { Actor, ActorEntry } from './actor'
export type { Account, AccountEntry } from './account'
export type { RepoRoot } from './repo-root'
export type { RefreshToken } from './refresh-token'
Expand Down
Loading
Loading