mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-06-03 00:19:57 -04:00
refactor(backend): use @hedgedoc/commons DTOs
Co-authored-by: Erik Michelson <github@erik.michelson.eu> Signed-off-by: Erik Michelson <github@erik.michelson.eu> Signed-off-by: Philip Molares <philip.molares@udo.edu>
This commit is contained in:
parent
7285c2bc50
commit
b11dbd51c8
94 changed files with 514 additions and 1642 deletions
|
@ -1,77 +0,0 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2024 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
||||
import { Type } from 'class-transformer';
|
||||
import { IsLowercase, IsOptional, IsString } from 'class-validator';
|
||||
|
||||
import { BaseDto } from '../utils/base.dto.';
|
||||
import { Username } from '../utils/username';
|
||||
|
||||
export class UserInfoDto extends BaseDto {
|
||||
/**
|
||||
* The username
|
||||
* @example "john.smith"
|
||||
*/
|
||||
@Type(() => String)
|
||||
@IsString()
|
||||
@IsLowercase()
|
||||
@ApiProperty()
|
||||
username: Username;
|
||||
|
||||
/**
|
||||
* The display name
|
||||
* @example "John Smith"
|
||||
*/
|
||||
@IsString()
|
||||
@ApiProperty()
|
||||
displayName: string;
|
||||
|
||||
/**
|
||||
* URL of the profile picture
|
||||
* @example "https://hedgedoc.example.com/uploads/johnsmith.png"
|
||||
*/
|
||||
@ApiPropertyOptional({
|
||||
format: 'uri',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
photoUrl?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* This DTO contains all attributes of the standard UserInfoDto
|
||||
* in addition to the email address.
|
||||
*/
|
||||
export class FullUserInfoDto extends UserInfoDto {
|
||||
/**
|
||||
* Email address of the user
|
||||
* @example "john.smith@example.com"
|
||||
*/
|
||||
@ApiPropertyOptional({
|
||||
format: 'email',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
email?: string;
|
||||
}
|
||||
|
||||
export class FullUserInfoWithIdDto extends FullUserInfoDto {
|
||||
/**
|
||||
* The user's ID
|
||||
* @example 42
|
||||
*/
|
||||
@IsString()
|
||||
id: string;
|
||||
}
|
||||
|
||||
export class UserLoginInfoDto extends UserInfoDto {
|
||||
/**
|
||||
* Identifier of the auth provider that was used to log in
|
||||
*/
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
authProvider: string;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2024 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
@ -20,7 +20,6 @@ import { Group } from '../groups/group.entity';
|
|||
import { HistoryEntry } from '../history/history-entry.entity';
|
||||
import { MediaUpload } from '../media/media-upload.entity';
|
||||
import { Note } from '../notes/note.entity';
|
||||
import { Username } from '../utils/username';
|
||||
|
||||
@Entity()
|
||||
export class User {
|
||||
|
@ -30,7 +29,7 @@ export class User {
|
|||
@Column({
|
||||
unique: true,
|
||||
})
|
||||
username: Username;
|
||||
username: string;
|
||||
|
||||
@Column()
|
||||
displayName: string;
|
||||
|
@ -78,7 +77,7 @@ export class User {
|
|||
private constructor() {}
|
||||
|
||||
public static create(
|
||||
username: Username,
|
||||
username: string,
|
||||
displayName: string,
|
||||
email?: string,
|
||||
photoUrl?: string,
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2024 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { IsBoolean, IsLowercase, IsString } from 'class-validator';
|
||||
|
||||
import { BaseDto } from '../utils/base.dto.';
|
||||
import { Username } from '../utils/username';
|
||||
|
||||
export class UsernameCheckDto extends BaseDto {
|
||||
// eslint-disable-next-line @darraghor/nestjs-typed/validated-non-primitive-property-needs-type-decorator
|
||||
@IsString()
|
||||
@IsLowercase()
|
||||
username: Username;
|
||||
}
|
||||
|
||||
export class UsernameCheckResponseDto extends BaseDto {
|
||||
@IsBoolean()
|
||||
usernameAvailable: boolean;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2024 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
@ -54,7 +54,7 @@ describe('UsersService', () => {
|
|||
.mockImplementationOnce(async (user: User): Promise<User> => user);
|
||||
});
|
||||
it('successfully creates a user', async () => {
|
||||
const user = await service.createUser(username, displayname);
|
||||
const user = await service.createUser(username, displayname, null, null);
|
||||
expect(user.username).toEqual(username);
|
||||
expect(user.displayName).toEqual(displayname);
|
||||
});
|
||||
|
@ -64,11 +64,11 @@ describe('UsersService', () => {
|
|||
throw new Error();
|
||||
});
|
||||
// create first user with username
|
||||
await service.createUser(username, displayname);
|
||||
await service.createUser(username, displayname, null, null);
|
||||
// attempt to create second user with username
|
||||
await expect(service.createUser(username, displayname)).rejects.toThrow(
|
||||
AlreadyInDBError,
|
||||
);
|
||||
await expect(
|
||||
service.createUser(username, displayname, null, null),
|
||||
).rejects.toThrow(AlreadyInDBError);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -134,7 +134,7 @@ describe('UsersService', () => {
|
|||
expect(photoUrl).toEqual(photo);
|
||||
});
|
||||
it('works if a user no photoUrl', () => {
|
||||
user.photo = undefined;
|
||||
user.photo = null;
|
||||
const photoUrl = service.getPhotoUrl(user);
|
||||
expect(photoUrl).toEqual('');
|
||||
});
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2024 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { REGEX_USERNAME } from '@hedgedoc/commons';
|
||||
import {
|
||||
FullUserInfoDto,
|
||||
LoginUserInfoDto,
|
||||
ProviderType,
|
||||
REGEX_USERNAME,
|
||||
UserInfoDto,
|
||||
} from '@hedgedoc/commons';
|
||||
import { BadRequestException, Inject, Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
|
@ -11,12 +17,6 @@ import { Repository } from 'typeorm';
|
|||
import AuthConfiguration, { AuthConfig } from '../config/auth.config';
|
||||
import { AlreadyInDBError, NotInDBError } from '../errors/errors';
|
||||
import { ConsoleLoggerService } from '../logger/console-logger.service';
|
||||
import { Username } from '../utils/username';
|
||||
import {
|
||||
FullUserInfoDto,
|
||||
UserInfoDto,
|
||||
UserLoginInfoDto,
|
||||
} from './user-info.dto';
|
||||
import { UserRelationEnum } from './user-relation.enum';
|
||||
import { User } from './user.entity';
|
||||
|
||||
|
@ -34,7 +34,7 @@ export class UsersService {
|
|||
/**
|
||||
* @async
|
||||
* Create a new user with a given username and displayName
|
||||
* @param {Username} username - the username the new user shall have
|
||||
* @param {string} username - the username the new user shall have
|
||||
* @param {string} displayName - the display name the new user shall have
|
||||
* @param {string} [email] - the email the new user shall have
|
||||
* @param {string} [photoUrl] - the photoUrl the new user shall have
|
||||
|
@ -43,17 +43,22 @@ export class UsersService {
|
|||
* @throws {AlreadyInDBError} the username is already taken.
|
||||
*/
|
||||
async createUser(
|
||||
username: Username,
|
||||
username: string,
|
||||
displayName: string,
|
||||
email?: string,
|
||||
photoUrl?: string,
|
||||
email: string | null,
|
||||
photoUrl: string | null,
|
||||
): Promise<User> {
|
||||
if (!REGEX_USERNAME.test(username)) {
|
||||
throw new BadRequestException(
|
||||
`The username '${username}' is not a valid username.`,
|
||||
);
|
||||
}
|
||||
const user = User.create(username, displayName, email, photoUrl);
|
||||
const user = User.create(
|
||||
username,
|
||||
displayName,
|
||||
email || undefined,
|
||||
photoUrl || undefined,
|
||||
);
|
||||
try {
|
||||
return await this.userRepository.save(user);
|
||||
} catch {
|
||||
|
@ -123,7 +128,7 @@ export class UsersService {
|
|||
* @param username - the username to check
|
||||
* @return {boolean} true if the user exists, false otherwise
|
||||
*/
|
||||
async checkIfUserExists(username: Username): Promise<boolean> {
|
||||
async checkIfUserExists(username: string): Promise<boolean> {
|
||||
const user = await this.userRepository.findOne({
|
||||
where: { username: username },
|
||||
});
|
||||
|
@ -133,12 +138,12 @@ export class UsersService {
|
|||
/**
|
||||
* @async
|
||||
* Get the user specified by the username
|
||||
* @param {Username} username the username by which the user is specified
|
||||
* @param {string} username the username by which the user is specified
|
||||
* @param {UserRelationEnum[]} [withRelations=[]] if the returned user object should contain certain relations
|
||||
* @return {User} the specified user
|
||||
*/
|
||||
async getUserByUsername(
|
||||
username: Username,
|
||||
username: string,
|
||||
withRelations: UserRelationEnum[] = [],
|
||||
): Promise<User> {
|
||||
const user = await this.userRepository.findOne({
|
||||
|
@ -191,7 +196,7 @@ export class UsersService {
|
|||
};
|
||||
}
|
||||
|
||||
toUserLoginInfoDto(user: User, authProvider: string): UserLoginInfoDto {
|
||||
return { ...this.toUserDto(user), authProvider };
|
||||
toLoginUserInfoDto(user: User, authProvider: ProviderType): LoginUserInfoDto {
|
||||
return { ...this.toFullUserDto(user), authProvider };
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue