Browse Source

feat: add shared vault invite model. (#634)

Co-authored-by: Mo <mo@standardnotes.com>
Karol Sójko 2 years ago
parent
commit
890cf48749

+ 20 - 0
packages/syncing-server/src/Domain/SharedVault/User/Invite/SharedVaultInvite.spec.ts

@@ -0,0 +1,20 @@
+import { Timestamps, Uuid } from '@standardnotes/domain-core'
+
+import { SharedVaultInvite } from './SharedVaultInvite'
+import { SharedVaultUserPermission } from '../SharedVaultUserPermission'
+
+describe('SharedVaultInvite', () => {
+  it('should create an entity', () => {
+    const entityOrError = SharedVaultInvite.create({
+      permission: SharedVaultUserPermission.create('read').getValue(),
+      sharedVaultUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
+      senderUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
+      encryptedMessage: 'encryptedMessage',
+      timestamps: Timestamps.create(123456789, 123456789).getValue(),
+      userUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
+    })
+
+    expect(entityOrError.isFailed()).toBeFalsy()
+    expect(entityOrError.getValue().id).not.toBeNull()
+  })
+})

+ 17 - 0
packages/syncing-server/src/Domain/SharedVault/User/Invite/SharedVaultInvite.ts

@@ -0,0 +1,17 @@
+import { Entity, Result, UniqueEntityId } from '@standardnotes/domain-core'
+
+import { SharedVaultInviteProps } from './SharedVaultInviteProps'
+
+export class SharedVaultInvite extends Entity<SharedVaultInviteProps> {
+  get id(): UniqueEntityId {
+    return this._id
+  }
+
+  private constructor(props: SharedVaultInviteProps, id?: UniqueEntityId) {
+    super(props, id)
+  }
+
+  static create(props: SharedVaultInviteProps, id?: UniqueEntityId): Result<SharedVaultInvite> {
+    return Result.ok<SharedVaultInvite>(new SharedVaultInvite(props, id))
+  }
+}

+ 11 - 0
packages/syncing-server/src/Domain/SharedVault/User/Invite/SharedVaultInviteProps.ts

@@ -0,0 +1,11 @@
+import { Timestamps, Uuid } from '@standardnotes/domain-core'
+import { SharedVaultUserPermission } from '../SharedVaultUserPermission'
+
+export interface SharedVaultInviteProps {
+  sharedVaultUuid: Uuid
+  userUuid: Uuid
+  senderUuid: Uuid
+  encryptedMessage: string
+  permission: SharedVaultUserPermission
+  timestamps: Timestamps
+}

+ 9 - 0
packages/syncing-server/src/Domain/SharedVault/User/Invite/SharedVaultInviteRepositoryInterface.ts

@@ -0,0 +1,9 @@
+import { Uuid } from '@standardnotes/domain-core'
+
+import { SharedVaultInvite } from './SharedVaultInvite'
+
+export interface SharedVaultInviteRepositoryInterface {
+  findByUuid(sharedVaultInviteUuid: Uuid): Promise<SharedVaultInvite | null>
+  save(sharedVaultInvite: SharedVaultInvite): Promise<void>
+  remove(sharedVaultInvite: SharedVaultInvite): Promise<void>
+}

+ 50 - 0
packages/syncing-server/src/Infra/TypeORM/TypeORMSharedVaultInvite.ts

@@ -0,0 +1,50 @@
+import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'
+
+@Entity({ name: 'shared_vault_invites' })
+export class TypeORMSharedVaultInvite {
+  @PrimaryGeneratedColumn('uuid')
+  declare uuid: string
+
+  @Column({
+    name: 'shared_vault_uuid',
+    length: 36,
+  })
+  declare sharedVaultUuid: string
+
+  @Column({
+    name: 'user_uuid',
+    length: 36,
+  })
+  declare userUuid: string
+
+  @Column({
+    name: 'sender_uuid',
+    length: 36,
+  })
+  declare senderUuid: string
+
+  @Column({
+    name: 'encrypted_message',
+    type: 'text',
+  })
+  declare encryptedMessage: string
+
+  @Column({
+    name: 'permission',
+    type: 'varchar',
+    length: 24,
+  })
+  declare permission: string
+
+  @Column({
+    name: 'created_at_timestamp',
+    type: 'bigint',
+  })
+  declare createdAtTimestamp: number
+
+  @Column({
+    name: 'updated_at_timestamp',
+    type: 'bigint',
+  })
+  declare updatedAtTimestamp: number
+}

+ 38 - 0
packages/syncing-server/src/Infra/TypeORM/TypeORMSharedVaultInviteRepository.ts

@@ -0,0 +1,38 @@
+import { Repository } from 'typeorm'
+import { MapperInterface, Uuid } from '@standardnotes/domain-core'
+
+import { TypeORMSharedVaultInvite } from './TypeORMSharedVaultInvite'
+import { SharedVaultInvite } from '../../Domain/SharedVault/User/Invite/SharedVaultInvite'
+import { SharedVaultInviteRepositoryInterface } from '../../Domain/SharedVault/User/Invite/SharedVaultInviteRepositoryInterface'
+
+export class TypeORMSharedVaultInviteRepository implements SharedVaultInviteRepositoryInterface {
+  constructor(
+    private ormRepository: Repository<TypeORMSharedVaultInvite>,
+    private mapper: MapperInterface<SharedVaultInvite, TypeORMSharedVaultInvite>,
+  ) {}
+
+  async save(sharedVaultInvite: SharedVaultInvite): Promise<void> {
+    const persistence = this.mapper.toProjection(sharedVaultInvite)
+
+    await this.ormRepository.save(persistence)
+  }
+
+  async findByUuid(uuid: Uuid): Promise<SharedVaultInvite | null> {
+    const persistence = await this.ormRepository
+      .createQueryBuilder('shared_vault_invite')
+      .where('shared_vault_invite.uuid = :uuid', {
+        uuid: uuid.toString(),
+      })
+      .getOne()
+
+    if (persistence === null) {
+      return null
+    }
+
+    return this.mapper.toDomain(persistence)
+  }
+
+  async remove(sharedVaultInvite: SharedVaultInvite): Promise<void> {
+    await this.ormRepository.remove(this.mapper.toProjection(sharedVaultInvite))
+  }
+}

+ 81 - 0
packages/syncing-server/src/Mapping/SharedVaultInvitePersistenceMapper.ts

@@ -0,0 +1,81 @@
+import { Timestamps, MapperInterface, UniqueEntityId, Uuid, Validator } from '@standardnotes/domain-core'
+
+import { SharedVaultInvite } from '../Domain/SharedVault/User/Invite/SharedVaultInvite'
+import { TypeORMSharedVaultInvite } from '../Infra/TypeORM/TypeORMSharedVaultInvite'
+import { SharedVaultUserPermission } from '../Domain/SharedVault/User/SharedVaultUserPermission'
+
+export class SharedVaultInvitePersistenceMapper
+  implements MapperInterface<SharedVaultInvite, TypeORMSharedVaultInvite>
+{
+  toDomain(projection: TypeORMSharedVaultInvite): SharedVaultInvite {
+    const userUuidOrError = Uuid.create(projection.userUuid)
+    if (userUuidOrError.isFailed()) {
+      throw new Error(`Failed to create shared vault invite from projection: ${userUuidOrError.getError()}`)
+    }
+    const userUuid = userUuidOrError.getValue()
+
+    const senderUuidOrError = Uuid.create(projection.senderUuid)
+    if (senderUuidOrError.isFailed()) {
+      throw new Error(`Failed to create shared vault invite from projection: ${senderUuidOrError.getError()}`)
+    }
+    const senderUuid = senderUuidOrError.getValue()
+
+    const sharedVaultUuidOrError = Uuid.create(projection.sharedVaultUuid)
+    if (sharedVaultUuidOrError.isFailed()) {
+      throw new Error(`Failed to create shared vault invite from projection: ${sharedVaultUuidOrError.getError()}`)
+    }
+    const sharedVaultUuid = sharedVaultUuidOrError.getValue()
+
+    const timestampsOrError = Timestamps.create(projection.createdAtTimestamp, projection.updatedAtTimestamp)
+    if (timestampsOrError.isFailed()) {
+      throw new Error(`Failed to create shared vault invite from projection: ${timestampsOrError.getError()}`)
+    }
+    const timestamps = timestampsOrError.getValue()
+
+    const permissionOrError = SharedVaultUserPermission.create(projection.permission)
+    if (permissionOrError.isFailed()) {
+      throw new Error(`Failed to create shared vault invite from projection: ${permissionOrError.getError()}`)
+    }
+    const permission = permissionOrError.getValue()
+
+    const notEmptyMessageValidationResult = Validator.isNotEmpty(projection.encryptedMessage)
+    if (notEmptyMessageValidationResult.isFailed()) {
+      throw new Error(
+        `Failed to create shared vault invite from projection: ${notEmptyMessageValidationResult.getError()}`,
+      )
+    }
+
+    const sharedVaultInviteOrError = SharedVaultInvite.create(
+      {
+        userUuid,
+        sharedVaultUuid,
+        senderUuid,
+        permission,
+        timestamps,
+        encryptedMessage: projection.encryptedMessage,
+      },
+      new UniqueEntityId(projection.uuid),
+    )
+    if (sharedVaultInviteOrError.isFailed()) {
+      throw new Error(`Failed to create shared vault invite from projection: ${sharedVaultInviteOrError.getError()}`)
+    }
+    const sharedVaultInvite = sharedVaultInviteOrError.getValue()
+
+    return sharedVaultInvite
+  }
+
+  toProjection(domain: SharedVaultInvite): TypeORMSharedVaultInvite {
+    const typeorm = new TypeORMSharedVaultInvite()
+
+    typeorm.uuid = domain.id.toString()
+    typeorm.sharedVaultUuid = domain.props.sharedVaultUuid.value
+    typeorm.userUuid = domain.props.userUuid.value
+    typeorm.permission = domain.props.permission.value
+    typeorm.senderUuid = domain.props.senderUuid.value
+    typeorm.encryptedMessage = domain.props.encryptedMessage
+    typeorm.createdAtTimestamp = domain.props.timestamps.createdAt
+    typeorm.updatedAtTimestamp = domain.props.timestamps.updatedAt
+
+    return typeorm
+  }
+}