diff --git a/e2e/src/api/specs/user.e2e-spec.ts b/e2e/src/api/specs/user.e2e-spec.ts index 911f25381a..5de410606a 100644 --- a/e2e/src/api/specs/user.e2e-spec.ts +++ b/e2e/src/api/specs/user.e2e-spec.ts @@ -257,23 +257,6 @@ describe('/user', () => { expect(body).toMatchObject({ id: admin.userId, profileImagePath: '' }); }); - it('should ignore updates to createdAt, updatedAt and deletedAt', async () => { - const before = await getUserById({ id: admin.userId }, { headers: asBearerAuth(admin.accessToken) }); - - const { status, body } = await request(app) - .put(`/user`) - .send({ - id: admin.userId, - createdAt: '2023-01-01T00:00:00.000Z', - updatedAt: '2023-01-01T00:00:00.000Z', - deletedAt: '2023-01-01T00:00:00.000Z', - }) - .set('Authorization', `Bearer ${admin.accessToken}`); - - expect(status).toBe(200); - expect(body).toStrictEqual(before); - }); - it('should update first and last name', async () => { const before = await getUserById({ id: admin.userId }, { headers: asBearerAuth(admin.accessToken) }); diff --git a/server/src/cores/user.core.ts b/server/src/cores/user.core.ts index 4628c83834..fa6ee7cdea 100644 --- a/server/src/cores/user.core.ts +++ b/server/src/cores/user.core.ts @@ -69,7 +69,7 @@ export class UserCore { dto.storageLabel = null; } - return this.userRepository.update(id, dto); + return this.userRepository.update(id, { ...dto, updatedAt: new Date() }); } async createUser(dto: Partial & { email: string }): Promise { diff --git a/server/src/dtos/user-profile.dto.ts b/server/src/dtos/user-profile.dto.ts index 2f3d8cf224..bc879380c4 100644 --- a/server/src/dtos/user-profile.dto.ts +++ b/server/src/dtos/user-profile.dto.ts @@ -1,6 +1,5 @@ import { ApiProperty } from '@nestjs/swagger'; import { UploadFieldName } from 'src/dtos/asset.dto'; -import { UserAvatarColor, UserEntity } from 'src/entities/user.entity'; export class CreateProfileImageDto { @ApiProperty({ type: 'string', format: 'binary' }) @@ -18,11 +17,3 @@ export function mapCreateProfileImageResponse(userId: string, profileImagePath: profileImagePath: profileImagePath, }; } - -export const getRandomAvatarColor = (user: UserEntity): UserAvatarColor => { - const values = Object.values(UserAvatarColor); - const randomIndex = Math.floor( - [...user.email].map((letter) => letter.codePointAt(0) ?? 0).reduce((a, b) => a + b, 0) % values.length, - ); - return values[randomIndex] as UserAvatarColor; -}; diff --git a/server/src/dtos/user.dto.ts b/server/src/dtos/user.dto.ts index d0d19e2713..21cc9ae2c3 100644 --- a/server/src/dtos/user.dto.ts +++ b/server/src/dtos/user.dto.ts @@ -1,8 +1,9 @@ import { ApiProperty } from '@nestjs/swagger'; import { Transform } from 'class-transformer'; import { IsBoolean, IsEmail, IsEnum, IsNotEmpty, IsNumber, IsPositive, IsString, IsUUID } from 'class-validator'; -import { getRandomAvatarColor } from 'src/dtos/user-profile.dto'; -import { UserAvatarColor, UserEntity, UserStatus } from 'src/entities/user.entity'; +import { UserAvatarColor } from 'src/entities/user-metadata.entity'; +import { UserEntity, UserStatus } from 'src/entities/user.entity'; +import { getPreferences } from 'src/utils/preferences'; import { Optional, ValidateBoolean, toEmail, toSanitized } from 'src/validation'; export class CreateUserDto { @@ -151,7 +152,7 @@ export const mapSimpleUser = (entity: UserEntity): UserDto => { email: entity.email, name: entity.name, profileImagePath: entity.profileImagePath, - avatarColor: entity.avatarColor ?? getRandomAvatarColor(entity), + avatarColor: getPreferences(entity).avatar.color, }; }; @@ -165,7 +166,7 @@ export function mapUser(entity: UserEntity): UserResponseDto { deletedAt: entity.deletedAt, updatedAt: entity.updatedAt, oauthId: entity.oauthId, - memoriesEnabled: entity.memoriesEnabled, + memoriesEnabled: getPreferences(entity).memories.enabled, quotaSizeInBytes: entity.quotaSizeInBytes, quotaUsageInBytes: entity.quotaUsageInBytes, status: entity.status, diff --git a/server/src/entities/index.ts b/server/src/entities/index.ts index abe67efdd5..313f2dc269 100644 --- a/server/src/entities/index.ts +++ b/server/src/entities/index.ts @@ -20,6 +20,7 @@ import { SmartInfoEntity } from 'src/entities/smart-info.entity'; import { SmartSearchEntity } from 'src/entities/smart-search.entity'; import { SystemMetadataEntity } from 'src/entities/system-metadata.entity'; import { TagEntity } from 'src/entities/tag.entity'; +import { UserMetadataEntity } from 'src/entities/user-metadata.entity'; import { UserEntity } from 'src/entities/user.entity'; export const entities = [ @@ -44,6 +45,7 @@ export const entities = [ SystemMetadataEntity, TagEntity, UserEntity, + UserMetadataEntity, SessionEntity, LibraryEntity, ]; diff --git a/server/src/entities/user-metadata.entity.ts b/server/src/entities/user-metadata.entity.ts new file mode 100644 index 0000000000..26715e05e3 --- /dev/null +++ b/server/src/entities/user-metadata.entity.ts @@ -0,0 +1,63 @@ +import { UserEntity } from 'src/entities/user.entity'; +import { Column, DeepPartial, Entity, ManyToOne, PrimaryColumn } from 'typeorm'; + +@Entity('user_metadata') +export class UserMetadataEntity { + @PrimaryColumn({ type: 'uuid' }) + userId!: string; + + @ManyToOne(() => UserEntity, (user) => user.metadata, { onUpdate: 'CASCADE', onDelete: 'CASCADE' }) + user!: UserEntity; + + @PrimaryColumn({ type: 'varchar' }) + key!: T; + + @Column({ type: 'jsonb' }) + value!: UserMetadata[T]; +} + +export enum UserAvatarColor { + PRIMARY = 'primary', + PINK = 'pink', + RED = 'red', + YELLOW = 'yellow', + BLUE = 'blue', + GREEN = 'green', + PURPLE = 'purple', + ORANGE = 'orange', + GRAY = 'gray', + AMBER = 'amber', +} + +export interface UserPreferences { + memories: { + enabled: boolean; + }; + avatar: { + color: UserAvatarColor; + }; +} + +export const getDefaultPreferences = (user: { email: string }): UserPreferences => { + const values = Object.values(UserAvatarColor); + const randomIndex = Math.floor( + [...user.email].map((letter) => letter.codePointAt(0) ?? 0).reduce((a, b) => a + b, 0) % values.length, + ); + + return { + memories: { + enabled: true, + }, + avatar: { + color: values[randomIndex], + }, + }; +}; + +export enum UserMetadataKey { + PREFERENCES = 'preferences', +} + +export interface UserMetadata extends Record> { + [UserMetadataKey.PREFERENCES]: DeepPartial; +} diff --git a/server/src/entities/user.entity.ts b/server/src/entities/user.entity.ts index 4d6361abad..6878292ab0 100644 --- a/server/src/entities/user.entity.ts +++ b/server/src/entities/user.entity.ts @@ -1,5 +1,6 @@ import { AssetEntity } from 'src/entities/asset.entity'; import { TagEntity } from 'src/entities/tag.entity'; +import { UserMetadataEntity } from 'src/entities/user-metadata.entity'; import { Column, CreateDateColumn, @@ -10,19 +11,6 @@ import { UpdateDateColumn, } from 'typeorm'; -export enum UserAvatarColor { - PRIMARY = 'primary', - PINK = 'pink', - RED = 'red', - YELLOW = 'yellow', - BLUE = 'blue', - GREEN = 'green', - PURPLE = 'purple', - ORANGE = 'orange', - GRAY = 'gray', - AMBER = 'amber', -} - export enum UserStatus { ACTIVE = 'active', REMOVING = 'removing', @@ -37,9 +25,6 @@ export class UserEntity { @Column({ default: '' }) name!: string; - @Column({ type: 'varchar', nullable: true }) - avatarColor!: UserAvatarColor | null; - @Column({ default: false }) isAdmin!: boolean; @@ -73,9 +58,6 @@ export class UserEntity { @UpdateDateColumn({ type: 'timestamptz' }) updatedAt!: Date; - @Column({ default: true }) - memoriesEnabled!: boolean; - @OneToMany(() => TagEntity, (tag) => tag.user) tags!: TagEntity[]; @@ -87,4 +69,7 @@ export class UserEntity { @Column({ type: 'bigint', default: 0 }) quotaUsageInBytes!: number; + + @OneToMany(() => UserMetadataEntity, (metadata) => metadata.user) + metadata!: UserMetadataEntity[]; } diff --git a/server/src/interfaces/user.interface.ts b/server/src/interfaces/user.interface.ts index ebc70688ea..87ed2ccb08 100644 --- a/server/src/interfaces/user.interface.ts +++ b/server/src/interfaces/user.interface.ts @@ -1,3 +1,4 @@ +import { UserMetadata } from 'src/entities/user-metadata.entity'; import { UserEntity } from 'src/entities/user.entity'; export interface UserListFilter { @@ -31,6 +32,7 @@ export interface IUserRepository { getUserStats(): Promise; create(user: Partial): Promise; update(id: string, user: Partial): Promise; + upsertMetadata(id: string, item: { key: T; value: UserMetadata[T] }): Promise; delete(user: UserEntity, hard?: boolean): Promise; updateUsage(id: string, delta: number): Promise; syncUsage(id?: string): Promise; diff --git a/server/src/migrations/1716312279245-UserMetadata.ts b/server/src/migrations/1716312279245-UserMetadata.ts new file mode 100644 index 0000000000..b118a8d42a --- /dev/null +++ b/server/src/migrations/1716312279245-UserMetadata.ts @@ -0,0 +1,60 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class UserMetadata1716312279245 implements MigrationInterface { + name = 'UserMetadata1716312279245'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `CREATE TABLE "user_metadata" ("userId" uuid NOT NULL, "key" character varying NOT NULL, "value" jsonb NOT NULL, CONSTRAINT "PK_5931462150b3438cbc83277fe5a" PRIMARY KEY ("userId", "key"))`, + ); + const users = await queryRunner.query('SELECT "id", "memoriesEnabled", "avatarColor" FROM "users"'); + for (const { id, memoriesEnabled, avatarColor } of users) { + const preferences: any = {}; + if (!memoriesEnabled) { + preferences.memories = { enabled: false }; + } + + if (avatarColor) { + preferences.avatar = { color: avatarColor }; + } + + if (Object.keys(preferences).length === 0) { + continue; + } + + await queryRunner.query('INSERT INTO "user_metadata" ("userId", "key", "value") VALUES ($1, $2, $3)', [ + id, + 'preferences', + preferences, + ]); + } + await queryRunner.query(`ALTER TABLE "users" DROP COLUMN "memoriesEnabled"`); + await queryRunner.query(`ALTER TABLE "users" DROP COLUMN "avatarColor"`); + await queryRunner.query( + `ALTER TABLE "user_metadata" ADD CONSTRAINT "FK_6afb43681a21cf7815932bc38ac" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "user_metadata" DROP CONSTRAINT "FK_6afb43681a21cf7815932bc38ac"`); + await queryRunner.query(`ALTER TABLE "users" ADD "avatarColor" character varying`); + await queryRunner.query(`ALTER TABLE "users" ADD "memoriesEnabled" boolean NOT NULL DEFAULT true`); + const items = await queryRunner.query( + `SELECT "userId" as "id", "value" FROM "user_metadata" WHERE "key"='preferences'`, + ); + for (const { id, value } of items) { + if (!value) { + continue; + } + + if (value.avatar?.color) { + await queryRunner.query(`UPDATE "users" SET "avatarColor" = $1 WHERE "id" = $2`, [value.avatar.color, id]); + } + + if (value.memories?.enabled === false) { + await queryRunner.query(`UPDATE "users" SET "memoriesEnabled" = false WHERE "id" = $1`, [id]); + } + } + await queryRunner.query(`DROP TABLE "user_metadata"`); + } +} diff --git a/server/src/queries/activity.repository.sql b/server/src/queries/activity.repository.sql index c271e4bef2..3f3e04140c 100644 --- a/server/src/queries/activity.repository.sql +++ b/server/src/queries/activity.repository.sql @@ -12,7 +12,6 @@ SELECT "ActivityEntity"."isLiked" AS "ActivityEntity_isLiked", "ActivityEntity__ActivityEntity_user"."id" AS "ActivityEntity__ActivityEntity_user_id", "ActivityEntity__ActivityEntity_user"."name" AS "ActivityEntity__ActivityEntity_user_name", - "ActivityEntity__ActivityEntity_user"."avatarColor" AS "ActivityEntity__ActivityEntity_user_avatarColor", "ActivityEntity__ActivityEntity_user"."isAdmin" AS "ActivityEntity__ActivityEntity_user_isAdmin", "ActivityEntity__ActivityEntity_user"."email" AS "ActivityEntity__ActivityEntity_user_email", "ActivityEntity__ActivityEntity_user"."storageLabel" AS "ActivityEntity__ActivityEntity_user_storageLabel", @@ -23,7 +22,6 @@ SELECT "ActivityEntity__ActivityEntity_user"."deletedAt" AS "ActivityEntity__ActivityEntity_user_deletedAt", "ActivityEntity__ActivityEntity_user"."status" AS "ActivityEntity__ActivityEntity_user_status", "ActivityEntity__ActivityEntity_user"."updatedAt" AS "ActivityEntity__ActivityEntity_user_updatedAt", - "ActivityEntity__ActivityEntity_user"."memoriesEnabled" AS "ActivityEntity__ActivityEntity_user_memoriesEnabled", "ActivityEntity__ActivityEntity_user"."quotaSizeInBytes" AS "ActivityEntity__ActivityEntity_user_quotaSizeInBytes", "ActivityEntity__ActivityEntity_user"."quotaUsageInBytes" AS "ActivityEntity__ActivityEntity_user_quotaUsageInBytes" FROM diff --git a/server/src/queries/album.repository.sql b/server/src/queries/album.repository.sql index 2037e320a1..8ac7ed6731 100644 --- a/server/src/queries/album.repository.sql +++ b/server/src/queries/album.repository.sql @@ -18,7 +18,6 @@ FROM "AlbumEntity"."order" AS "AlbumEntity_order", "AlbumEntity__AlbumEntity_owner"."id" AS "AlbumEntity__AlbumEntity_owner_id", "AlbumEntity__AlbumEntity_owner"."name" AS "AlbumEntity__AlbumEntity_owner_name", - "AlbumEntity__AlbumEntity_owner"."avatarColor" AS "AlbumEntity__AlbumEntity_owner_avatarColor", "AlbumEntity__AlbumEntity_owner"."isAdmin" AS "AlbumEntity__AlbumEntity_owner_isAdmin", "AlbumEntity__AlbumEntity_owner"."email" AS "AlbumEntity__AlbumEntity_owner_email", "AlbumEntity__AlbumEntity_owner"."storageLabel" AS "AlbumEntity__AlbumEntity_owner_storageLabel", @@ -29,7 +28,6 @@ FROM "AlbumEntity__AlbumEntity_owner"."deletedAt" AS "AlbumEntity__AlbumEntity_owner_deletedAt", "AlbumEntity__AlbumEntity_owner"."status" AS "AlbumEntity__AlbumEntity_owner_status", "AlbumEntity__AlbumEntity_owner"."updatedAt" AS "AlbumEntity__AlbumEntity_owner_updatedAt", - "AlbumEntity__AlbumEntity_owner"."memoriesEnabled" AS "AlbumEntity__AlbumEntity_owner_memoriesEnabled", "AlbumEntity__AlbumEntity_owner"."quotaSizeInBytes" AS "AlbumEntity__AlbumEntity_owner_quotaSizeInBytes", "AlbumEntity__AlbumEntity_owner"."quotaUsageInBytes" AS "AlbumEntity__AlbumEntity_owner_quotaUsageInBytes", "AlbumEntity__AlbumEntity_albumUsers"."albumsId" AS "AlbumEntity__AlbumEntity_albumUsers_albumsId", @@ -37,7 +35,6 @@ FROM "AlbumEntity__AlbumEntity_albumUsers"."role" AS "AlbumEntity__AlbumEntity_albumUsers_role", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."id" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_id", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."name" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_name", - "a641d58cf46d4a391ba060ac4dc337665c69ffea"."avatarColor" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_avatarColor", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."isAdmin" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_isAdmin", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."email" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_email", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."storageLabel" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_storageLabel", @@ -48,7 +45,6 @@ FROM "a641d58cf46d4a391ba060ac4dc337665c69ffea"."deletedAt" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_deletedAt", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."status" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_status", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."updatedAt" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_updatedAt", - "a641d58cf46d4a391ba060ac4dc337665c69ffea"."memoriesEnabled" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_memoriesEnabled", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."quotaSizeInBytes" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_quotaSizeInBytes", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."quotaUsageInBytes" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_quotaUsageInBytes", "AlbumEntity__AlbumEntity_sharedLinks"."id" AS "AlbumEntity__AlbumEntity_sharedLinks_id", @@ -98,7 +94,6 @@ SELECT "AlbumEntity"."order" AS "AlbumEntity_order", "AlbumEntity__AlbumEntity_owner"."id" AS "AlbumEntity__AlbumEntity_owner_id", "AlbumEntity__AlbumEntity_owner"."name" AS "AlbumEntity__AlbumEntity_owner_name", - "AlbumEntity__AlbumEntity_owner"."avatarColor" AS "AlbumEntity__AlbumEntity_owner_avatarColor", "AlbumEntity__AlbumEntity_owner"."isAdmin" AS "AlbumEntity__AlbumEntity_owner_isAdmin", "AlbumEntity__AlbumEntity_owner"."email" AS "AlbumEntity__AlbumEntity_owner_email", "AlbumEntity__AlbumEntity_owner"."storageLabel" AS "AlbumEntity__AlbumEntity_owner_storageLabel", @@ -109,7 +104,6 @@ SELECT "AlbumEntity__AlbumEntity_owner"."deletedAt" AS "AlbumEntity__AlbumEntity_owner_deletedAt", "AlbumEntity__AlbumEntity_owner"."status" AS "AlbumEntity__AlbumEntity_owner_status", "AlbumEntity__AlbumEntity_owner"."updatedAt" AS "AlbumEntity__AlbumEntity_owner_updatedAt", - "AlbumEntity__AlbumEntity_owner"."memoriesEnabled" AS "AlbumEntity__AlbumEntity_owner_memoriesEnabled", "AlbumEntity__AlbumEntity_owner"."quotaSizeInBytes" AS "AlbumEntity__AlbumEntity_owner_quotaSizeInBytes", "AlbumEntity__AlbumEntity_owner"."quotaUsageInBytes" AS "AlbumEntity__AlbumEntity_owner_quotaUsageInBytes", "AlbumEntity__AlbumEntity_albumUsers"."albumsId" AS "AlbumEntity__AlbumEntity_albumUsers_albumsId", @@ -117,7 +111,6 @@ SELECT "AlbumEntity__AlbumEntity_albumUsers"."role" AS "AlbumEntity__AlbumEntity_albumUsers_role", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."id" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_id", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."name" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_name", - "a641d58cf46d4a391ba060ac4dc337665c69ffea"."avatarColor" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_avatarColor", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."isAdmin" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_isAdmin", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."email" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_email", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."storageLabel" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_storageLabel", @@ -128,7 +121,6 @@ SELECT "a641d58cf46d4a391ba060ac4dc337665c69ffea"."deletedAt" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_deletedAt", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."status" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_status", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."updatedAt" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_updatedAt", - "a641d58cf46d4a391ba060ac4dc337665c69ffea"."memoriesEnabled" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_memoriesEnabled", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."quotaSizeInBytes" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_quotaSizeInBytes", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."quotaUsageInBytes" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_quotaUsageInBytes" FROM @@ -160,7 +152,6 @@ SELECT "AlbumEntity"."order" AS "AlbumEntity_order", "AlbumEntity__AlbumEntity_owner"."id" AS "AlbumEntity__AlbumEntity_owner_id", "AlbumEntity__AlbumEntity_owner"."name" AS "AlbumEntity__AlbumEntity_owner_name", - "AlbumEntity__AlbumEntity_owner"."avatarColor" AS "AlbumEntity__AlbumEntity_owner_avatarColor", "AlbumEntity__AlbumEntity_owner"."isAdmin" AS "AlbumEntity__AlbumEntity_owner_isAdmin", "AlbumEntity__AlbumEntity_owner"."email" AS "AlbumEntity__AlbumEntity_owner_email", "AlbumEntity__AlbumEntity_owner"."storageLabel" AS "AlbumEntity__AlbumEntity_owner_storageLabel", @@ -171,7 +162,6 @@ SELECT "AlbumEntity__AlbumEntity_owner"."deletedAt" AS "AlbumEntity__AlbumEntity_owner_deletedAt", "AlbumEntity__AlbumEntity_owner"."status" AS "AlbumEntity__AlbumEntity_owner_status", "AlbumEntity__AlbumEntity_owner"."updatedAt" AS "AlbumEntity__AlbumEntity_owner_updatedAt", - "AlbumEntity__AlbumEntity_owner"."memoriesEnabled" AS "AlbumEntity__AlbumEntity_owner_memoriesEnabled", "AlbumEntity__AlbumEntity_owner"."quotaSizeInBytes" AS "AlbumEntity__AlbumEntity_owner_quotaSizeInBytes", "AlbumEntity__AlbumEntity_owner"."quotaUsageInBytes" AS "AlbumEntity__AlbumEntity_owner_quotaUsageInBytes", "AlbumEntity__AlbumEntity_albumUsers"."albumsId" AS "AlbumEntity__AlbumEntity_albumUsers_albumsId", @@ -179,7 +169,6 @@ SELECT "AlbumEntity__AlbumEntity_albumUsers"."role" AS "AlbumEntity__AlbumEntity_albumUsers_role", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."id" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_id", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."name" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_name", - "a641d58cf46d4a391ba060ac4dc337665c69ffea"."avatarColor" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_avatarColor", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."isAdmin" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_isAdmin", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."email" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_email", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."storageLabel" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_storageLabel", @@ -190,7 +179,6 @@ SELECT "a641d58cf46d4a391ba060ac4dc337665c69ffea"."deletedAt" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_deletedAt", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."status" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_status", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."updatedAt" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_updatedAt", - "a641d58cf46d4a391ba060ac4dc337665c69ffea"."memoriesEnabled" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_memoriesEnabled", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."quotaSizeInBytes" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_quotaSizeInBytes", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."quotaUsageInBytes" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_quotaUsageInBytes" FROM @@ -299,7 +287,6 @@ SELECT "AlbumEntity__AlbumEntity_albumUsers"."role" AS "AlbumEntity__AlbumEntity_albumUsers_role", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."id" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_id", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."name" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_name", - "a641d58cf46d4a391ba060ac4dc337665c69ffea"."avatarColor" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_avatarColor", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."isAdmin" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_isAdmin", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."email" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_email", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."storageLabel" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_storageLabel", @@ -310,7 +297,6 @@ SELECT "a641d58cf46d4a391ba060ac4dc337665c69ffea"."deletedAt" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_deletedAt", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."status" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_status", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."updatedAt" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_updatedAt", - "a641d58cf46d4a391ba060ac4dc337665c69ffea"."memoriesEnabled" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_memoriesEnabled", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."quotaSizeInBytes" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_quotaSizeInBytes", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."quotaUsageInBytes" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_quotaUsageInBytes", "AlbumEntity__AlbumEntity_sharedLinks"."id" AS "AlbumEntity__AlbumEntity_sharedLinks_id", @@ -327,7 +313,6 @@ SELECT "AlbumEntity__AlbumEntity_sharedLinks"."albumId" AS "AlbumEntity__AlbumEntity_sharedLinks_albumId", "AlbumEntity__AlbumEntity_owner"."id" AS "AlbumEntity__AlbumEntity_owner_id", "AlbumEntity__AlbumEntity_owner"."name" AS "AlbumEntity__AlbumEntity_owner_name", - "AlbumEntity__AlbumEntity_owner"."avatarColor" AS "AlbumEntity__AlbumEntity_owner_avatarColor", "AlbumEntity__AlbumEntity_owner"."isAdmin" AS "AlbumEntity__AlbumEntity_owner_isAdmin", "AlbumEntity__AlbumEntity_owner"."email" AS "AlbumEntity__AlbumEntity_owner_email", "AlbumEntity__AlbumEntity_owner"."storageLabel" AS "AlbumEntity__AlbumEntity_owner_storageLabel", @@ -338,7 +323,6 @@ SELECT "AlbumEntity__AlbumEntity_owner"."deletedAt" AS "AlbumEntity__AlbumEntity_owner_deletedAt", "AlbumEntity__AlbumEntity_owner"."status" AS "AlbumEntity__AlbumEntity_owner_status", "AlbumEntity__AlbumEntity_owner"."updatedAt" AS "AlbumEntity__AlbumEntity_owner_updatedAt", - "AlbumEntity__AlbumEntity_owner"."memoriesEnabled" AS "AlbumEntity__AlbumEntity_owner_memoriesEnabled", "AlbumEntity__AlbumEntity_owner"."quotaSizeInBytes" AS "AlbumEntity__AlbumEntity_owner_quotaSizeInBytes", "AlbumEntity__AlbumEntity_owner"."quotaUsageInBytes" AS "AlbumEntity__AlbumEntity_owner_quotaUsageInBytes" FROM @@ -376,7 +360,6 @@ SELECT "AlbumEntity__AlbumEntity_albumUsers"."role" AS "AlbumEntity__AlbumEntity_albumUsers_role", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."id" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_id", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."name" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_name", - "a641d58cf46d4a391ba060ac4dc337665c69ffea"."avatarColor" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_avatarColor", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."isAdmin" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_isAdmin", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."email" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_email", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."storageLabel" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_storageLabel", @@ -387,7 +370,6 @@ SELECT "a641d58cf46d4a391ba060ac4dc337665c69ffea"."deletedAt" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_deletedAt", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."status" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_status", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."updatedAt" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_updatedAt", - "a641d58cf46d4a391ba060ac4dc337665c69ffea"."memoriesEnabled" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_memoriesEnabled", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."quotaSizeInBytes" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_quotaSizeInBytes", "a641d58cf46d4a391ba060ac4dc337665c69ffea"."quotaUsageInBytes" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_quotaUsageInBytes", "AlbumEntity__AlbumEntity_sharedLinks"."id" AS "AlbumEntity__AlbumEntity_sharedLinks_id", @@ -404,7 +386,6 @@ SELECT "AlbumEntity__AlbumEntity_sharedLinks"."albumId" AS "AlbumEntity__AlbumEntity_sharedLinks_albumId", "AlbumEntity__AlbumEntity_owner"."id" AS "AlbumEntity__AlbumEntity_owner_id", "AlbumEntity__AlbumEntity_owner"."name" AS "AlbumEntity__AlbumEntity_owner_name", - "AlbumEntity__AlbumEntity_owner"."avatarColor" AS "AlbumEntity__AlbumEntity_owner_avatarColor", "AlbumEntity__AlbumEntity_owner"."isAdmin" AS "AlbumEntity__AlbumEntity_owner_isAdmin", "AlbumEntity__AlbumEntity_owner"."email" AS "AlbumEntity__AlbumEntity_owner_email", "AlbumEntity__AlbumEntity_owner"."storageLabel" AS "AlbumEntity__AlbumEntity_owner_storageLabel", @@ -415,7 +396,6 @@ SELECT "AlbumEntity__AlbumEntity_owner"."deletedAt" AS "AlbumEntity__AlbumEntity_owner_deletedAt", "AlbumEntity__AlbumEntity_owner"."status" AS "AlbumEntity__AlbumEntity_owner_status", "AlbumEntity__AlbumEntity_owner"."updatedAt" AS "AlbumEntity__AlbumEntity_owner_updatedAt", - "AlbumEntity__AlbumEntity_owner"."memoriesEnabled" AS "AlbumEntity__AlbumEntity_owner_memoriesEnabled", "AlbumEntity__AlbumEntity_owner"."quotaSizeInBytes" AS "AlbumEntity__AlbumEntity_owner_quotaSizeInBytes", "AlbumEntity__AlbumEntity_owner"."quotaUsageInBytes" AS "AlbumEntity__AlbumEntity_owner_quotaUsageInBytes" FROM @@ -504,7 +484,6 @@ SELECT "AlbumEntity__AlbumEntity_sharedLinks"."albumId" AS "AlbumEntity__AlbumEntity_sharedLinks_albumId", "AlbumEntity__AlbumEntity_owner"."id" AS "AlbumEntity__AlbumEntity_owner_id", "AlbumEntity__AlbumEntity_owner"."name" AS "AlbumEntity__AlbumEntity_owner_name", - "AlbumEntity__AlbumEntity_owner"."avatarColor" AS "AlbumEntity__AlbumEntity_owner_avatarColor", "AlbumEntity__AlbumEntity_owner"."isAdmin" AS "AlbumEntity__AlbumEntity_owner_isAdmin", "AlbumEntity__AlbumEntity_owner"."email" AS "AlbumEntity__AlbumEntity_owner_email", "AlbumEntity__AlbumEntity_owner"."storageLabel" AS "AlbumEntity__AlbumEntity_owner_storageLabel", @@ -515,7 +494,6 @@ SELECT "AlbumEntity__AlbumEntity_owner"."deletedAt" AS "AlbumEntity__AlbumEntity_owner_deletedAt", "AlbumEntity__AlbumEntity_owner"."status" AS "AlbumEntity__AlbumEntity_owner_status", "AlbumEntity__AlbumEntity_owner"."updatedAt" AS "AlbumEntity__AlbumEntity_owner_updatedAt", - "AlbumEntity__AlbumEntity_owner"."memoriesEnabled" AS "AlbumEntity__AlbumEntity_owner_memoriesEnabled", "AlbumEntity__AlbumEntity_owner"."quotaSizeInBytes" AS "AlbumEntity__AlbumEntity_owner_quotaSizeInBytes", "AlbumEntity__AlbumEntity_owner"."quotaUsageInBytes" AS "AlbumEntity__AlbumEntity_owner_quotaUsageInBytes" FROM @@ -564,7 +542,6 @@ SELECT "AlbumEntity"."order" AS "AlbumEntity_order", "AlbumEntity__AlbumEntity_owner"."id" AS "AlbumEntity__AlbumEntity_owner_id", "AlbumEntity__AlbumEntity_owner"."name" AS "AlbumEntity__AlbumEntity_owner_name", - "AlbumEntity__AlbumEntity_owner"."avatarColor" AS "AlbumEntity__AlbumEntity_owner_avatarColor", "AlbumEntity__AlbumEntity_owner"."isAdmin" AS "AlbumEntity__AlbumEntity_owner_isAdmin", "AlbumEntity__AlbumEntity_owner"."email" AS "AlbumEntity__AlbumEntity_owner_email", "AlbumEntity__AlbumEntity_owner"."storageLabel" AS "AlbumEntity__AlbumEntity_owner_storageLabel", @@ -575,7 +552,6 @@ SELECT "AlbumEntity__AlbumEntity_owner"."deletedAt" AS "AlbumEntity__AlbumEntity_owner_deletedAt", "AlbumEntity__AlbumEntity_owner"."status" AS "AlbumEntity__AlbumEntity_owner_status", "AlbumEntity__AlbumEntity_owner"."updatedAt" AS "AlbumEntity__AlbumEntity_owner_updatedAt", - "AlbumEntity__AlbumEntity_owner"."memoriesEnabled" AS "AlbumEntity__AlbumEntity_owner_memoriesEnabled", "AlbumEntity__AlbumEntity_owner"."quotaSizeInBytes" AS "AlbumEntity__AlbumEntity_owner_quotaSizeInBytes", "AlbumEntity__AlbumEntity_owner"."quotaUsageInBytes" AS "AlbumEntity__AlbumEntity_owner_quotaUsageInBytes" FROM diff --git a/server/src/queries/api.key.repository.sql b/server/src/queries/api.key.repository.sql index 22b8fd6722..fa0431fb0f 100644 --- a/server/src/queries/api.key.repository.sql +++ b/server/src/queries/api.key.repository.sql @@ -11,7 +11,6 @@ FROM "APIKeyEntity"."userId" AS "APIKeyEntity_userId", "APIKeyEntity__APIKeyEntity_user"."id" AS "APIKeyEntity__APIKeyEntity_user_id", "APIKeyEntity__APIKeyEntity_user"."name" AS "APIKeyEntity__APIKeyEntity_user_name", - "APIKeyEntity__APIKeyEntity_user"."avatarColor" AS "APIKeyEntity__APIKeyEntity_user_avatarColor", "APIKeyEntity__APIKeyEntity_user"."isAdmin" AS "APIKeyEntity__APIKeyEntity_user_isAdmin", "APIKeyEntity__APIKeyEntity_user"."email" AS "APIKeyEntity__APIKeyEntity_user_email", "APIKeyEntity__APIKeyEntity_user"."storageLabel" AS "APIKeyEntity__APIKeyEntity_user_storageLabel", @@ -22,7 +21,6 @@ FROM "APIKeyEntity__APIKeyEntity_user"."deletedAt" AS "APIKeyEntity__APIKeyEntity_user_deletedAt", "APIKeyEntity__APIKeyEntity_user"."status" AS "APIKeyEntity__APIKeyEntity_user_status", "APIKeyEntity__APIKeyEntity_user"."updatedAt" AS "APIKeyEntity__APIKeyEntity_user_updatedAt", - "APIKeyEntity__APIKeyEntity_user"."memoriesEnabled" AS "APIKeyEntity__APIKeyEntity_user_memoriesEnabled", "APIKeyEntity__APIKeyEntity_user"."quotaSizeInBytes" AS "APIKeyEntity__APIKeyEntity_user_quotaSizeInBytes", "APIKeyEntity__APIKeyEntity_user"."quotaUsageInBytes" AS "APIKeyEntity__APIKeyEntity_user_quotaUsageInBytes" FROM diff --git a/server/src/queries/library.repository.sql b/server/src/queries/library.repository.sql index 700a71048a..7f1e0eff93 100644 --- a/server/src/queries/library.repository.sql +++ b/server/src/queries/library.repository.sql @@ -17,7 +17,6 @@ FROM "LibraryEntity"."refreshedAt" AS "LibraryEntity_refreshedAt", "LibraryEntity__LibraryEntity_owner"."id" AS "LibraryEntity__LibraryEntity_owner_id", "LibraryEntity__LibraryEntity_owner"."name" AS "LibraryEntity__LibraryEntity_owner_name", - "LibraryEntity__LibraryEntity_owner"."avatarColor" AS "LibraryEntity__LibraryEntity_owner_avatarColor", "LibraryEntity__LibraryEntity_owner"."isAdmin" AS "LibraryEntity__LibraryEntity_owner_isAdmin", "LibraryEntity__LibraryEntity_owner"."email" AS "LibraryEntity__LibraryEntity_owner_email", "LibraryEntity__LibraryEntity_owner"."storageLabel" AS "LibraryEntity__LibraryEntity_owner_storageLabel", @@ -28,7 +27,6 @@ FROM "LibraryEntity__LibraryEntity_owner"."deletedAt" AS "LibraryEntity__LibraryEntity_owner_deletedAt", "LibraryEntity__LibraryEntity_owner"."status" AS "LibraryEntity__LibraryEntity_owner_status", "LibraryEntity__LibraryEntity_owner"."updatedAt" AS "LibraryEntity__LibraryEntity_owner_updatedAt", - "LibraryEntity__LibraryEntity_owner"."memoriesEnabled" AS "LibraryEntity__LibraryEntity_owner_memoriesEnabled", "LibraryEntity__LibraryEntity_owner"."quotaSizeInBytes" AS "LibraryEntity__LibraryEntity_owner_quotaSizeInBytes", "LibraryEntity__LibraryEntity_owner"."quotaUsageInBytes" AS "LibraryEntity__LibraryEntity_owner_quotaUsageInBytes" FROM @@ -89,7 +87,6 @@ SELECT "LibraryEntity"."refreshedAt" AS "LibraryEntity_refreshedAt", "LibraryEntity__LibraryEntity_owner"."id" AS "LibraryEntity__LibraryEntity_owner_id", "LibraryEntity__LibraryEntity_owner"."name" AS "LibraryEntity__LibraryEntity_owner_name", - "LibraryEntity__LibraryEntity_owner"."avatarColor" AS "LibraryEntity__LibraryEntity_owner_avatarColor", "LibraryEntity__LibraryEntity_owner"."isAdmin" AS "LibraryEntity__LibraryEntity_owner_isAdmin", "LibraryEntity__LibraryEntity_owner"."email" AS "LibraryEntity__LibraryEntity_owner_email", "LibraryEntity__LibraryEntity_owner"."storageLabel" AS "LibraryEntity__LibraryEntity_owner_storageLabel", @@ -100,7 +97,6 @@ SELECT "LibraryEntity__LibraryEntity_owner"."deletedAt" AS "LibraryEntity__LibraryEntity_owner_deletedAt", "LibraryEntity__LibraryEntity_owner"."status" AS "LibraryEntity__LibraryEntity_owner_status", "LibraryEntity__LibraryEntity_owner"."updatedAt" AS "LibraryEntity__LibraryEntity_owner_updatedAt", - "LibraryEntity__LibraryEntity_owner"."memoriesEnabled" AS "LibraryEntity__LibraryEntity_owner_memoriesEnabled", "LibraryEntity__LibraryEntity_owner"."quotaSizeInBytes" AS "LibraryEntity__LibraryEntity_owner_quotaSizeInBytes", "LibraryEntity__LibraryEntity_owner"."quotaUsageInBytes" AS "LibraryEntity__LibraryEntity_owner_quotaUsageInBytes" FROM @@ -128,7 +124,6 @@ SELECT "LibraryEntity"."refreshedAt" AS "LibraryEntity_refreshedAt", "LibraryEntity__LibraryEntity_owner"."id" AS "LibraryEntity__LibraryEntity_owner_id", "LibraryEntity__LibraryEntity_owner"."name" AS "LibraryEntity__LibraryEntity_owner_name", - "LibraryEntity__LibraryEntity_owner"."avatarColor" AS "LibraryEntity__LibraryEntity_owner_avatarColor", "LibraryEntity__LibraryEntity_owner"."isAdmin" AS "LibraryEntity__LibraryEntity_owner_isAdmin", "LibraryEntity__LibraryEntity_owner"."email" AS "LibraryEntity__LibraryEntity_owner_email", "LibraryEntity__LibraryEntity_owner"."storageLabel" AS "LibraryEntity__LibraryEntity_owner_storageLabel", @@ -139,7 +134,6 @@ SELECT "LibraryEntity__LibraryEntity_owner"."deletedAt" AS "LibraryEntity__LibraryEntity_owner_deletedAt", "LibraryEntity__LibraryEntity_owner"."status" AS "LibraryEntity__LibraryEntity_owner_status", "LibraryEntity__LibraryEntity_owner"."updatedAt" AS "LibraryEntity__LibraryEntity_owner_updatedAt", - "LibraryEntity__LibraryEntity_owner"."memoriesEnabled" AS "LibraryEntity__LibraryEntity_owner_memoriesEnabled", "LibraryEntity__LibraryEntity_owner"."quotaSizeInBytes" AS "LibraryEntity__LibraryEntity_owner_quotaSizeInBytes", "LibraryEntity__LibraryEntity_owner"."quotaUsageInBytes" AS "LibraryEntity__LibraryEntity_owner_quotaUsageInBytes" FROM @@ -166,7 +160,6 @@ SELECT "LibraryEntity"."refreshedAt" AS "LibraryEntity_refreshedAt", "LibraryEntity__LibraryEntity_owner"."id" AS "LibraryEntity__LibraryEntity_owner_id", "LibraryEntity__LibraryEntity_owner"."name" AS "LibraryEntity__LibraryEntity_owner_name", - "LibraryEntity__LibraryEntity_owner"."avatarColor" AS "LibraryEntity__LibraryEntity_owner_avatarColor", "LibraryEntity__LibraryEntity_owner"."isAdmin" AS "LibraryEntity__LibraryEntity_owner_isAdmin", "LibraryEntity__LibraryEntity_owner"."email" AS "LibraryEntity__LibraryEntity_owner_email", "LibraryEntity__LibraryEntity_owner"."storageLabel" AS "LibraryEntity__LibraryEntity_owner_storageLabel", @@ -177,7 +170,6 @@ SELECT "LibraryEntity__LibraryEntity_owner"."deletedAt" AS "LibraryEntity__LibraryEntity_owner_deletedAt", "LibraryEntity__LibraryEntity_owner"."status" AS "LibraryEntity__LibraryEntity_owner_status", "LibraryEntity__LibraryEntity_owner"."updatedAt" AS "LibraryEntity__LibraryEntity_owner_updatedAt", - "LibraryEntity__LibraryEntity_owner"."memoriesEnabled" AS "LibraryEntity__LibraryEntity_owner_memoriesEnabled", "LibraryEntity__LibraryEntity_owner"."quotaSizeInBytes" AS "LibraryEntity__LibraryEntity_owner_quotaSizeInBytes", "LibraryEntity__LibraryEntity_owner"."quotaUsageInBytes" AS "LibraryEntity__LibraryEntity_owner_quotaUsageInBytes" FROM diff --git a/server/src/queries/session.repository.sql b/server/src/queries/session.repository.sql index 87c1b55c9b..b26b291e8b 100644 --- a/server/src/queries/session.repository.sql +++ b/server/src/queries/session.repository.sql @@ -27,7 +27,6 @@ FROM "SessionEntity"."deviceOS" AS "SessionEntity_deviceOS", "SessionEntity__SessionEntity_user"."id" AS "SessionEntity__SessionEntity_user_id", "SessionEntity__SessionEntity_user"."name" AS "SessionEntity__SessionEntity_user_name", - "SessionEntity__SessionEntity_user"."avatarColor" AS "SessionEntity__SessionEntity_user_avatarColor", "SessionEntity__SessionEntity_user"."isAdmin" AS "SessionEntity__SessionEntity_user_isAdmin", "SessionEntity__SessionEntity_user"."email" AS "SessionEntity__SessionEntity_user_email", "SessionEntity__SessionEntity_user"."storageLabel" AS "SessionEntity__SessionEntity_user_storageLabel", @@ -38,7 +37,6 @@ FROM "SessionEntity__SessionEntity_user"."deletedAt" AS "SessionEntity__SessionEntity_user_deletedAt", "SessionEntity__SessionEntity_user"."status" AS "SessionEntity__SessionEntity_user_status", "SessionEntity__SessionEntity_user"."updatedAt" AS "SessionEntity__SessionEntity_user_updatedAt", - "SessionEntity__SessionEntity_user"."memoriesEnabled" AS "SessionEntity__SessionEntity_user_memoriesEnabled", "SessionEntity__SessionEntity_user"."quotaSizeInBytes" AS "SessionEntity__SessionEntity_user_quotaSizeInBytes", "SessionEntity__SessionEntity_user"."quotaUsageInBytes" AS "SessionEntity__SessionEntity_user_quotaUsageInBytes" FROM diff --git a/server/src/queries/shared.link.repository.sql b/server/src/queries/shared.link.repository.sql index 6ae80b3e6a..09f0cf7cb5 100644 --- a/server/src/queries/shared.link.repository.sql +++ b/server/src/queries/shared.link.repository.sql @@ -147,7 +147,6 @@ FROM "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f"."fps" AS "d9f2f4dd8920bad1d6907cdb1d699732daff3c2f_fps", "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."id" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_id", "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."name" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_name", - "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."avatarColor" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_avatarColor", "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."isAdmin" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_isAdmin", "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."email" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_email", "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."storageLabel" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_storageLabel", @@ -158,7 +157,6 @@ FROM "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."deletedAt" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_deletedAt", "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."status" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_status", "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."updatedAt" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_updatedAt", - "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."memoriesEnabled" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_memoriesEnabled", "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."quotaSizeInBytes" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_quotaSizeInBytes", "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."quotaUsageInBytes" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_quotaUsageInBytes" FROM @@ -252,7 +250,6 @@ SELECT "SharedLinkEntity__SharedLinkEntity_album"."order" AS "SharedLinkEntity__SharedLinkEntity_album_order", "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."id" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_id", "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."name" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_name", - "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."avatarColor" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_avatarColor", "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."isAdmin" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_isAdmin", "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."email" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_email", "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."storageLabel" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_storageLabel", @@ -263,7 +260,6 @@ SELECT "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."deletedAt" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_deletedAt", "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."status" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_status", "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."updatedAt" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_updatedAt", - "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."memoriesEnabled" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_memoriesEnabled", "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."quotaSizeInBytes" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_quotaSizeInBytes", "6d7fd45329a05fd86b3dbcacde87fe76e33a422d"."quotaUsageInBytes" AS "6d7fd45329a05fd86b3dbcacde87fe76e33a422d_quotaUsageInBytes" FROM @@ -306,7 +302,6 @@ FROM "SharedLinkEntity"."albumId" AS "SharedLinkEntity_albumId", "SharedLinkEntity__SharedLinkEntity_user"."id" AS "SharedLinkEntity__SharedLinkEntity_user_id", "SharedLinkEntity__SharedLinkEntity_user"."name" AS "SharedLinkEntity__SharedLinkEntity_user_name", - "SharedLinkEntity__SharedLinkEntity_user"."avatarColor" AS "SharedLinkEntity__SharedLinkEntity_user_avatarColor", "SharedLinkEntity__SharedLinkEntity_user"."isAdmin" AS "SharedLinkEntity__SharedLinkEntity_user_isAdmin", "SharedLinkEntity__SharedLinkEntity_user"."email" AS "SharedLinkEntity__SharedLinkEntity_user_email", "SharedLinkEntity__SharedLinkEntity_user"."storageLabel" AS "SharedLinkEntity__SharedLinkEntity_user_storageLabel", @@ -317,7 +312,6 @@ FROM "SharedLinkEntity__SharedLinkEntity_user"."deletedAt" AS "SharedLinkEntity__SharedLinkEntity_user_deletedAt", "SharedLinkEntity__SharedLinkEntity_user"."status" AS "SharedLinkEntity__SharedLinkEntity_user_status", "SharedLinkEntity__SharedLinkEntity_user"."updatedAt" AS "SharedLinkEntity__SharedLinkEntity_user_updatedAt", - "SharedLinkEntity__SharedLinkEntity_user"."memoriesEnabled" AS "SharedLinkEntity__SharedLinkEntity_user_memoriesEnabled", "SharedLinkEntity__SharedLinkEntity_user"."quotaSizeInBytes" AS "SharedLinkEntity__SharedLinkEntity_user_quotaSizeInBytes", "SharedLinkEntity__SharedLinkEntity_user"."quotaUsageInBytes" AS "SharedLinkEntity__SharedLinkEntity_user_quotaUsageInBytes" FROM diff --git a/server/src/queries/user.repository.sql b/server/src/queries/user.repository.sql index d27b83fdd7..64d4e12643 100644 --- a/server/src/queries/user.repository.sql +++ b/server/src/queries/user.repository.sql @@ -4,7 +4,6 @@ SELECT "UserEntity"."id" AS "UserEntity_id", "UserEntity"."name" AS "UserEntity_name", - "UserEntity"."avatarColor" AS "UserEntity_avatarColor", "UserEntity"."isAdmin" AS "UserEntity_isAdmin", "UserEntity"."email" AS "UserEntity_email", "UserEntity"."storageLabel" AS "UserEntity_storageLabel", @@ -15,7 +14,6 @@ SELECT "UserEntity"."deletedAt" AS "UserEntity_deletedAt", "UserEntity"."status" AS "UserEntity_status", "UserEntity"."updatedAt" AS "UserEntity_updatedAt", - "UserEntity"."memoriesEnabled" AS "UserEntity_memoriesEnabled", "UserEntity"."quotaSizeInBytes" AS "UserEntity_quotaSizeInBytes", "UserEntity"."quotaUsageInBytes" AS "UserEntity_quotaUsageInBytes" FROM @@ -51,7 +49,6 @@ LIMIT SELECT "user"."id" AS "user_id", "user"."name" AS "user_name", - "user"."avatarColor" AS "user_avatarColor", "user"."isAdmin" AS "user_isAdmin", "user"."email" AS "user_email", "user"."storageLabel" AS "user_storageLabel", @@ -62,7 +59,6 @@ SELECT "user"."deletedAt" AS "user_deletedAt", "user"."status" AS "user_status", "user"."updatedAt" AS "user_updatedAt", - "user"."memoriesEnabled" AS "user_memoriesEnabled", "user"."quotaSizeInBytes" AS "user_quotaSizeInBytes", "user"."quotaUsageInBytes" AS "user_quotaUsageInBytes" FROM @@ -75,7 +71,6 @@ WHERE SELECT "UserEntity"."id" AS "UserEntity_id", "UserEntity"."name" AS "UserEntity_name", - "UserEntity"."avatarColor" AS "UserEntity_avatarColor", "UserEntity"."isAdmin" AS "UserEntity_isAdmin", "UserEntity"."email" AS "UserEntity_email", "UserEntity"."storageLabel" AS "UserEntity_storageLabel", @@ -86,7 +81,6 @@ SELECT "UserEntity"."deletedAt" AS "UserEntity_deletedAt", "UserEntity"."status" AS "UserEntity_status", "UserEntity"."updatedAt" AS "UserEntity_updatedAt", - "UserEntity"."memoriesEnabled" AS "UserEntity_memoriesEnabled", "UserEntity"."quotaSizeInBytes" AS "UserEntity_quotaSizeInBytes", "UserEntity"."quotaUsageInBytes" AS "UserEntity_quotaUsageInBytes" FROM @@ -101,7 +95,6 @@ LIMIT SELECT "UserEntity"."id" AS "UserEntity_id", "UserEntity"."name" AS "UserEntity_name", - "UserEntity"."avatarColor" AS "UserEntity_avatarColor", "UserEntity"."isAdmin" AS "UserEntity_isAdmin", "UserEntity"."email" AS "UserEntity_email", "UserEntity"."storageLabel" AS "UserEntity_storageLabel", @@ -112,7 +105,6 @@ SELECT "UserEntity"."deletedAt" AS "UserEntity_deletedAt", "UserEntity"."status" AS "UserEntity_status", "UserEntity"."updatedAt" AS "UserEntity_updatedAt", - "UserEntity"."memoriesEnabled" AS "UserEntity_memoriesEnabled", "UserEntity"."quotaSizeInBytes" AS "UserEntity_quotaSizeInBytes", "UserEntity"."quotaUsageInBytes" AS "UserEntity_quotaUsageInBytes" FROM diff --git a/server/src/repositories/user.repository.ts b/server/src/repositories/user.repository.ts index 6829bb024a..7b7861a8de 100644 --- a/server/src/repositories/user.repository.ts +++ b/server/src/repositories/user.repository.ts @@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { DummyValue, GenerateSql } from 'src/decorators'; import { AssetEntity } from 'src/entities/asset.entity'; +import { UserMetadata, UserMetadataEntity, UserMetadataKey } from 'src/entities/user-metadata.entity'; import { UserEntity } from 'src/entities/user.entity'; import { IUserRepository, @@ -18,6 +19,7 @@ export class UserRepository implements IUserRepository { constructor( @InjectRepository(AssetEntity) private assetRepository: Repository, @InjectRepository(UserEntity) private userRepository: Repository, + @InjectRepository(UserMetadataEntity) private metadataRepository: Repository, ) {} async get(userId: string, options: UserFindOptions): Promise { @@ -25,6 +27,9 @@ export class UserRepository implements IUserRepository { return this.userRepository.findOne({ where: { id: userId }, withDeleted: options.withDeleted, + relations: { + metadata: true, + }, }); } @@ -69,6 +74,9 @@ export class UserRepository implements IUserRepository { order: { createdAt: 'DESC', }, + relations: { + metadata: true, + }, }); } @@ -81,6 +89,13 @@ export class UserRepository implements IUserRepository { return this.save({ ...user, id }); } + async upsertMetadata( + id: string, + { key, value }: { key: T; value: UserMetadata[T] }, + ) { + await this.metadataRepository.upsert({ userId: id, key, value }, { conflictPaths: { userId: true, key: true } }); + } + async delete(user: UserEntity, hard?: boolean): Promise { return hard ? this.userRepository.remove(user) : this.userRepository.softRemove(user); } @@ -142,6 +157,12 @@ export class UserRepository implements IUserRepository { private async save(user: Partial) { const { id } = await this.userRepository.save(user); - return this.userRepository.findOneOrFail({ where: { id }, withDeleted: true }); + return this.userRepository.findOneOrFail({ + where: { id }, + withDeleted: true, + relations: { + metadata: true, + }, + }); } } diff --git a/server/src/services/auth.service.spec.ts b/server/src/services/auth.service.spec.ts index b93599b38a..34b8d9a550 100644 --- a/server/src/services/auth.service.spec.ts +++ b/server/src/services/auth.service.spec.ts @@ -4,6 +4,7 @@ import { Issuer, generators } from 'openid-client'; import { Socket } from 'socket.io'; import { AuthType } from 'src/constants'; import { AuthDto, SignUpDto } from 'src/dtos/auth.dto'; +import { UserMetadataEntity } from 'src/entities/user-metadata.entity'; import { UserEntity } from 'src/entities/user.entity'; import { IKeyRepository } from 'src/interfaces/api-key.interface'; import { ICryptoRepository } from 'src/interfaces/crypto.interface'; @@ -248,8 +249,13 @@ describe('AuthService', () => { it('should sign up the admin', async () => { userMock.getAdmin.mockResolvedValue(null); - userMock.create.mockResolvedValue({ ...dto, id: 'admin', createdAt: new Date('2021-01-01') } as UserEntity); - await expect(sut.adminSignUp(dto)).resolves.toEqual({ + userMock.create.mockResolvedValue({ + ...dto, + id: 'admin', + createdAt: new Date('2021-01-01'), + metadata: [] as UserMetadataEntity[], + } as UserEntity); + await expect(sut.adminSignUp(dto)).resolves.toMatchObject({ avatarColor: expect.any(String), id: 'admin', createdAt: new Date('2021-01-01'), diff --git a/server/src/services/partner.service.spec.ts b/server/src/services/partner.service.spec.ts index 70c73b0d94..8fe93e7961 100644 --- a/server/src/services/partner.service.spec.ts +++ b/server/src/services/partner.service.spec.ts @@ -1,6 +1,6 @@ import { BadRequestException } from '@nestjs/common'; import { PartnerResponseDto } from 'src/dtos/partner.dto'; -import { UserAvatarColor } from 'src/entities/user.entity'; +import { UserAvatarColor } from 'src/entities/user-metadata.entity'; import { IAccessRepository } from 'src/interfaces/access.interface'; import { IPartnerRepository, PartnerDirection } from 'src/interfaces/partner.interface'; import { PartnerService } from 'src/services/partner.service'; @@ -23,7 +23,7 @@ const responseDto = { deletedAt: null, updatedAt: new Date('2021-01-01'), memoriesEnabled: true, - avatarColor: UserAvatarColor.PRIMARY, + avatarColor: UserAvatarColor.GRAY, quotaSizeInBytes: null, inTimeline: true, quotaUsageInBytes: 0, diff --git a/server/src/services/user.service.spec.ts b/server/src/services/user.service.spec.ts index da9c375131..e96cb0e663 100644 --- a/server/src/services/user.service.spec.ts +++ b/server/src/services/user.service.spec.ts @@ -138,13 +138,17 @@ describe(UserService.name, () => { expect(userMock.update).toHaveBeenCalledWith(userStub.user1.id, { id: userStub.user1.id, storageLabel: null, + updatedAt: expect.any(Date), }); }); it('should omit a storage label set by non-admin users', async () => { userMock.update.mockResolvedValue(userStub.user1); await sut.update({ user: userStub.user1 }, { id: userStub.user1.id, storageLabel: 'admin' }); - expect(userMock.update).toHaveBeenCalledWith(userStub.user1.id, { id: userStub.user1.id }); + expect(userMock.update).toHaveBeenCalledWith(userStub.user1.id, { + id: userStub.user1.id, + updatedAt: expect.any(Date), + }); }); it('user can only update its information', async () => { @@ -174,6 +178,7 @@ describe(UserService.name, () => { expect(userMock.update).toHaveBeenCalledWith(userStub.user1.id, { id: 'user-id', email: 'updated@test.com', + updatedAt: expect.any(Date), }); }); @@ -210,6 +215,7 @@ describe(UserService.name, () => { expect(userMock.update).toHaveBeenCalledWith(userStub.user1.id, { id: 'user-id', shouldChangePassword: true, + updatedAt: expect.any(Date), }); }); @@ -231,7 +237,7 @@ describe(UserService.name, () => { await sut.update(authStub.admin, dto); - expect(userMock.update).toHaveBeenCalledWith(userStub.admin.id, dto); + expect(userMock.update).toHaveBeenCalledWith(userStub.admin.id, { ...dto, updatedAt: expect.any(Date) }); }); it('should not let the another user become an admin', async () => { diff --git a/server/src/services/user.service.ts b/server/src/services/user.service.ts index 0df2ecae94..d546705d3c 100644 --- a/server/src/services/user.service.ts +++ b/server/src/services/user.service.ts @@ -6,6 +6,7 @@ import { UserCore } from 'src/cores/user.core'; import { AuthDto } from 'src/dtos/auth.dto'; import { CreateProfileImageResponseDto, mapCreateProfileImageResponse } from 'src/dtos/user-profile.dto'; import { CreateUserDto, DeleteUserDto, UpdateUserDto, UserResponseDto, mapUser } from 'src/dtos/user.dto'; +import { UserMetadataKey } from 'src/entities/user-metadata.entity'; import { UserEntity, UserStatus } from 'src/entities/user.entity'; import { IAlbumRepository } from 'src/interfaces/album.interface'; import { ICryptoRepository } from 'src/interfaces/crypto.interface'; @@ -16,6 +17,7 @@ import { IStorageRepository } from 'src/interfaces/storage.interface'; import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface'; import { IUserRepository, UserFindOptions } from 'src/interfaces/user.interface'; import { CacheControl, ImmichFileResponse } from 'src/utils/file'; +import { getPreferences, getPreferencesPartial } from 'src/utils/preferences'; @Injectable() export class UserService { @@ -61,9 +63,21 @@ export class UserService { } async create(dto: CreateUserDto): Promise { - const user = await this.userCore.createUser(dto); - const tempPassword = user.shouldChangePassword ? dto.password : undefined; - if (dto.notify) { + const { memoriesEnabled, notify, ...rest } = dto; + let user = await this.userCore.createUser(rest); + + // TODO remove and replace with entire dto.preferences config + if (memoriesEnabled === false) { + await this.userRepository.upsertMetadata(user.id, { + key: UserMetadataKey.PREFERENCES, + value: { memories: { enabled: false } }, + }); + + user = await this.findOrFail(user.id, {}); + } + + const tempPassword = user.shouldChangePassword ? rest.password : undefined; + if (notify) { await this.jobRepository.queue({ name: JobName.NOTIFY_SIGNUP, data: { id: user.id, tempPassword } }); } return mapUser(user); @@ -76,7 +90,28 @@ export class UserService { await this.userRepository.syncUsage(dto.id); } - return this.userCore.updateUser(auth.user, dto.id, dto).then(mapUser); + // TODO replace with entire preferences object + if (dto.memoriesEnabled !== undefined || dto.avatarColor) { + const newPreferences = getPreferences(user); + if (dto.memoriesEnabled !== undefined) { + newPreferences.memories.enabled = dto.memoriesEnabled; + delete dto.memoriesEnabled; + } + + if (dto.avatarColor) { + newPreferences.avatar.color = dto.avatarColor; + delete dto.avatarColor; + } + + await this.userRepository.upsertMetadata(dto.id, { + key: UserMetadataKey.PREFERENCES, + value: getPreferencesPartial(user, newPreferences), + }); + } + + const updatedUser = await this.userCore.updateUser(auth.user, dto.id, dto); + + return mapUser(updatedUser); } async delete(auth: AuthDto, id: string, dto: DeleteUserDto): Promise { diff --git a/server/src/utils/preferences.ts b/server/src/utils/preferences.ts new file mode 100644 index 0000000000..ae10c24fc9 --- /dev/null +++ b/server/src/utils/preferences.ts @@ -0,0 +1,39 @@ +import _ from 'lodash'; +import { UserMetadataKey, UserPreferences, getDefaultPreferences } from 'src/entities/user-metadata.entity'; +import { UserEntity } from 'src/entities/user.entity'; +import { getKeysDeep } from 'src/utils/misc'; +import { DeepPartial } from 'typeorm'; + +export const getPreferences = (user: UserEntity) => { + const preferences = getDefaultPreferences(user); + if (!user.metadata) { + return preferences; + } + + const item = user.metadata.find(({ key }) => key === UserMetadataKey.PREFERENCES); + const partial = item?.value || {}; + for (const property of getKeysDeep(partial)) { + _.set(preferences, property, _.get(partial, property)); + } + + return preferences; +}; + +export const getPreferencesPartial = (user: { email: string }, newPreferences: UserPreferences) => { + const defaultPreferences = getDefaultPreferences(user); + const partial: DeepPartial = {}; + for (const property of getKeysDeep(defaultPreferences)) { + const newValue = _.get(newPreferences, property); + const isEmpty = newValue === undefined || newValue === null || newValue === ''; + const defaultValue = _.get(defaultPreferences, property); + const isEqual = newValue === defaultValue || _.isEqual(newValue, defaultValue); + + if (isEmpty || isEqual) { + continue; + } + + _.set(partial, property, newValue); + } + + return partial; +}; diff --git a/server/test/fixtures/user.stub.ts b/server/test/fixtures/user.stub.ts index 5cf5acfc3b..cb82dfe26c 100644 --- a/server/test/fixtures/user.stub.ts +++ b/server/test/fixtures/user.stub.ts @@ -1,4 +1,5 @@ -import { UserAvatarColor, UserEntity } from 'src/entities/user.entity'; +import { UserAvatarColor, UserMetadataKey } from 'src/entities/user-metadata.entity'; +import { UserEntity } from 'src/entities/user.entity'; import { authStub } from 'test/fixtures/auth.stub'; export const userDto = { @@ -39,8 +40,7 @@ export const userStub = { updatedAt: new Date('2021-01-01'), tags: [], assets: [], - memoriesEnabled: true, - avatarColor: UserAvatarColor.PRIMARY, + metadata: [], quotaSizeInBytes: null, quotaUsageInBytes: 0, }), @@ -57,8 +57,14 @@ export const userStub = { updatedAt: new Date('2021-01-01'), tags: [], assets: [], - memoriesEnabled: true, - avatarColor: UserAvatarColor.PRIMARY, + metadata: [ + { + user: authStub.user1.user, + userId: authStub.user1.user.id, + key: UserMetadataKey.PREFERENCES, + value: { avatar: { color: UserAvatarColor.PRIMARY } }, + }, + ], quotaSizeInBytes: null, quotaUsageInBytes: 0, }), @@ -75,8 +81,6 @@ export const userStub = { updatedAt: new Date('2021-01-01'), tags: [], assets: [], - memoriesEnabled: true, - avatarColor: UserAvatarColor.PRIMARY, quotaSizeInBytes: null, quotaUsageInBytes: 0, }), @@ -93,8 +97,6 @@ export const userStub = { updatedAt: new Date('2021-01-01'), tags: [], assets: [], - memoriesEnabled: true, - avatarColor: UserAvatarColor.PRIMARY, quotaSizeInBytes: null, quotaUsageInBytes: 0, }), @@ -111,8 +113,6 @@ export const userStub = { updatedAt: new Date('2021-01-01'), tags: [], assets: [], - memoriesEnabled: true, - avatarColor: UserAvatarColor.PRIMARY, quotaSizeInBytes: null, quotaUsageInBytes: 0, }), @@ -129,8 +129,6 @@ export const userStub = { updatedAt: new Date('2021-01-01'), tags: [], assets: [], - memoriesEnabled: true, - avatarColor: UserAvatarColor.PRIMARY, quotaSizeInBytes: null, quotaUsageInBytes: 0, }), diff --git a/server/test/repositories/user.repository.mock.ts b/server/test/repositories/user.repository.mock.ts index 5f2e2f083e..c3b9dc0f3d 100644 --- a/server/test/repositories/user.repository.mock.ts +++ b/server/test/repositories/user.repository.mock.ts @@ -22,5 +22,6 @@ export const newUserRepositoryMock = (reset = true): Mocked => hasAdmin: vitest.fn(), updateUsage: vitest.fn(), syncUsage: vitest.fn(), + upsertMetadata: vitest.fn(), }; };