mirror of
https://github.com/immich-app/immich
synced 2025-11-14 17:36:12 +00:00
feat(server): user metadata (#9650)
* feat(server): user metadata * add missing method to user mock * update migration to include cascades * update sql files * test: fix e2e * chore: clean up --------- Co-authored-by: Daniel Dietzler <mail@ddietzler.dev>
This commit is contained in:
parent
a4887bfa7e
commit
06ce8247cc
24 changed files with 267 additions and 126 deletions
|
|
@ -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,
|
||||
];
|
||||
|
|
|
|||
63
server/src/entities/user-metadata.entity.ts
Normal file
63
server/src/entities/user-metadata.entity.ts
Normal file
|
|
@ -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<T extends keyof UserMetadata = UserMetadataKey> {
|
||||
@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, Record<string, any>> {
|
||||
[UserMetadataKey.PREFERENCES]: DeepPartial<UserPreferences>;
|
||||
}
|
||||
|
|
@ -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[];
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue