fix(syncing-server): race condition when adding admin user to newly created shared vault (#688)
This commit is contained in:
parent
a1fe15f7a9
commit
3bd1547ce3
6 changed files with 36 additions and 6 deletions
|
@ -19,7 +19,8 @@
|
|||
"publish": "lerna publish from-git --yes --no-verify-access --loglevel verbose",
|
||||
"postversion": "./scripts/push-tags-one-by-one.sh",
|
||||
"upgrade:snjs": "yarn workspaces foreach --verbose run upgrade:snjs",
|
||||
"e2e": "yarn build packages/home-server && PORT=3123 yarn workspace @standardnotes/home-server start"
|
||||
"e2e": "yarn build packages/home-server && PORT=3123 yarn workspace @standardnotes/home-server start",
|
||||
"start": "yarn build packages/home-server && yarn workspace @standardnotes/home-server start"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^17.0.2",
|
||||
|
|
|
@ -115,4 +115,20 @@ describe('AddUserToSharedVault', () => {
|
|||
expect(result.isFailed()).toBe(false)
|
||||
expect(sharedVaultUserRepository.save).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should add a user to a shared vault and skip checking if shared vault exists to avoid race conditions', async () => {
|
||||
sharedVaultRepository.findByUuid = jest.fn().mockResolvedValueOnce(null)
|
||||
|
||||
const useCase = createUseCase()
|
||||
|
||||
const result = await useCase.execute({
|
||||
sharedVaultUuid: validUuid,
|
||||
userUuid: validUuid,
|
||||
permission: 'read',
|
||||
skipSharedVaultExistenceCheck: true,
|
||||
})
|
||||
|
||||
expect(result.isFailed()).toBe(false)
|
||||
expect(sharedVaultUserRepository.save).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
|
|
@ -20,9 +20,11 @@ export class AddUserToSharedVault implements UseCaseInterface<SharedVaultUser> {
|
|||
}
|
||||
const sharedVaultUuid = sharedVaultUuidOrError.getValue()
|
||||
|
||||
const sharedVault = await this.sharedVaultRepository.findByUuid(sharedVaultUuid)
|
||||
if (!sharedVault) {
|
||||
return Result.fail('Attempting to add a shared vault user to a non-existent shared vault')
|
||||
if (!dto.skipSharedVaultExistenceCheck) {
|
||||
const sharedVault = await this.sharedVaultRepository.findByUuid(sharedVaultUuid)
|
||||
if (!sharedVault) {
|
||||
return Result.fail('Attempting to add a shared vault user to a non-existent shared vault')
|
||||
}
|
||||
}
|
||||
|
||||
const userUuidOrError = Uuid.create(dto.userUuid)
|
||||
|
|
|
@ -2,4 +2,5 @@ export interface AddUserToSharedVaultDTO {
|
|||
sharedVaultUuid: string
|
||||
userUuid: string
|
||||
permission: string
|
||||
skipSharedVaultExistenceCheck?: boolean
|
||||
}
|
||||
|
|
|
@ -93,6 +93,7 @@ describe('CreateSharedVault', () => {
|
|||
sharedVaultUuid: expect.any(String),
|
||||
userUuid: '00000000-0000-0000-0000-000000000000',
|
||||
permission: 'admin',
|
||||
skipSharedVaultExistenceCheck: true,
|
||||
})
|
||||
expect(sharedVaultRepository.save).toHaveBeenCalled()
|
||||
})
|
||||
|
|
|
@ -1,4 +1,12 @@
|
|||
import { Result, RoleName, Timestamps, UseCaseInterface, Uuid, Validator } from '@standardnotes/domain-core'
|
||||
import {
|
||||
Result,
|
||||
RoleName,
|
||||
SharedVaultUserPermission,
|
||||
Timestamps,
|
||||
UseCaseInterface,
|
||||
Uuid,
|
||||
Validator,
|
||||
} from '@standardnotes/domain-core'
|
||||
import { CreateSharedVaultResult } from './CreateSharedVaultResult'
|
||||
import { CreateSharedVaultDTO } from './CreateSharedVaultDTO'
|
||||
import { TimerInterface } from '@standardnotes/time'
|
||||
|
@ -56,7 +64,8 @@ export class CreateSharedVault implements UseCaseInterface<CreateSharedVaultResu
|
|||
const sharedVaultUserOrError = await this.addUserToSharedVault.execute({
|
||||
sharedVaultUuid: sharedVault.id.toString(),
|
||||
userUuid: dto.userUuid,
|
||||
permission: 'admin',
|
||||
permission: SharedVaultUserPermission.PERMISSIONS.Admin,
|
||||
skipSharedVaultExistenceCheck: true,
|
||||
})
|
||||
if (sharedVaultUserOrError.isFailed()) {
|
||||
return Result.fail(sharedVaultUserOrError.getError())
|
||||
|
|
Loading…
Reference in a new issue