feat(user-info-dto): split email into separate DTO

The email address should only be available
in /me routes.
This commit splits the email address into a new FullUserInfoDto.

Signed-off-by: David Mehren <git@herrmehren.de>
This commit is contained in:
David Mehren 2022-02-20 22:18:51 +01:00
parent a7edf00ebc
commit 0394679134
7 changed files with 44 additions and 12 deletions

View file

@ -10,7 +10,7 @@ import { SessionGuard } from '../../../identity/session.guard';
import { ConsoleLoggerService } from '../../../logger/console-logger.service'; import { ConsoleLoggerService } from '../../../logger/console-logger.service';
import { MediaUploadDto } from '../../../media/media-upload.dto'; import { MediaUploadDto } from '../../../media/media-upload.dto';
import { MediaService } from '../../../media/media.service'; import { MediaService } from '../../../media/media.service';
import { UserInfoDto } from '../../../users/user-info.dto'; import { FullUserInfoDto } from '../../../users/user-info.dto';
import { User } from '../../../users/user.entity'; import { User } from '../../../users/user.entity';
import { UsersService } from '../../../users/users.service'; import { UsersService } from '../../../users/users.service';
import { OpenApi } from '../../utils/openapi.decorator'; import { OpenApi } from '../../utils/openapi.decorator';
@ -28,10 +28,11 @@ export class MeController {
) { ) {
this.logger.setContext(MeController.name); this.logger.setContext(MeController.name);
} }
@Get() @Get()
@OpenApi(200) @OpenApi(200)
getMe(@RequestUser() user: User): UserInfoDto { getMe(@RequestUser() user: User): FullUserInfoDto {
return this.userService.toUserDto(user); return this.userService.toFullUserDto(user);
} }
@Get('media') @Get('media')

View file

@ -24,7 +24,7 @@ import { MediaService } from '../../../media/media.service';
import { NoteMetadataDto } from '../../../notes/note-metadata.dto'; import { NoteMetadataDto } from '../../../notes/note-metadata.dto';
import { Note } from '../../../notes/note.entity'; import { Note } from '../../../notes/note.entity';
import { NotesService } from '../../../notes/notes.service'; import { NotesService } from '../../../notes/notes.service';
import { UserInfoDto } from '../../../users/user-info.dto'; import { FullUserInfoDto } from '../../../users/user-info.dto';
import { User } from '../../../users/user.entity'; import { User } from '../../../users/user.entity';
import { UsersService } from '../../../users/users.service'; import { UsersService } from '../../../users/users.service';
import { GetNoteInterceptor } from '../../utils/get-note.interceptor'; import { GetNoteInterceptor } from '../../utils/get-note.interceptor';
@ -52,10 +52,10 @@ export class MeController {
@OpenApi({ @OpenApi({
code: 200, code: 200,
description: 'The user information', description: 'The user information',
dto: UserInfoDto, dto: FullUserInfoDto,
}) })
getMe(@RequestUser() user: User): UserInfoDto { getMe(@RequestUser() user: User): FullUserInfoDto {
return this.usersService.toUserDto(user); return this.usersService.toFullUserDto(user);
} }
@Get('history') @Get('history')

View file

@ -34,7 +34,13 @@ export class UserInfoDto extends BaseDto {
}) })
@IsString() @IsString()
photo: string; photo: 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 * Email address of the user
* @example "john.smith@example.com" * @example "john.smith@example.com"

View file

@ -148,6 +148,18 @@ describe('UsersService', () => {
expect(userDto.username).toEqual(username); expect(userDto.username).toEqual(username);
expect(userDto.displayName).toEqual(displayname); expect(userDto.displayName).toEqual(displayname);
expect(userDto.photo).toEqual(''); expect(userDto.photo).toEqual('');
});
});
describe('toFullUserDto', () => {
const username = 'hardcoded';
const displayname = 'Testy';
const user = User.create(username, displayname) as User;
it('works if a user is provided', () => {
const userDto = service.toFullUserDto(user);
expect(userDto.username).toEqual(username);
expect(userDto.displayName).toEqual(displayname);
expect(userDto.photo).toEqual('');
expect(userDto.email).toEqual(''); expect(userDto.email).toEqual('');
}); });
}); });

View file

@ -9,7 +9,7 @@ import { Repository } from 'typeorm';
import { AlreadyInDBError, NotInDBError } from '../errors/errors'; import { AlreadyInDBError, NotInDBError } from '../errors/errors';
import { ConsoleLoggerService } from '../logger/console-logger.service'; import { ConsoleLoggerService } from '../logger/console-logger.service';
import { UserInfoDto } from './user-info.dto'; import { FullUserInfoDto, UserInfoDto } from './user-info.dto';
import { UserRelationEnum } from './user-relation.enum'; import { UserRelationEnum } from './user-relation.enum';
import { User } from './user.entity'; import { User } from './user.entity';
@ -111,6 +111,19 @@ export class UsersService {
* @return {(UserInfoDto)} the built UserInfoDto * @return {(UserInfoDto)} the built UserInfoDto
*/ */
toUserDto(user: User): UserInfoDto { toUserDto(user: User): UserInfoDto {
return {
username: user.username,
displayName: user.displayName,
photo: this.getPhotoUrl(user),
};
}
/**
* Build FullUserInfoDto from a user.
* @param {User=} user - the user to use
* @return {(UserInfoDto)} the built FullUserInfoDto
*/
toFullUserDto(user: User): FullUserInfoDto {
return { return {
username: user.username, username: user.username,
displayName: user.displayName, displayName: user.displayName,

View file

@ -9,7 +9,7 @@ import request from 'supertest';
import { AuthConfig } from '../../src/config/auth.config'; import { AuthConfig } from '../../src/config/auth.config';
import { NotInDBError } from '../../src/errors/errors'; import { NotInDBError } from '../../src/errors/errors';
import { Note } from '../../src/notes/note.entity'; import { Note } from '../../src/notes/note.entity';
import { UserInfoDto } from '../../src/users/user-info.dto'; import { FullUserInfoDto } from '../../src/users/user-info.dto';
import { User } from '../../src/users/user.entity'; import { User } from '../../src/users/user.entity';
import { setupSessionMiddleware } from '../../src/utils/session'; import { setupSessionMiddleware } from '../../src/utils/session';
import { TestSetup, TestSetupBuilder } from '../test-setup'; import { TestSetup, TestSetupBuilder } from '../test-setup';
@ -50,12 +50,12 @@ describe('Me', () => {
}); });
it('GET /me', async () => { it('GET /me', async () => {
const userInfo = testSetup.userService.toUserDto(user); const userInfo = testSetup.userService.toFullUserDto(user);
const response = await agent const response = await agent
.get('/api/private/me') .get('/api/private/me')
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
.expect(200); .expect(200);
const gotUser = response.body as UserInfoDto; const gotUser = response.body as FullUserInfoDto;
expect(gotUser).toEqual(userInfo); expect(gotUser).toEqual(userInfo);
}); });

View file

@ -32,7 +32,7 @@ describe('Me', () => {
}); });
it(`GET /me`, async () => { it(`GET /me`, async () => {
const userInfo = testSetup.userService.toUserDto(user); const userInfo = testSetup.userService.toFullUserDto(user);
const response = await request(testSetup.app.getHttpServer()) const response = await request(testSetup.app.getHttpServer())
.get('/api/v2/me') .get('/api/v2/me')
.expect('Content-Type', /json/) .expect('Content-Type', /json/)