mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-25 03:06:31 -05:00
feat(api/private/me): include authProvider in UserInfo
This information is supposed to be used by the frontend to identify the login method that was used. The used login method is saved as a string into the session data and extracted via a new SessionAuthProvider decorator. Signed-off-by: David Mehren <git@herrmehren.de>
This commit is contained in:
parent
3f8e3b0589
commit
d6ea4d29fe
7 changed files with 71 additions and 8 deletions
|
@ -75,11 +75,18 @@ export class AuthController {
|
|||
@Post('local/login')
|
||||
@OpenApi(201, 400, 401)
|
||||
login(
|
||||
@Req() request: Request & { session: { user: string } },
|
||||
@Req()
|
||||
request: Request & {
|
||||
session: {
|
||||
authProvider: string;
|
||||
user: string;
|
||||
};
|
||||
},
|
||||
@Body() loginDto: LoginDto,
|
||||
): void {
|
||||
// There is no further testing needed as we only get to this point if LocalAuthGuard was successful
|
||||
request.session.user = loginDto.username;
|
||||
request.session.authProvider = 'local';
|
||||
}
|
||||
|
||||
@UseGuards(SessionGuard)
|
||||
|
|
|
@ -10,11 +10,12 @@ import { SessionGuard } from '../../../identity/session.guard';
|
|||
import { ConsoleLoggerService } from '../../../logger/console-logger.service';
|
||||
import { MediaUploadDto } from '../../../media/media-upload.dto';
|
||||
import { MediaService } from '../../../media/media.service';
|
||||
import { FullUserInfoDto } from '../../../users/user-info.dto';
|
||||
import { UserLoginInfoDto } from '../../../users/user-info.dto';
|
||||
import { User } from '../../../users/user.entity';
|
||||
import { UsersService } from '../../../users/users.service';
|
||||
import { OpenApi } from '../../utils/openapi.decorator';
|
||||
import { RequestUser } from '../../utils/request-user.decorator';
|
||||
import { SessionAuthProvider } from '../../utils/session-authprovider.decorator';
|
||||
|
||||
@UseGuards(SessionGuard)
|
||||
@OpenApi(401)
|
||||
|
@ -31,8 +32,11 @@ export class MeController {
|
|||
|
||||
@Get()
|
||||
@OpenApi(200)
|
||||
getMe(@RequestUser() user: User): FullUserInfoDto {
|
||||
return this.userService.toFullUserDto(user);
|
||||
getMe(
|
||||
@RequestUser() user: User,
|
||||
@SessionAuthProvider() authProvider: string,
|
||||
): UserInfoDto {
|
||||
return this.userService.toUserLoginInfoDto(user, authProvider);
|
||||
}
|
||||
|
||||
@Get('media')
|
||||
|
|
34
src/api/utils/session-authprovider.decorator.ts
Normal file
34
src/api/utils/session-authprovider.decorator.ts
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import {
|
||||
createParamDecorator,
|
||||
ExecutionContext,
|
||||
InternalServerErrorException,
|
||||
} from '@nestjs/common';
|
||||
import { Request } from 'express';
|
||||
|
||||
/**
|
||||
* Extracts the auth provider identifier from a session inside a request
|
||||
*
|
||||
* Will throw an {@link InternalServerErrorException} if no identifier is present
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
export const SessionAuthProvider = createParamDecorator(
|
||||
(data: unknown, ctx: ExecutionContext) => {
|
||||
const request: Request & {
|
||||
session: {
|
||||
authProvider: string;
|
||||
};
|
||||
} = ctx.switchToHttp().getRequest();
|
||||
if (!request.session?.authProvider) {
|
||||
// We should have an auth provider here, otherwise something is wrong
|
||||
throw new InternalServerErrorException(
|
||||
'Session is missing an auth provider identifier',
|
||||
);
|
||||
}
|
||||
return request.session.authProvider;
|
||||
},
|
||||
);
|
|
@ -51,3 +51,12 @@ export class FullUserInfoDto extends UserInfoDto {
|
|||
@IsString()
|
||||
email: string;
|
||||
}
|
||||
|
||||
export class UserLoginInfoDto extends UserInfoDto {
|
||||
/**
|
||||
* Identifier of the auth provider that was used to log in
|
||||
*/
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
authProvider: string;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,11 @@ import { Repository } from 'typeorm';
|
|||
|
||||
import { AlreadyInDBError, NotInDBError } from '../errors/errors';
|
||||
import { ConsoleLoggerService } from '../logger/console-logger.service';
|
||||
import { FullUserInfoDto, UserInfoDto } from './user-info.dto';
|
||||
import {
|
||||
FullUserInfoDto,
|
||||
UserInfoDto,
|
||||
UserLoginInfoDto,
|
||||
} from './user-info.dto';
|
||||
import { UserRelationEnum } from './user-relation.enum';
|
||||
import { User } from './user.entity';
|
||||
|
||||
|
@ -131,4 +135,8 @@ export class UsersService {
|
|||
email: user.email ?? '',
|
||||
};
|
||||
}
|
||||
|
||||
toUserLoginInfoDto(user: User, authProvider: string): UserLoginInfoDto {
|
||||
return { ...this.toUserDto(user), authProvider };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import request from 'supertest';
|
|||
|
||||
import { NotInDBError } from '../../src/errors/errors';
|
||||
import { Note } from '../../src/notes/note.entity';
|
||||
import { FullUserInfoDto } from '../../src/users/user-info.dto';
|
||||
import { UserLoginInfoDto } from '../../src/users/user-info.dto';
|
||||
import { User } from '../../src/users/user.entity';
|
||||
import { TestSetup, TestSetupBuilder } from '../test-setup';
|
||||
|
||||
|
@ -50,12 +50,12 @@ describe('Me', () => {
|
|||
});
|
||||
|
||||
it('GET /me', async () => {
|
||||
const userInfo = testSetup.userService.toFullUserDto(user);
|
||||
const userInfo = testSetup.userService.toUserLoginInfoDto(user, 'local');
|
||||
const response = await agent
|
||||
.get('/api/private/me')
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200);
|
||||
const gotUser = response.body as FullUserInfoDto;
|
||||
const gotUser = response.body as UserLoginInfoDto;
|
||||
expect(gotUser).toEqual(userInfo);
|
||||
});
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ describe('Register and Login', () => {
|
|||
const profile = await session.get('/api/private/me').expect(200);
|
||||
expect(profile.body.username).toEqual(USERNAME);
|
||||
expect(profile.body.displayName).toEqual(DISPLAYNAME);
|
||||
expect(profile.body.authProvider).toEqual('local');
|
||||
|
||||
// logout again
|
||||
await session.delete('/api/private/auth/logout').expect(204);
|
||||
|
|
Loading…
Reference in a new issue