Bläddra i källkod

fix(syncing-server): add missing messages and key system identifier sql representations (#663)

Karol Sójko 1 år sedan
förälder
incheckning
d026152ac8
18 ändrade filer med 171 tillägg och 33 borttagningar
  1. 14 0
      packages/domain-core/src/Domain/Core/Validator.spec.ts
  2. 14 0
      packages/domain-core/src/Domain/Core/Validator.ts
  3. 17 0
      packages/syncing-server/migrations/mysql/1689745128577-add-messages.ts
  4. 27 0
      packages/syncing-server/migrations/mysql/1689746180559-rename-key-message-identifier.ts
  5. 19 0
      packages/syncing-server/migrations/sqlite/1689744778643-add-messages.ts
  6. 43 0
      packages/syncing-server/migrations/sqlite/1689746527310-rename-key-message-identifier.ts
  7. 2 0
      packages/syncing-server/src/Bootstrap/DataSource.ts
  8. 1 1
      packages/syncing-server/src/Domain/KeySystem/KeySystemAssocationProps.ts
  9. 1 1
      packages/syncing-server/src/Domain/KeySystem/KeySystemAssociation.spec.ts
  10. 2 2
      packages/syncing-server/src/Domain/UseCase/Syncing/SaveNewItem/SaveNewItem.spec.ts
  11. 6 5
      packages/syncing-server/src/Domain/UseCase/Syncing/SaveNewItem/SaveNewItem.ts
  12. 4 4
      packages/syncing-server/src/Domain/UseCase/Syncing/UpdateExistingItem/UpdateExistingItem.spec.ts
  13. 7 7
      packages/syncing-server/src/Domain/UseCase/Syncing/UpdateExistingItem/UpdateExistingItem.ts
  14. 3 3
      packages/syncing-server/src/Infra/TypeORM/TypeORMKeySystemAssociation.ts
  15. 3 1
      packages/syncing-server/src/Infra/TypeORM/TypeORMMessage.ts
  16. 1 1
      packages/syncing-server/src/Mapping/Http/ItemHttpMapper.ts
  17. 1 1
      packages/syncing-server/src/Mapping/Http/SavedItemHttpMapper.ts
  18. 6 7
      packages/syncing-server/src/Mapping/Persistence/KeySystemAssociationPersistenceMapper.ts

+ 14 - 0
packages/domain-core/src/Domain/Core/Validator.spec.ts

@@ -78,4 +78,18 @@ describe('Validator', () => {
       expect(Validator.isNotEmpty(value).isFailed()).toBeTruthy()
     }
   })
+
+  describe('is not empty string', () => {
+    it('should not validate invalid string', () => {
+      expect(Validator.isNotEmptyString(123 as unknown as string).isFailed()).toBeTruthy()
+    })
+
+    it('should not validate an empty string', () => {
+      expect(Validator.isNotEmptyString('').isFailed()).toBeTruthy()
+    })
+
+    it('should validate a string', () => {
+      expect(Validator.isNotEmptyString('foo').isFailed()).toBeFalsy()
+    })
+  })
 })

+ 14 - 0
packages/domain-core/src/Domain/Core/Validator.ts

@@ -42,4 +42,18 @@ export class Validator {
 
     return Result.ok()
   }
+
+  static isNotEmptyString(value: unknown): Result<string> {
+    const isStringResult = Validator.isString(value)
+    if (isStringResult.isFailed()) {
+      return isStringResult
+    }
+
+    const isNotEmptyResult = Validator.isNotEmpty(value)
+    if (isNotEmptyResult.isFailed()) {
+      return isNotEmptyResult
+    }
+
+    return Result.ok()
+  }
 }

+ 17 - 0
packages/syncing-server/migrations/mysql/1689745128577-add-messages.ts

