Skip to content

Commit efe7c1d

Browse files
committed
Fix possible race condition on update of vault key
1 parent a24f8cb commit efe7c1d

File tree

1 file changed

+16
-18
lines changed

1 file changed

+16
-18
lines changed

api/resolvers/vault.js

+16-18
Original file line numberDiff line numberDiff line change
@@ -25,39 +25,37 @@ export default {
2525
updateVaultKey: async (parent, { entries, hash }, { me, models }) => {
2626
if (!me) throw new GqlAuthenticationError()
2727
if (!hash) throw new GqlInputError('hash required')
28-
const txs = []
2928

3029
const { vaultKeyHash: oldKeyHash } = await models.user.findUnique({ where: { id: me.id } })
3130
if (oldKeyHash) {
32-
if (oldKeyHash !== hash) {
33-
throw new GqlInputError('vault key already set', E_VAULT_KEY_EXISTS)
34-
} else {
31+
if (oldKeyHash === hash) {
3532
return true
3633
}
37-
} else {
38-
txs.push(models.user.update({
39-
where: { id: me.id },
40-
data: { vaultKeyHash: hash }
41-
}))
34+
throw new GqlInputError('vault key already set', E_VAULT_KEY_EXISTS)
4235
}
4336

44-
const wallets = await models.wallet.findMany({ where: { userId: me.id } })
45-
for (const wallet of wallets) {
46-
const def = getWalletByType(wallet.type)
47-
txs.push(
48-
models.wallet.update({
37+
return await models.$transaction(async tx => {
38+
const wallets = await tx.wallet.findMany({ where: { userId: me.id } })
39+
for (const wallet of wallets) {
40+
const def = getWalletByType(wallet.type)
41+
await tx.wallet.update({
4942
where: { id: wallet.id },
5043
data: {
5144
[def.walletField]: {
5245
update: vaultPrismaFragments.upsert({ ...wallet, vaultEntries: entries })
5346
}
5447
}
5548
})
56-
)
57-
}
49+
}
5850

59-
await models.$transaction(txs)
60-
return true
51+
// optimistic concurrency control: make sure the user's vault key didn't change while we were updating the wallets
52+
await tx.user.update({
53+
where: { id: me.id, vaultKeyHash: oldKeyHash },
54+
data: { vaultKeyHash: hash }
55+
})
56+
57+
return true
58+
})
6159
},
6260
clearVault: async (parent, args, { me, models }) => {
6361
if (!me) throw new GqlAuthenticationError()

0 commit comments

Comments
 (0)