Skip to content

Commit

Permalink
Provide proper error for updating to an email that's already in use (#…
Browse files Browse the repository at this point in the history
…1770)

provide proper error for updating to an email already in use
  • Loading branch information
devinivy authored Nov 21, 2023
1 parent b532c50 commit f232371
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 9 deletions.
17 changes: 14 additions & 3 deletions packages/pds/src/api/com/atproto/server/updateEmail.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import disposable from 'disposable-email'
import { InvalidRequestError } from '@atproto/xrpc-server'
import { Server } from '../../../../lexicon'
import AppContext from '../../../../context'
import { InvalidRequestError } from '@atproto/xrpc-server'
import disposable from 'disposable-email'
import { UserAlreadyExistsError } from '../../../../services/account'

export default function (server: Server, ctx: AppContext) {
server.com.atproto.server.updateEmail({
Expand Down Expand Up @@ -38,7 +39,17 @@ export default function (server: Server, ctx: AppContext) {
await accntSrvce.deleteEmailToken(did, 'update_email')
}
if (user.email !== email) {
await accntSrvce.updateEmail(did, email)
try {
await accntSrvce.updateEmail(did, email)
} catch (err) {
if (err instanceof UserAlreadyExistsError) {
throw new InvalidRequestError(
'This email address is already in use, please use a different email.',
)
} else {
throw err
}
}
}
})
},
Expand Down
8 changes: 8 additions & 0 deletions packages/pds/src/db/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,11 @@ export const dummyDialect = {
export type DbRef = RawBuilder | ReturnType<DynamicModule['ref']>

export type AnyQb = SelectQueryBuilder<any, any, any>

export const isErrUniqueViolation = (err: unknown) => {
const code = err?.['code']
return (
code === '23505' || // postgres, see https://www.postgresql.org/docs/current/errcodes-appendix.html
code === 'SQLITE_CONSTRAINT_UNIQUE' // sqlite, see https://www.sqlite.org/rescode.html#constraint_unique
)
}
24 changes: 18 additions & 6 deletions packages/pds/src/services/account/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ import * as scrypt from '../../db/scrypt'
import { UserAccountEntry } from '../../db/tables/user-account'
import { DidHandle } from '../../db/tables/did-handle'
import { RepoRoot } from '../../db/tables/repo-root'
import { countAll, notSoftDeletedClause } from '../../db/util'
import {
countAll,
isErrUniqueViolation,
notSoftDeletedClause,
} from '../../db/util'
import { paginate, TimeCidKeyset } from '../../db/pagination'
import * as sequencer from '../../sequencer'
import { AppPassword } from '../../lexicon/types/com/atproto/server/createAppPassword'
Expand Down Expand Up @@ -189,11 +193,19 @@ export class AccountService {
}

async updateEmail(did: string, email: string) {
await this.db.db
.updateTable('user_account')
.set({ email: email.toLowerCase(), emailConfirmedAt: null })
.where('did', '=', did)
.executeTakeFirst()
try {
await this.db.db
.updateTable('user_account')
.set({ email: email.toLowerCase(), emailConfirmedAt: null })
.where('did', '=', did)
.executeTakeFirst()
} catch (err) {
if (isErrUniqueViolation(err)) {
throw new UserAlreadyExistsError()
} else {
throw err
}
}
}

async updateUserPassword(did: string, password: string) {
Expand Down
13 changes: 13 additions & 0 deletions packages/pds/tests/email-confirmation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,19 @@ describe('email confirmation', () => {
)
})

it('fails email update with in-use email', async () => {
const attempt = agent.api.com.atproto.server.updateEmail(
{
email: '[email protected]',
token: updateToken,
},
{ headers: sc.getHeaders(alice.did), encoding: 'application/json' },
)
await expect(attempt).rejects.toThrow(
'This email address is already in use, please use a different email.',
)
})

it('updates email', async () => {
await agent.api.com.atproto.server.updateEmail(
{
Expand Down

0 comments on commit f232371

Please sign in to comment.