@@ -0,0 +1,17 @@
+import { MigrationInterface, QueryRunner } from 'typeorm'
+
+export class AddMessages1689745128577 implements MigrationInterface {
+  name = 'AddMessages1689745128577'
+
+  public async up(queryRunner: QueryRunner): Promise<void> {
+    await queryRunner.query(
+      'CREATE TABLE `messages` (`uuid` varchar(36) NOT NULL, `recipient_uuid` varchar(36) NOT NULL, `sender_uuid` varchar(36) NOT NULL, `encrypted_message` text NOT NULL, `replaceability_identifier` varchar(255) NULL, `created_at_timestamp` bigint NOT NULL, `updated_at_timestamp` bigint NOT NULL, INDEX `recipient_uuid_on_messages` (`recipient_uuid`), INDEX `sender_uuid_on_messages` (`sender_uuid`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB',
+    )
+  }
+
+  public async down(queryRunner: QueryRunner): Promise<void> {
+    await queryRunner.query('DROP INDEX `sender_uuid_on_messages` ON `messages`')
+    await queryRunner.query('DROP INDEX `recipient_uuid_on_messages` ON `messages`')
+    await queryRunner.query('DROP TABLE `messages`')
+  }
+}

+ 27 - 0
packages/syncing-server/migrations/mysql/1689746180559-rename-key-message-identifier.ts

@@ -0,0 +1,27 @@
+import { MigrationInterface, QueryRunner } from 'typeorm'
+
+export class RenameKeyMessageIdentifier1689746180559 implements MigrationInterface {
+  name = 'RenameKeyMessageIdentifier1689746180559'
+
+  public async up(queryRunner: QueryRunner): Promise<void> {
+    await queryRunner.query('DROP INDEX `key_system_uuid_on_key_system_associations` ON `key_system_associations`')
+    await queryRunner.query(
+      'ALTER TABLE `key_system_associations` CHANGE `key_system_uuid` `key_system_identifier` varchar(36) NOT NULL',
+    )
+    await queryRunner.query(
+      'CREATE INDEX `key_system_identifier_on_key_system_associations` ON `key_system_associations` (`key_system_identifier`)',
+    )
+  }
+
+  public async down(queryRunner: QueryRunner): Promise<void> {
+    await queryRunner.query(
+      'DROP INDEX `key_system_identifier_on_key_system_associations` ON `key_system_associations`',
+    )
+    await queryRunner.query(
+      'ALTER TABLE `key_system_associations` CHANGE `key_system_identifier` `key_system_uuid` varchar(36) NOT NULL',
+    )
+    await queryRunner.query(
+      'CREATE INDEX `key_system_uuid_on_key_system_associations` ON `key_system_associations` (`key_system_uuid`)',
+    )
+  }
+}

+ 19 - 0
packages/syncing-server/migrations/sqlite/1689744778643-add-messages.ts

@@ -0,0 +1,19 @@
+import { MigrationInterface, QueryRunner } from 'typeorm'
+
+export class AddMessages1689744778643 implements MigrationInterface {
+  name = 'AddMessages1689744778643'
+
+  public async up(queryRunner: QueryRunner): Promise<void> {
+    await queryRunner.query(
+      'CREATE TABLE "messages" ("uuid" varchar PRIMARY KEY NOT NULL, "recipient_uuid" varchar(36) NOT NULL, "sender_uuid" varchar(36) NOT NULL, "encrypted_message" text NOT NULL, "replaceability_identifier" varchar(255), "created_at_timestamp" bigint NOT NULL, "updated_at_timestamp" bigint NOT NULL)',
+    )
+    await queryRunner.query('CREATE INDEX "recipient_uuid_on_messages" ON "messages" ("recipient_uuid") ')
+    await queryRunner.query('CREATE INDEX "sender_uuid_on_messages" ON "messages" ("sender_uuid") ')
+  }
+
+  public async down(queryRunner: QueryRunner): Promise<void> {
+    await queryRunner.query('DROP INDEX "sender_uuid_on_messages"')
+    await queryRunner.query('DROP INDEX "recipient_uuid_on_messages"')
+    await queryRunner.query('DROP TABLE "messages"')
+  }
+}

+ 43 - 0
packages/syncing-server/migrations/sqlite/1689746527310-rename-key-message-identifier.ts

