refactor(server): user endpoints (#9730)
* refactor(server): user endpoints * fix repos * fix unit tests --------- Co-authored-by: Daniel Dietzler <mail@ddietzler.dev> Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsEnum, IsNotEmpty, IsString, ValidateIf } from 'class-validator';
|
||||
import { UserDto, mapSimpleUser } from 'src/dtos/user.dto';
|
||||
import { UserResponseDto, mapUser } from 'src/dtos/user.dto';
|
||||
import { ActivityEntity } from 'src/entities/activity.entity';
|
||||
import { Optional, ValidateUUID } from 'src/validation';
|
||||
|
||||
@@ -20,7 +20,7 @@ export class ActivityResponseDto {
|
||||
id!: string;
|
||||
createdAt!: Date;
|
||||
type!: ReactionType;
|
||||
user!: UserDto;
|
||||
user!: UserResponseDto;
|
||||
assetId!: string | null;
|
||||
comment?: string | null;
|
||||
}
|
||||
@@ -73,6 +73,6 @@ export function mapActivity(activity: ActivityEntity): ActivityResponseDto {
|
||||
createdAt: activity.createdAt,
|
||||
comment: activity.comment,
|
||||
type: activity.isLiked ? ReactionType.LIKE : ReactionType.COMMENT,
|
||||
user: mapSimpleUser(activity.user),
|
||||
user: mapUser(activity.user),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { plainToInstance } from 'class-transformer';
|
||||
import { validate } from 'class-validator';
|
||||
import { CreateUserDto, CreateUserOAuthDto, UpdateUserDto } from 'src/dtos/user.dto';
|
||||
import { UserAdminCreateDto, UserUpdateMeDto } from 'src/dtos/user.dto';
|
||||
|
||||
describe('update user DTO', () => {
|
||||
it('should allow emails without a tld', async () => {
|
||||
const someEmail = 'test@test';
|
||||
|
||||
const dto = plainToInstance(UpdateUserDto, {
|
||||
const dto = plainToInstance(UserUpdateMeDto, {
|
||||
email: someEmail,
|
||||
id: '3fe388e4-2078-44d7-b36c-39d9dee3a657',
|
||||
});
|
||||
@@ -18,22 +18,22 @@ describe('update user DTO', () => {
|
||||
|
||||
describe('create user DTO', () => {
|
||||
it('validates the email', async () => {
|
||||
const params: Partial<CreateUserDto> = {
|
||||
const params: Partial<UserAdminCreateDto> = {
|
||||
email: undefined,
|
||||
password: 'password',
|
||||
name: 'name',
|
||||
};
|
||||
let dto: CreateUserDto = plainToInstance(CreateUserDto, params);
|
||||
let dto: UserAdminCreateDto = plainToInstance(UserAdminCreateDto, params);
|
||||
let errors = await validate(dto);
|
||||
expect(errors).toHaveLength(1);
|
||||
|
||||
params.email = 'invalid email';
|
||||
dto = plainToInstance(CreateUserDto, params);
|
||||
dto = plainToInstance(UserAdminCreateDto, params);
|
||||
errors = await validate(dto);
|
||||
expect(errors).toHaveLength(1);
|
||||
|
||||
params.email = 'valid@email.com';
|
||||
dto = plainToInstance(CreateUserDto, params);
|
||||
dto = plainToInstance(UserAdminCreateDto, params);
|
||||
errors = await validate(dto);
|
||||
expect(errors).toHaveLength(0);
|
||||
});
|
||||
@@ -41,7 +41,7 @@ describe('create user DTO', () => {
|
||||
it('should allow emails without a tld', async () => {
|
||||
const someEmail = 'test@test';
|
||||
|
||||
const dto = plainToInstance(CreateUserDto, {
|
||||
const dto = plainToInstance(UserAdminCreateDto, {
|
||||
email: someEmail,
|
||||
password: 'some password',
|
||||
name: 'some name',
|
||||
@@ -51,18 +51,3 @@ describe('create user DTO', () => {
|
||||
expect(dto.email).toEqual(someEmail);
|
||||
});
|
||||
});
|
||||
|
||||
describe('create user oauth DTO', () => {
|
||||
it('should allow emails without a tld', async () => {
|
||||
const someEmail = 'test@test';
|
||||
|
||||
const dto = plainToInstance(CreateUserOAuthDto, {
|
||||
email: someEmail,
|
||||
oauthId: 'some oauth id',
|
||||
name: 'some name',
|
||||
});
|
||||
const errors = await validate(dto);
|
||||
expect(errors).toHaveLength(0);
|
||||
expect(dto.email).toEqual(someEmail);
|
||||
});
|
||||
});
|
||||
|
||||
+62
-50
@@ -1,12 +1,63 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { Transform } from 'class-transformer';
|
||||
import { IsBoolean, IsEmail, IsEnum, IsNotEmpty, IsNumber, IsPositive, IsString, IsUUID } from 'class-validator';
|
||||
import { IsBoolean, IsEmail, IsEnum, IsNotEmpty, IsNumber, IsPositive, IsString } from 'class-validator';
|
||||
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 {
|
||||
export class UserUpdateMeDto {
|
||||
@Optional()
|
||||
@IsEmail({ require_tld: false })
|
||||
@Transform(toEmail)
|
||||
email?: string;
|
||||
|
||||
// TODO: migrate to the other change password endpoint
|
||||
@Optional()
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
password?: string;
|
||||
|
||||
@Optional()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
name?: string;
|
||||
|
||||
@ValidateBoolean({ optional: true })
|
||||
memoriesEnabled?: boolean;
|
||||
|
||||
@Optional()
|
||||
@IsEnum(UserAvatarColor)
|
||||
@ApiProperty({ enumName: 'UserAvatarColor', enum: UserAvatarColor })
|
||||
avatarColor?: UserAvatarColor;
|
||||
}
|
||||
|
||||
export class UserResponseDto {
|
||||
id!: string;
|
||||
name!: string;
|
||||
email!: string;
|
||||
profileImagePath!: string;
|
||||
@IsEnum(UserAvatarColor)
|
||||
@ApiProperty({ enumName: 'UserAvatarColor', enum: UserAvatarColor })
|
||||
avatarColor!: UserAvatarColor;
|
||||
}
|
||||
|
||||
export const mapUser = (entity: UserEntity): UserResponseDto => {
|
||||
return {
|
||||
id: entity.id,
|
||||
email: entity.email,
|
||||
name: entity.name,
|
||||
profileImagePath: entity.profileImagePath,
|
||||
avatarColor: getPreferences(entity).avatar.color,
|
||||
};
|
||||
};
|
||||
|
||||
export class UserAdminSearchDto {
|
||||
@ValidateBoolean({ optional: true })
|
||||
withDeleted?: boolean;
|
||||
}
|
||||
|
||||
export class UserAdminCreateDto {
|
||||
@IsEmail({ require_tld: false })
|
||||
@Transform(toEmail)
|
||||
email!: string;
|
||||
@@ -41,23 +92,7 @@ export class CreateUserDto {
|
||||
notify?: boolean;
|
||||
}
|
||||
|
||||
export class CreateUserOAuthDto {
|
||||
@IsEmail({ require_tld: false })
|
||||
@Transform(({ value }) => value?.toLowerCase())
|
||||
email!: string;
|
||||
|
||||
@IsNotEmpty()
|
||||
oauthId!: string;
|
||||
|
||||
name?: string;
|
||||
}
|
||||
|
||||
export class DeleteUserDto {
|
||||
@ValidateBoolean({ optional: true })
|
||||
force?: boolean;
|
||||
}
|
||||
|
||||
export class UpdateUserDto {
|
||||
export class UserAdminUpdateDto {
|
||||
@Optional()
|
||||
@IsEmail({ require_tld: false })
|
||||
@Transform(toEmail)
|
||||
@@ -73,18 +108,10 @@ export class UpdateUserDto {
|
||||
@IsNotEmpty()
|
||||
name?: string;
|
||||
|
||||
@Optional()
|
||||
@Optional({ nullable: true })
|
||||
@IsString()
|
||||
@Transform(toSanitized)
|
||||
storageLabel?: string;
|
||||
|
||||
@IsNotEmpty()
|
||||
@IsUUID('4')
|
||||
@ApiProperty({ format: 'uuid' })
|
||||
id!: string;
|
||||
|
||||
@ValidateBoolean({ optional: true })
|
||||
isAdmin?: boolean;
|
||||
storageLabel?: string | null;
|
||||
|
||||
@ValidateBoolean({ optional: true })
|
||||
shouldChangePassword?: boolean;
|
||||
@@ -104,17 +131,12 @@ export class UpdateUserDto {
|
||||
quotaSizeInBytes?: number | null;
|
||||
}
|
||||
|
||||
export class UserDto {
|
||||
id!: string;
|
||||
name!: string;
|
||||
email!: string;
|
||||
profileImagePath!: string;
|
||||
@IsEnum(UserAvatarColor)
|
||||
@ApiProperty({ enumName: 'UserAvatarColor', enum: UserAvatarColor })
|
||||
avatarColor!: UserAvatarColor;
|
||||
export class UserAdminDeleteDto {
|
||||
@ValidateBoolean({ optional: true })
|
||||
force?: boolean;
|
||||
}
|
||||
|
||||
export class UserResponseDto extends UserDto {
|
||||
export class UserAdminResponseDto extends UserResponseDto {
|
||||
storageLabel!: string | null;
|
||||
shouldChangePassword!: boolean;
|
||||
isAdmin!: boolean;
|
||||
@@ -131,19 +153,9 @@ export class UserResponseDto extends UserDto {
|
||||
status!: string;
|
||||
}
|
||||
|
||||
export const mapSimpleUser = (entity: UserEntity): UserDto => {
|
||||
export function mapUserAdmin(entity: UserEntity): UserAdminResponseDto {
|
||||
return {
|
||||
id: entity.id,
|
||||
email: entity.email,
|
||||
name: entity.name,
|
||||
profileImagePath: entity.profileImagePath,
|
||||
avatarColor: getPreferences(entity).avatar.color,
|
||||
};
|
||||
};
|
||||
|
||||
export function mapUser(entity: UserEntity): UserResponseDto {
|
||||
return {
|
||||
...mapSimpleUser(entity),
|
||||
...mapUser(entity),
|
||||
storageLabel: entity.storageLabel,
|
||||
shouldChangePassword: entity.shouldChangePassword,
|
||||
isAdmin: entity.isAdmin,
|
||||
|
||||
Reference in New Issue
Block a user