diff --git a/packages/syncing-server/src/Domain/SharedVault/User/SharedVaultUserPermission.ts b/packages/syncing-server/src/Domain/SharedVault/User/SharedVaultUserPermission.ts index 53989d7ae..969647744 100644 --- a/packages/syncing-server/src/Domain/SharedVault/User/SharedVaultUserPermission.ts +++ b/packages/syncing-server/src/Domain/SharedVault/User/SharedVaultUserPermission.ts @@ -3,6 +3,12 @@ import { Result, ValueObject } from '@standardnotes/domain-core' import { SharedVaultUserPermissionProps } from './SharedVaultUserPermissionProps' export class SharedVaultUserPermission extends ValueObject { + static readonly PERMISSIONS = { + Read: 'read', + Write: 'write', + Admin: 'admin', + } + get value(): string { return this.props.value } @@ -12,7 +18,8 @@ export class SharedVaultUserPermission extends ValueObject { - if (!['read', 'write', 'admin'].includes(sharedVaultUserPermission)) { + const isValidPermission = Object.values(this.PERMISSIONS).includes(sharedVaultUserPermission) + if (!isValidPermission) { return Result.fail(`Invalid shared vault user permission ${sharedVaultUserPermission}`) } else { return Result.ok(new SharedVaultUserPermission({ value: sharedVaultUserPermission })) diff --git a/packages/syncing-server/src/Domain/SharedVault/User/SharedVaultUserRepositoryInterface.ts b/packages/syncing-server/src/Domain/SharedVault/User/SharedVaultUserRepositoryInterface.ts index fe2135d84..be85a8460 100644 --- a/packages/syncing-server/src/Domain/SharedVault/User/SharedVaultUserRepositoryInterface.ts +++ b/packages/syncing-server/src/Domain/SharedVault/User/SharedVaultUserRepositoryInterface.ts @@ -6,4 +6,5 @@ export interface SharedVaultUserRepositoryInterface { findByUuid(sharedVaultUserUuid: Uuid): Promise save(sharedVaultUser: SharedVaultUser): Promise remove(sharedVault: SharedVaultUser): Promise + findByUserUuidAndSharedVaultUuid(dto: { userUuid: Uuid; sharedVaultUuid: Uuid }): Promise } diff --git a/packages/syncing-server/src/Domain/UseCase/CreateSharedVaultFileValetToken/CreateSharedVaultFileValetToken.spec.ts b/packages/syncing-server/src/Domain/UseCase/CreateSharedVaultFileValetToken/CreateSharedVaultFileValetToken.spec.ts new file mode 100644 index 000000000..389b9ecae --- /dev/null +++ b/packages/syncing-server/src/Domain/UseCase/CreateSharedVaultFileValetToken/CreateSharedVaultFileValetToken.spec.ts @@ -0,0 +1,363 @@ +import { SharedVaultValetTokenData, TokenEncoderInterface, ValetTokenOperation } from '@standardnotes/security' +import { SharedVaultRepositoryInterface } from '../../SharedVault/SharedVaultRepositoryInterface' +import { SharedVaultUserRepositoryInterface } from '../../SharedVault/User/SharedVaultUserRepositoryInterface' +import { CreateSharedVaultFileValetToken } from './CreateSharedVaultFileValetToken' +import { SharedVault } from '../../SharedVault/SharedVault' +import { SharedVaultUser } from '../../SharedVault/User/SharedVaultUser' +import { SharedVaultUserPermission } from '../../SharedVault/User/SharedVaultUserPermission' +import { Timestamps, Uuid } from '@standardnotes/domain-core' + +describe('CreateSharedVaultFileValetToken', () => { + let sharedVaultRepository: SharedVaultRepositoryInterface + let sharedVaultUserRepository: SharedVaultUserRepositoryInterface + let tokenEncoder: TokenEncoderInterface + const valetTokenTTL = 3600 + let sharedVault: SharedVault + let sharedVaultUser: SharedVaultUser + + const createUseCase = () => + new CreateSharedVaultFileValetToken(sharedVaultRepository, sharedVaultUserRepository, tokenEncoder, valetTokenTTL) + + beforeEach(() => { + sharedVault = SharedVault.create({ + fileUploadBytesLimit: 100, + fileUploadBytesUsed: 2, + userUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(), + timestamps: Timestamps.create(123, 123).getValue(), + }).getValue() + + sharedVaultRepository = {} as jest.Mocked + sharedVaultRepository.findByUuid = jest.fn().mockResolvedValue(sharedVault) + + sharedVaultUser = SharedVaultUser.create({ + permission: SharedVaultUserPermission.create(SharedVaultUserPermission.PERMISSIONS.Read).getValue(), + sharedVaultUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(), + userUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(), + timestamps: Timestamps.create(123, 123).getValue(), + }).getValue() + + sharedVaultUserRepository = {} as jest.Mocked + sharedVaultUserRepository.findByUserUuidAndSharedVaultUuid = jest.fn().mockResolvedValue(sharedVaultUser) + + tokenEncoder = {} as jest.Mocked> + tokenEncoder.encodeExpirableToken = jest.fn().mockReturnValue('encoded-token') + }) + + it('should return error when shared vault uuid is invalid', async () => { + const useCase = createUseCase() + const result = await useCase.execute({ + userUuid: '00000000-0000-0000-0000-000000000000', + sharedVaultUuid: 'invalid-uuid', + remoteIdentifier: 'remote-identifier', + operation: ValetTokenOperation.Read, + }) + + expect(result.isFailed()).toBe(true) + expect(result.getError()).toBe('Given value is not a valid uuid: invalid-uuid') + }) + + it('should return error when user uuid is invalid', async () => { + const useCase = createUseCase() + const result = await useCase.execute({ + userUuid: 'invalid-uuid', + sharedVaultUuid: '00000000-0000-0000-0000-000000000000', + remoteIdentifier: 'remote-identifier', + operation: ValetTokenOperation.Read, + }) + + expect(result.isFailed()).toBe(true) + expect(result.getError()).toBe('Given value is not a valid uuid: invalid-uuid') + }) + + it('should return error when shared vault is not found', async () => { + sharedVaultRepository.findByUuid = jest.fn().mockResolvedValue(null) + + const useCase = createUseCase() + const result = await useCase.execute({ + userUuid: '00000000-0000-0000-0000-000000000000', + sharedVaultUuid: '00000000-0000-0000-0000-000000000000', + remoteIdentifier: 'remote-identifier', + operation: ValetTokenOperation.Read, + }) + + expect(result.isFailed()).toBe(true) + expect(result.getError()).toBe('Shared vault not found') + }) + + it('should return error when shared vault user is not found', async () => { + sharedVaultUserRepository.findByUserUuidAndSharedVaultUuid = jest.fn().mockResolvedValue(null) + + const useCase = createUseCase() + const result = await useCase.execute({ + userUuid: '00000000-0000-0000-0000-000000000000', + sharedVaultUuid: '00000000-0000-0000-0000-000000000000', + remoteIdentifier: 'remote-identifier', + operation: ValetTokenOperation.Read, + }) + + expect(result.isFailed()).toBe(true) + expect(result.getError()).toBe('Shared vault user not found') + }) + + it('should return error when shared vault user does not have permission', async () => { + const useCase = createUseCase() + const result = await useCase.execute({ + userUuid: '00000000-0000-0000-0000-000000000000', + sharedVaultUuid: '00000000-0000-0000-0000-000000000000', + remoteIdentifier: 'remote-identifier', + operation: ValetTokenOperation.Write, + }) + + expect(result.isFailed()).toBe(true) + expect(result.getError()).toBe('User does not have permission to perform this operation') + }) + + it('should create a shared vault file valet token', async () => { + sharedVaultUser = SharedVaultUser.create({ + permission: SharedVaultUserPermission.create(SharedVaultUserPermission.PERMISSIONS.Write).getValue(), + sharedVaultUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(), + userUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(), + timestamps: Timestamps.create(123, 123).getValue(), + }).getValue() + sharedVaultUserRepository.findByUserUuidAndSharedVaultUuid = jest.fn().mockResolvedValue(sharedVaultUser) + + const useCase = createUseCase() + const result = await useCase.execute({ + userUuid: '00000000-0000-0000-0000-000000000000', + sharedVaultUuid: '00000000-0000-0000-0000-000000000000', + remoteIdentifier: 'remote-identifier', + operation: ValetTokenOperation.Write, + }) + + expect(result.isFailed()).toBe(false) + expect(result.getValue()).toBe('encoded-token') + }) + + describe('move operation', () => { + beforeEach(() => { + sharedVaultUserRepository.findByUserUuidAndSharedVaultUuid = jest + .fn() + .mockReturnValueOnce( + SharedVaultUser.create({ + permission: SharedVaultUserPermission.create(SharedVaultUserPermission.PERMISSIONS.Write).getValue(), + sharedVaultUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(), + userUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(), + timestamps: Timestamps.create(123, 123).getValue(), + }).getValue(), + ) + .mockReturnValueOnce( + SharedVaultUser.create({ + permission: SharedVaultUserPermission.create(SharedVaultUserPermission.PERMISSIONS.Read).getValue(), + sharedVaultUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(), + userUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(), + timestamps: Timestamps.create(123, 123).getValue(), + }).getValue(), + ) + }) + + it('should return error when move operation type is not specified', async () => { + const useCase = createUseCase() + const result = await useCase.execute({ + userUuid: '00000000-0000-0000-0000-000000000000', + sharedVaultUuid: '00000000-0000-0000-0000-000000000000', + remoteIdentifier: 'remote-identifier', + operation: ValetTokenOperation.Move, + }) + + expect(result.isFailed()).toBe(true) + expect(result.getError()).toBe('Move operation type is required') + }) + + it('should return error when target uuid is missing on a shared-vault-to-shared-vault move operation', async () => { + const useCase = createUseCase() + const result = await useCase.execute({ + userUuid: '00000000-0000-0000-0000-000000000000', + sharedVaultUuid: '00000000-0000-0000-0000-000000000000', + remoteIdentifier: 'remote-identifier', + operation: ValetTokenOperation.Move, + moveOperationType: 'shared-vault-to-shared-vault', + }) + + expect(result.isFailed()).toBe(true) + expect(result.getError()).toBe('Shared vault to shared vault move target uuid is required') + }) + + it('should return error when target uuid is invalid on a shared-vault-to-shared-vault move operation', async () => { + const useCase = createUseCase() + const result = await useCase.execute({ + userUuid: '00000000-0000-0000-0000-000000000000', + sharedVaultUuid: '00000000-0000-0000-0000-000000000000', + remoteIdentifier: 'remote-identifier', + operation: ValetTokenOperation.Move, + moveOperationType: 'shared-vault-to-shared-vault', + sharedVaultToSharedVaultMoveTargetUuid: 'invalid-uuid', + }) + + expect(result.isFailed()).toBe(true) + expect(result.getError()).toBe('Given value is not a valid uuid: invalid-uuid') + }) + + it('should return error when target shared vault user is not found on a shared-vault-to-shared-vault move operation', async () => { + sharedVaultUserRepository.findByUserUuidAndSharedVaultUuid = jest + .fn() + .mockReturnValueOnce( + SharedVaultUser.create({ + permission: SharedVaultUserPermission.create(SharedVaultUserPermission.PERMISSIONS.Write).getValue(), + sharedVaultUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(), + userUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(), + timestamps: Timestamps.create(123, 123).getValue(), + }).getValue(), + ) + .mockReturnValueOnce(null) + + const useCase = createUseCase() + const result = await useCase.execute({ + userUuid: '00000000-0000-0000-0000-000000000000', + sharedVaultUuid: '00000000-0000-0000-0000-000000000000', + remoteIdentifier: 'remote-identifier', + operation: ValetTokenOperation.Move, + moveOperationType: 'shared-vault-to-shared-vault', + sharedVaultToSharedVaultMoveTargetUuid: '00000000-0000-0000-0000-000000000000', + }) + + expect(result.isFailed()).toBe(true) + expect(result.getError()).toBe('Shared vault target user not found') + }) + + it('should return error when target shared vault user does not have permission on a shared-vault-to-shared-vault move operation', async () => { + sharedVaultUserRepository.findByUserUuidAndSharedVaultUuid = jest + .fn() + .mockReturnValueOnce( + SharedVaultUser.create({ + permission: SharedVaultUserPermission.create(SharedVaultUserPermission.PERMISSIONS.Write).getValue(), + sharedVaultUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(), + userUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(), + timestamps: Timestamps.create(123, 123).getValue(), + }).getValue(), + ) + .mockReturnValueOnce( + SharedVaultUser.create({ + permission: SharedVaultUserPermission.create(SharedVaultUserPermission.PERMISSIONS.Read).getValue(), + sharedVaultUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(), + userUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(), + timestamps: Timestamps.create(123, 123).getValue(), + }).getValue(), + ) + + const useCase = createUseCase() + const result = await useCase.execute({ + userUuid: '00000000-0000-0000-0000-000000000000', + sharedVaultUuid: '00000000-0000-0000-0000-000000000000', + remoteIdentifier: 'remote-identifier', + operation: ValetTokenOperation.Move, + moveOperationType: 'shared-vault-to-shared-vault', + sharedVaultToSharedVaultMoveTargetUuid: '00000000-0000-0000-0000-000000000000', + }) + + expect(result.isFailed()).toBe(true) + expect(result.getError()).toBe('User does not have permission to perform this operation') + }) + + it('should create move valet token for shared-vault-to-shared-vault operation', async () => { + sharedVaultUserRepository.findByUserUuidAndSharedVaultUuid = jest + .fn() + .mockReturnValueOnce( + SharedVaultUser.create({ + permission: SharedVaultUserPermission.create(SharedVaultUserPermission.PERMISSIONS.Write).getValue(), + sharedVaultUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(), + userUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(), + timestamps: Timestamps.create(123, 123).getValue(), + }).getValue(), + ) + .mockReturnValueOnce( + SharedVaultUser.create({ + permission: SharedVaultUserPermission.create(SharedVaultUserPermission.PERMISSIONS.Write).getValue(), + sharedVaultUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(), + userUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(), + timestamps: Timestamps.create(123, 123).getValue(), + }).getValue(), + ) + + const useCase = createUseCase() + const result = await useCase.execute({ + userUuid: '00000000-0000-0000-0000-000000000000', + sharedVaultUuid: '00000000-0000-0000-0000-000000000000', + remoteIdentifier: 'remote-identifier', + operation: ValetTokenOperation.Move, + moveOperationType: 'shared-vault-to-shared-vault', + sharedVaultToSharedVaultMoveTargetUuid: '00000000-0000-0000-0000-000000000000', + }) + + expect(result.isFailed()).toBe(false) + expect(result.getValue()).toBe('encoded-token') + }) + + it('should create move valet token for shared-vault-to-user operation', async () => { + sharedVaultUserRepository.findByUserUuidAndSharedVaultUuid = jest + .fn() + .mockReturnValueOnce( + SharedVaultUser.create({ + permission: SharedVaultUserPermission.create(SharedVaultUserPermission.PERMISSIONS.Write).getValue(), + sharedVaultUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(), + userUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(), + timestamps: Timestamps.create(123, 123).getValue(), + }).getValue(), + ) + .mockReturnValueOnce( + SharedVaultUser.create({ + permission: SharedVaultUserPermission.create(SharedVaultUserPermission.PERMISSIONS.Write).getValue(), + sharedVaultUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(), + userUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(), + timestamps: Timestamps.create(123, 123).getValue(), + }).getValue(), + ) + + const useCase = createUseCase() + const result = await useCase.execute({ + userUuid: '00000000-0000-0000-0000-000000000000', + sharedVaultUuid: '00000000-0000-0000-0000-000000000000', + remoteIdentifier: 'remote-identifier', + operation: ValetTokenOperation.Move, + moveOperationType: 'shared-vault-to-user', + sharedVaultToSharedVaultMoveTargetUuid: '00000000-0000-0000-0000-000000000000', + }) + + expect(result.isFailed()).toBe(false) + expect(result.getValue()).toBe('encoded-token') + }) + + it('should create move valet token for user-to-shared-vault operation', async () => { + sharedVaultUserRepository.findByUserUuidAndSharedVaultUuid = jest + .fn() + .mockReturnValueOnce( + SharedVaultUser.create({ + permission: SharedVaultUserPermission.create(SharedVaultUserPermission.PERMISSIONS.Write).getValue(), + sharedVaultUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(), + userUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(), + timestamps: Timestamps.create(123, 123).getValue(), + }).getValue(), + ) + .mockReturnValueOnce( + SharedVaultUser.create({ + permission: SharedVaultUserPermission.create(SharedVaultUserPermission.PERMISSIONS.Write).getValue(), + sharedVaultUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(), + userUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(), + timestamps: Timestamps.create(123, 123).getValue(), + }).getValue(), + ) + + const useCase = createUseCase() + const result = await useCase.execute({ + userUuid: '00000000-0000-0000-0000-000000000000', + sharedVaultUuid: '00000000-0000-0000-0000-000000000000', + remoteIdentifier: 'remote-identifier', + operation: ValetTokenOperation.Move, + moveOperationType: 'user-to-shared-vault', + sharedVaultToSharedVaultMoveTargetUuid: '00000000-0000-0000-0000-000000000000', + }) + + expect(result.isFailed()).toBe(false) + expect(result.getValue()).toBe('encoded-token') + }) + }) +}) diff --git a/packages/syncing-server/src/Domain/UseCase/CreateSharedVaultFileValetToken/CreateSharedVaultFileValetToken.ts b/packages/syncing-server/src/Domain/UseCase/CreateSharedVaultFileValetToken/CreateSharedVaultFileValetToken.ts new file mode 100644 index 000000000..0f8460894 --- /dev/null +++ b/packages/syncing-server/src/Domain/UseCase/CreateSharedVaultFileValetToken/CreateSharedVaultFileValetToken.ts @@ -0,0 +1,124 @@ +import { SharedVaultValetTokenData, TokenEncoderInterface, ValetTokenOperation } from '@standardnotes/security' + +import { SharedVaultRepositoryInterface } from '../../SharedVault/SharedVaultRepositoryInterface' +import { Result, UseCaseInterface, Uuid } from '@standardnotes/domain-core' +import { SharedVaultUserRepositoryInterface } from '../../SharedVault/User/SharedVaultUserRepositoryInterface' +import { CreateSharedVaultFileValetTokenDTO } from './CreateSharedVaultFileValetTokenDTO' +import { SharedVaultUserPermission } from '../../SharedVault/User/SharedVaultUserPermission' + +export class CreateSharedVaultFileValetToken implements UseCaseInterface { + constructor( + private sharedVaultRepository: SharedVaultRepositoryInterface, + private sharedVaultUserRepository: SharedVaultUserRepositoryInterface, + private tokenEncoder: TokenEncoderInterface, + private valetTokenTTL: number, + ) {} + + async execute(dto: CreateSharedVaultFileValetTokenDTO): Promise> { + const sharedVaultUuidOrError = Uuid.create(dto.sharedVaultUuid) + if (sharedVaultUuidOrError.isFailed()) { + return Result.fail(sharedVaultUuidOrError.getError()) + } + const sharedVaultUuid = sharedVaultUuidOrError.getValue() + + const userUuidOrError = Uuid.create(dto.userUuid) + if (userUuidOrError.isFailed()) { + return Result.fail(userUuidOrError.getError()) + } + const userUuid = userUuidOrError.getValue() + + const sharedVault = await this.sharedVaultRepository.findByUuid(sharedVaultUuid) + if (!sharedVault) { + return Result.fail('Shared vault not found') + } + + const sharedVaultUser = await this.sharedVaultUserRepository.findByUserUuidAndSharedVaultUuid({ + userUuid: userUuid, + sharedVaultUuid: sharedVaultUuid, + }) + if (!sharedVaultUser) { + return Result.fail('Shared vault user not found') + } + + if ( + sharedVaultUser.props.permission.value === SharedVaultUserPermission.PERMISSIONS.Read && + dto.operation !== ValetTokenOperation.Read + ) { + return Result.fail('User does not have permission to perform this operation') + } + + if (dto.operation === ValetTokenOperation.Move) { + if (!dto.moveOperationType) { + return Result.fail('Move operation type is required') + } + + if (dto.moveOperationType === 'shared-vault-to-shared-vault') { + if (!dto.sharedVaultToSharedVaultMoveTargetUuid) { + return Result.fail('Shared vault to shared vault move target uuid is required') + } + + const sharedVaultTargetUuidOrError = Uuid.create(dto.sharedVaultToSharedVaultMoveTargetUuid) + if (sharedVaultTargetUuidOrError.isFailed()) { + return Result.fail(sharedVaultTargetUuidOrError.getError()) + } + const sharedVaultTargetUuid = sharedVaultTargetUuidOrError.getValue() + + const toSharedVaultUser = await this.sharedVaultUserRepository.findByUserUuidAndSharedVaultUuid({ + userUuid: userUuid, + sharedVaultUuid: sharedVaultTargetUuid, + }) + + if (!toSharedVaultUser) { + return Result.fail('Shared vault target user not found') + } + + if (toSharedVaultUser.props.permission.value === SharedVaultUserPermission.PERMISSIONS.Read) { + return Result.fail('User does not have permission to perform this operation') + } + } + } + + const tokenData: SharedVaultValetTokenData = { + sharedVaultUuid: dto.sharedVaultUuid, + permittedOperation: dto.operation, + remoteIdentifier: dto.remoteIdentifier, + uploadBytesUsed: sharedVault.props.fileUploadBytesUsed, + uploadBytesLimit: sharedVault.props.fileUploadBytesLimit, + unencryptedFileSize: dto.unencryptedFileSize, + moveOperation: this.createMoveOperationData(dto), + } + + const valetToken = this.tokenEncoder.encodeExpirableToken(tokenData, this.valetTokenTTL) + + return Result.ok(valetToken) + } + + private createMoveOperationData(dto: CreateSharedVaultFileValetTokenDTO): SharedVaultValetTokenData['moveOperation'] { + if (!dto.moveOperationType) { + return undefined + } + + let fromUuid: string + let toUuid: string + switch (dto.moveOperationType) { + case 'shared-vault-to-user': + fromUuid = dto.sharedVaultUuid + toUuid = dto.userUuid + break + case 'user-to-shared-vault': + fromUuid = dto.userUuid + toUuid = dto.sharedVaultUuid + break + case 'shared-vault-to-shared-vault': + fromUuid = dto.sharedVaultUuid + toUuid = dto.sharedVaultToSharedVaultMoveTargetUuid as string + break + } + + return { + type: dto.moveOperationType, + fromUuid, + toUuid, + } + } +} diff --git a/packages/syncing-server/src/Domain/UseCase/CreateSharedVaultFileValetToken/CreateSharedVaultFileValetTokenDTO.ts b/packages/syncing-server/src/Domain/UseCase/CreateSharedVaultFileValetToken/CreateSharedVaultFileValetTokenDTO.ts new file mode 100644 index 000000000..95a919635 --- /dev/null +++ b/packages/syncing-server/src/Domain/UseCase/CreateSharedVaultFileValetToken/CreateSharedVaultFileValetTokenDTO.ts @@ -0,0 +1,12 @@ +import { SharedVaultMoveType, ValetTokenOperation } from '@standardnotes/security' + +export interface CreateSharedVaultFileValetTokenDTO { + userUuid: string + sharedVaultUuid: string + fileUuid?: string + remoteIdentifier: string + operation: ValetTokenOperation + unencryptedFileSize?: number + moveOperationType?: SharedVaultMoveType + sharedVaultToSharedVaultMoveTargetUuid?: string +} diff --git a/packages/syncing-server/src/Infra/TypeORM/TypeORMSharedVaultRepository.ts b/packages/syncing-server/src/Infra/TypeORM/TypeORMSharedVaultRepository.ts index f414d9493..3e9602138 100644 --- a/packages/syncing-server/src/Infra/TypeORM/TypeORMSharedVaultRepository.ts +++ b/packages/syncing-server/src/Infra/TypeORM/TypeORMSharedVaultRepository.ts @@ -21,7 +21,7 @@ export class TypeORMSharedVaultRepository implements SharedVaultRepositoryInterf const persistence = await this.ormRepository .createQueryBuilder('shared_vault') .where('shared_vault.uuid = :uuid', { - uuid: uuid.toString(), + uuid: uuid.value, }) .getOne() diff --git a/packages/syncing-server/src/Infra/TypeORM/TypeORMSharedVaultUserRepository.ts b/packages/syncing-server/src/Infra/TypeORM/TypeORMSharedVaultUserRepository.ts index 17070dd92..7f1c56c06 100644 --- a/packages/syncing-server/src/Infra/TypeORM/TypeORMSharedVaultUserRepository.ts +++ b/packages/syncing-server/src/Infra/TypeORM/TypeORMSharedVaultUserRepository.ts @@ -11,6 +11,27 @@ export class TypeORMSharedVaultUserRepository implements SharedVaultUserReposito private mapper: MapperInterface, ) {} + async findByUserUuidAndSharedVaultUuid(dto: { + userUuid: Uuid + sharedVaultUuid: Uuid + }): Promise { + const persistence = await this.ormRepository + .createQueryBuilder('shared_vault_user') + .where('shared_vault_user.user_uuid = :userUuid', { + userUuid: dto.userUuid.value, + }) + .andWhere('shared_vault_user.shared_vault_uuid = :sharedVaultUuid', { + sharedVaultUuid: dto.sharedVaultUuid.value, + }) + .getOne() + + if (persistence === null) { + return null + } + + return this.mapper.toDomain(persistence) + } + async save(sharedVaultUser: SharedVaultUser): Promise { const persistence = this.mapper.toProjection(sharedVaultUser) @@ -21,7 +42,7 @@ export class TypeORMSharedVaultUserRepository implements SharedVaultUserReposito const persistence = await this.ormRepository .createQueryBuilder('shared_vault_user') .where('shared_vault_user.uuid = :uuid', { - uuid: uuid.toString(), + uuid: uuid.value, }) .getOne()