@@ -0,0 +1,43 @@
+import { MigrationInterface, QueryRunner } from 'typeorm'
+
+export class RenameKeyMessageIdentifier1689746527310 implements MigrationInterface {
+  name = 'RenameKeyMessageIdentifier1689746527310'
+
+  public async up(queryRunner: QueryRunner): Promise<void> {
+    await queryRunner.query('DROP INDEX "key_system_uuid_on_key_system_associations"')
+    await queryRunner.query('DROP INDEX "item_uuid_on_key_system_associations"')
+    await queryRunner.query(
+      'CREATE TABLE "temporary_key_system_associations" ("uuid" varchar PRIMARY KEY NOT NULL, "key_system_identifier" varchar(36) NOT NULL, "item_uuid" varchar(36) NOT NULL, "created_at_timestamp" bigint NOT NULL, "updated_at_timestamp" bigint NOT NULL)',
+    )
+    await queryRunner.query(
+      'INSERT INTO "temporary_key_system_associations"("uuid", "key_system_identifier", "item_uuid", "created_at_timestamp", "updated_at_timestamp") SELECT "uuid", "key_system_uuid", "item_uuid", "created_at_timestamp", "updated_at_timestamp" FROM "key_system_associations"',
+    )
+    await queryRunner.query('DROP TABLE "key_system_associations"')
+    await queryRunner.query('ALTER TABLE "temporary_key_system_associations" RENAME TO "key_system_associations"')
+    await queryRunner.query(
+      'CREATE INDEX "item_uuid_on_key_system_associations" ON "key_system_associations" ("item_uuid") ',
+    )
+    await queryRunner.query(
+      'CREATE INDEX "key_system_identifier_on_key_system_associations" ON "key_system_associations" ("key_system_identifier") ',
+    )
+  }
+
+  public async down(queryRunner: QueryRunner): Promise<void> {
+    await queryRunner.query('DROP INDEX "key_system_identifier_on_key_system_associations"')
+    await queryRunner.query('DROP INDEX "item_uuid_on_key_system_associations"')
+    await queryRunner.query('ALTER TABLE "key_system_associations" RENAME TO "temporary_key_system_associations"')
+    await queryRunner.query(
+      'CREATE TABLE "key_system_associations" ("uuid" varchar PRIMARY KEY NOT NULL, "key_system_uuid" varchar(36) NOT NULL, "item_uuid" varchar(36) NOT NULL, "created_at_timestamp" bigint NOT NULL, "updated_at_timestamp" bigint NOT NULL)',
+    )
+    await queryRunner.query(
+      'INSERT INTO "key_system_associations"("uuid", "key_system_uuid", "item_uuid", "created_at_timestamp", "updated_at_timestamp") SELECT "uuid", "key_system_identifier", "item_uuid", "created_at_timestamp", "updated_at_timestamp" FROM "temporary_key_system_associations"',
+    )
+    await queryRunner.query('DROP TABLE "temporary_key_system_associations"')
+    await queryRunner.query(
+      'CREATE INDEX "item_uuid_on_key_system_associations" ON "key_system_associations" ("item_uuid") ',
+    )
+    await queryRunner.query(
+      'CREATE INDEX "key_system_uuid_on_key_system_associations" ON "key_system_associations" ("key_system_uuid") ',
+    )
+  }
+}

+ 2 - 0
packages/syncing-server/src/Bootstrap/DataSource.ts

@@ -9,6 +9,7 @@ import { TypeORMKeySystemAssociation } from '../Infra/TypeORM/TypeORMKeySystemAs
 import { TypeORMSharedVault } from '../Infra/TypeORM/TypeORMSharedVault'
 import { TypeORMSharedVaultUser } from '../Infra/TypeORM/TypeORMSharedVaultUser'
 import { TypeORMSharedVaultInvite } from '../Infra/TypeORM/TypeORMSharedVaultInvite'
+import { TypeORMMessage } from '../Infra/TypeORM/TypeORMMessage'
 
 export class AppDataSource {
   private _dataSource: DataSource | undefined
@@ -46,6 +47,7 @@ export class AppDataSource {
         TypeORMSharedVault,
         TypeORMSharedVaultUser,
         TypeORMSharedVaultInvite,
+        TypeORMMessage,
       ],
       migrations: [`${__dirname}/../../migrations/${isConfiguredForMySQL ? 'mysql' : 'sqlite'}/*.js`],
       migrationsRun: true,

+ 1 - 1
packages/syncing-server/src/Domain/KeySystem/KeySystemAssocationProps.ts

@@ -2,6 +2,6 @@ import { Timestamps, Uuid } from '@standardnotes/domain-core'
 
 export interface KeySystemAssociationProps {
   itemUuid: Uuid
-  keySystemUuid: Uuid
+  keySystemIdentifier: string
   timestamps: Timestamps
 }

+ 1 - 1
packages/syncing-server/src/Domain/KeySystem/KeySystemAssociation.spec.ts

@@ -7,7 +7,7 @@ describe('KeySystemAssociation', () => {
     const entityOrError = KeySystemAssociation.create({
       timestamps: Timestamps.create(123456789, 123456789).getValue(),
       itemUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
-      keySystemUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
+      keySystemIdentifier: '00000000-0000-0000-0000-000000000000',
     })
 
     expect(entityOrError.isFailed()).toBeFalsy()

+ 2 - 2
packages/syncing-server/src/Domain/UseCase/Syncing/SaveNewItem/SaveNewItem.spec.ts

@@ -388,12 +388,12 @@ describe('SaveNewItem', () => {
       expect(itemRepository.save).toHaveBeenCalled()
     })
 
-    it('should return a failure if the item hash has an invalid key system uuid', async () => {
+    it('should return a failure if the item hash has an invalid key system identifier', async () => {
       const useCase = createUseCase()
 
       itemHash1 = ItemHash.create({
         ...itemHash1.props,
-        key_system_identifier: '1-2-3',
+        key_system_identifier: 123 as unknown as string,
       }).getValue()
 
       const result = await useCase.execute({

+ 6 - 5
packages/syncing-server/src/Domain/UseCase/Syncing/SaveNewItem/SaveNewItem.ts

@@ -6,6 +6,7 @@ import {
   UniqueEntityId,
   UseCaseInterface,
   Uuid,
+  Validator,
 } from '@standardnotes/domain-core'
 import { TimerInterface } from '@standardnotes/time'
 import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
@@ -111,11 +112,11 @@ export class SaveNewItem implements UseCaseInterface<Item> {
 
     let keySystemAssociation = undefined
     if (dto.itemHash.hasDedicatedKeySystemAssociation()) {
-      const keySystemUuidOrError = Uuid.create(dto.itemHash.props.key_system_identifier as string)
-      if (keySystemUuidOrError.isFailed()) {
-        return Result.fail(keySystemUuidOrError.getError())
+      const keySystemIdentifiedValidationResult = Validator.isNotEmptyString(dto.itemHash.props.key_system_identifier)
+      if (keySystemIdentifiedValidationResult.isFailed()) {
+        return Result.fail(keySystemIdentifiedValidationResult.getError())
       }
-      const keySystemUuid = keySystemUuidOrError.getValue()
+      const keySystemIdentifier = dto.itemHash.props.key_system_identifier as string
 
       const keySystemAssociationOrError = KeySystemAssociation.create({
         itemUuid: uuid,
@@ -123,7 +124,7 @@ export class SaveNewItem implements UseCaseInterface<Item> {
           this.timer.getTimestampInMicroseconds(),
           this.timer.getTimestampInMicroseconds(),
         ).getValue(),
-        keySystemUuid,
+        keySystemIdentifier,
       })
       if (keySystemAssociationOrError.isFailed()) {
         return Result.fail(keySystemAssociationOrError.getError())

+ 4 - 4
packages/syncing-server/src/Domain/UseCase/Syncing/UpdateExistingItem/UpdateExistingItem.spec.ts

@@ -385,7 +385,7 @@ describe('UpdateExistingItem', () => {
       })
       expect(result.isFailed()).toBeFalsy()
       expect(item1.props.keySystemAssociation).not.toBeUndefined()
-      expect(item1.props.keySystemAssociation?.props.keySystemUuid.value).toBe('00000000-0000-0000-0000-000000000000')
+      expect(item1.props.keySystemAssociation?.props.keySystemIdentifier).toBe('00000000-0000-0000-0000-000000000000')
     })
 
     it('should not add a key system association if item hash has a dedicated key system and the existing item is already associated to the key system', async () => {
@@ -398,7 +398,7 @@ describe('UpdateExistingItem', () => {
 
       item1.props.keySystemAssociation = KeySystemAssociation.create({
         itemUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
-        keySystemUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
+        keySystemIdentifier: '00000000-0000-0000-0000-000000000000',
         timestamps: Timestamps.create(123, 123).getValue(),
       }).getValue()
       const idBefore = item1.props.keySystemAssociation?.id.toString()
@@ -416,12 +416,12 @@ describe('UpdateExistingItem', () => {
       expect(item1.props.keySystemAssociation.id.toString()).toEqual(idBefore)
     })
 
-    it('should return error if key system uuid is invalid', async () => {
+    it('should return error if key system identifier is invalid', async () => {
       const useCase = createUseCase()
 
       const itemHash = ItemHash.create({
         ...itemHash1.props,
-        key_system_identifier: 'invalid-uuid',
+        key_system_identifier: 123 as unknown as string,
       }).getValue()
 
       const result = await useCase.execute({

+ 7 - 7
packages/syncing-server/src/Domain/UseCase/Syncing/UpdateExistingItem/UpdateExistingItem.ts

@@ -1,4 +1,4 @@
-import { ContentType, Dates, Result, Timestamps, UseCaseInterface, Uuid } from '@standardnotes/domain-core'
+import { ContentType, Dates, Result, Timestamps, UseCaseInterface, Uuid, Validator } from '@standardnotes/domain-core'
 import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
 import { TimerInterface } from '@standardnotes/time'
 
@@ -135,11 +135,11 @@ export class UpdateExistingItem implements UseCaseInterface<Item> {
       dto.itemHash.hasDedicatedKeySystemAssociation() &&
       !this.itemIsAlreadyAssociatedWithTheKeySystem(dto.existingItem, dto.itemHash)
     ) {
-      const keySystemUuidOrError = Uuid.create(dto.itemHash.props.key_system_identifier as string)
-      if (keySystemUuidOrError.isFailed()) {
-        return Result.fail(keySystemUuidOrError.getError())
+      const keySystemIdentifiedValidationResult = Validator.isNotEmptyString(dto.itemHash.props.key_system_identifier)
+      if (keySystemIdentifiedValidationResult.isFailed()) {
+        return Result.fail(keySystemIdentifiedValidationResult.getError())
       }
-      const keySystemUuid = keySystemUuidOrError.getValue()
+      const keySystemIdentifier = dto.itemHash.props.key_system_identifier as string
 
       const keySystemAssociationOrError = KeySystemAssociation.create({
         itemUuid: Uuid.create(dto.existingItem.id.toString()).getValue(),
@@ -147,7 +147,7 @@ export class UpdateExistingItem implements UseCaseInterface<Item> {
           this.timer.getTimestampInMicroseconds(),
           this.timer.getTimestampInMicroseconds(),
         ).getValue(),
-        keySystemUuid,
+        keySystemIdentifier,
       })
       if (keySystemAssociationOrError.isFailed()) {
         return Result.fail(keySystemAssociationOrError.getError())
@@ -203,7 +203,7 @@ export class UpdateExistingItem implements UseCaseInterface<Item> {
   private itemIsAlreadyAssociatedWithTheKeySystem(item: Item, itemHash: ItemHash): boolean {
     return (
       item.props.keySystemAssociation !== undefined &&
-      item.props.keySystemAssociation.props.keySystemUuid.value === itemHash.props.key_system_identifier
+      item.props.keySystemAssociation.props.keySystemIdentifier === itemHash.props.key_system_identifier
     )
   }
 }

+ 3 - 3
packages/syncing-server/src/Infra/TypeORM/TypeORMKeySystemAssociation.ts

@@ -6,11 +6,11 @@ export class TypeORMKeySystemAssociation {
   declare uuid: string
 
   @Column({
-    name: 'key_system_uuid',
+    name: 'key_system_identifier',
     length: 36,
   })
-  @Index('key_system_uuid_on_key_system_associations')
-  declare keySystemUuid: string
+  @Index('key_system_identifier_on_key_system_associations')
+  declare keySystemIdentifier: string
 
   @Column({
     name: 'item_uuid',

+ 3 - 1
packages/syncing-server/src/Infra/TypeORM/TypeORMMessage.ts

@@ -1,4 +1,4 @@
-import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'
+import { Column, Entity, Index, PrimaryGeneratedColumn } from 'typeorm'
 
 @Entity({ name: 'messages' })
 export class TypeORMMessage {
@@ -9,12 +9,14 @@ export class TypeORMMessage {
     name: 'recipient_uuid',
     length: 36,
   })
+  @Index('recipient_uuid_on_messages')
   declare recipientUuid: string
 
   @Column({
     name: 'sender_uuid',
     length: 36,
   })
+  @Index('sender_uuid_on_messages')
   declare senderUuid: string
 
   @Column({

+ 1 - 1
packages/syncing-server/src/Mapping/Http/ItemHttpMapper.ts

@@ -27,7 +27,7 @@ export class ItemHttpMapper implements MapperInterface<Item, ItemHttpRepresentat
       updated_at_timestamp: domain.props.timestamps.updatedAt,
       updated_with_session: domain.props.updatedWithSession ? domain.props.updatedWithSession.value : null,
       key_system_identifier: domain.props.keySystemAssociation
-        ? domain.props.keySystemAssociation.props.keySystemUuid.value
+        ? domain.props.keySystemAssociation.props.keySystemIdentifier
         : null,
       shared_vault_uuid: domain.props.sharedVaultAssociation
         ? domain.props.sharedVaultAssociation.props.sharedVaultUuid.value

+ 1 - 1
packages/syncing-server/src/Mapping/Http/SavedItemHttpMapper.ts

@@ -23,7 +23,7 @@ export class SavedItemHttpMapper implements MapperInterface<Item, SavedItemHttpR
       updated_at: this.timer.convertMicrosecondsToStringDate(domain.props.timestamps.updatedAt),
       updated_at_timestamp: domain.props.timestamps.updatedAt,
       key_system_identifier: domain.props.keySystemAssociation
-        ? domain.props.keySystemAssociation.props.keySystemUuid.value
+        ? domain.props.keySystemAssociation.props.keySystemIdentifier
         : null,
       shared_vault_uuid: domain.props.sharedVaultAssociation
         ? domain.props.sharedVaultAssociation.props.sharedVaultUuid.value

+ 6 - 7
packages/syncing-server/src/Mapping/Persistence/KeySystemAssociationPersistenceMapper.ts

@@ -1,4 +1,4 @@
-import { MapperInterface, Timestamps, UniqueEntityId, Uuid } from '@standardnotes/domain-core'
+import { MapperInterface, Timestamps, UniqueEntityId, Uuid, Validator } from '@standardnotes/domain-core'
 
 import { KeySystemAssociation } from '../../Domain/KeySystem/KeySystemAssociation'
 
@@ -14,11 +14,10 @@ export class KeySystemAssociationPersistenceMapper
     }
     const itemUuid = itemUuidOrError.getValue()
 
-    const keySystemUuidOrError = Uuid.create(projection.keySystemUuid)
-    if (keySystemUuidOrError.isFailed()) {
-      throw new Error(`Failed to create key system from projection: ${keySystemUuidOrError.getError()}`)
+    const keySystemIdentifiedValidationResult = Validator.isNotEmptyString(projection.keySystemIdentifier)
+    if (keySystemIdentifiedValidationResult.isFailed()) {
+      throw new Error(`Failed to create key system from projection: ${keySystemIdentifiedValidationResult.getError()}`)
     }
-    const keySystemUuid = keySystemUuidOrError.getValue()
 
     const timestampsOrError = Timestamps.create(projection.createdAtTimestamp, projection.updatedAtTimestamp)
     if (timestampsOrError.isFailed()) {
@@ -30,7 +29,7 @@ export class KeySystemAssociationPersistenceMapper
       {
         itemUuid,
         timestamps,
-        keySystemUuid,
+        keySystemIdentifier: projection.keySystemIdentifier,
       },
       new UniqueEntityId(projection.uuid),
     )
@@ -48,7 +47,7 @@ export class KeySystemAssociationPersistenceMapper
 
     typeorm.uuid = domain.id.toString()
     typeorm.itemUuid = domain.props.itemUuid.value
-    typeorm.keySystemUuid = domain.props.keySystemUuid.value
+    typeorm.keySystemIdentifier = domain.props.keySystemIdentifier
     typeorm.createdAtTimestamp = domain.props.timestamps.createdAt
     typeorm.updatedAtTimestamp = domain.props.timestamps.updatedAt