Merge pull request #1787 from hedgedoc/enhancement/e2e_login_registration

This commit is contained in:
Yannick Bungers 2021-10-29 22:12:30 +02:00 committed by GitHub
commit cf991decc0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 165 additions and 6 deletions

View file

@ -6,6 +6,7 @@
import { import {
BadRequestException, BadRequestException,
Body, Body,
ConflictException,
Controller, Controller,
Delete, Delete,
NotFoundException, NotFoundException,
@ -56,7 +57,7 @@ export class AuthController {
return; return;
} catch (e) { } catch (e) {
if (e instanceof AlreadyInDBError) { if (e instanceof AlreadyInDBError) {
throw new BadRequestException(e.message); throw new ConflictException(e.message);
} }
throw e; throw e;
} }

View file

@ -75,7 +75,7 @@ describe('Auth', () => {
.post('/api/private/auth/local') .post('/api/private/auth/local')
.set('Content-Type', 'application/json') .set('Content-Type', 'application/json')
.send(JSON.stringify(registrationDto)) .send(JSON.stringify(registrationDto))
.expect(400); .expect(409);
}); });
it('when registration is disabled', async () => { it('when registration is disabled', async () => {
testSetup.configService.get('authConfig').local.enableRegister = false; testSetup.configService.get('authConfig').local.enableRegister = false;

View file

@ -0,0 +1,139 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import request from 'supertest';
import { LoginDto } from '../../src/identity/local/login.dto';
import { RegisterDto } from '../../src/identity/local/register.dto';
import { TestSetup } from '../test-setup';
describe('Register and Login', () => {
let testSetup: TestSetup;
const USERNAME = 'testuser';
const DISPLAYNAME = 'A Test User';
const PASSWORD = 'secure';
beforeEach(async () => {
testSetup = await TestSetup.create();
await testSetup.app.init();
});
afterEach(async () => {
await testSetup.app.close();
});
test('a user can successfully create a local account and log in', async () => {
// register a new user
const registrationDto: RegisterDto = {
displayname: DISPLAYNAME,
password: PASSWORD,
username: USERNAME,
};
await request(testSetup.app.getHttpServer())
.post('/api/private/auth/local')
.set('Content-Type', 'application/json')
.send(JSON.stringify(registrationDto))
.expect(201);
// log in with the new user and create a session
const loginDto: LoginDto = {
password: PASSWORD,
username: USERNAME,
};
const session = request.agent(testSetup.app.getHttpServer());
await session
.post('/api/private/auth/local/login')
.set('Content-Type', 'application/json')
.send(JSON.stringify(loginDto))
.expect(201);
// request user profile
const profile = await session.get('/api/private/me').expect(200);
expect(profile.body.username).toEqual(USERNAME);
expect(profile.body.displayName).toEqual(DISPLAYNAME);
// logout again
await session.delete('/api/private/auth/logout').expect(200);
// not allowed to request profile now
await session.get('/api/private/me').expect(401);
});
test('a username cannot be used twice', async () => {
// register a new user
const registrationDto: RegisterDto = {
displayname: DISPLAYNAME,
password: PASSWORD,
username: USERNAME,
};
await request(testSetup.app.getHttpServer())
.post('/api/private/auth/local')
.set('Content-Type', 'application/json')
.send(JSON.stringify(registrationDto))
.expect(201);
// try to use the same username again
await request(testSetup.app.getHttpServer())
.post('/api/private/auth/local')
.set('Content-Type', 'application/json')
.send(JSON.stringify(registrationDto))
.expect(409);
});
test('a user can create a local account and change the password', async () => {
// register a new user
const registrationDto: RegisterDto = {
displayname: DISPLAYNAME,
password: PASSWORD,
username: USERNAME,
};
await request(testSetup.app.getHttpServer())
.post('/api/private/auth/local')
.set('Content-Type', 'application/json')
.send(JSON.stringify(registrationDto))
.expect(201);
// log in with the new user and create a session
const loginDto: LoginDto = {
password: PASSWORD,
username: USERNAME,
};
let session = request.agent(testSetup.app.getHttpServer());
await session
.post('/api/private/auth/local/login')
.set('Content-Type', 'application/json')
.send(JSON.stringify(loginDto))
.expect(201);
// change the password
await session
.put('/api/private/auth/local')
.set('Content-Type', 'application/json')
.send(
JSON.stringify({
newPassword: 'newPassword',
}),
)
.expect(200);
// get new session
session = request.agent(testSetup.app.getHttpServer());
// not allowed to request profile now
await session.get('/api/private/me').expect(401);
// login with new password
loginDto.password = 'newPassword';
await session
.post('/api/private/auth/local/login')
.set('Content-Type', 'application/json')
.send(JSON.stringify(loginDto))
.expect(201);
// allowed to request profile now
await session.get('/api/private/me').expect(200);
});
});

View file

@ -14,24 +14,33 @@ import { PublicApiModule } from '../src/api/public/public-api.module';
import { AuthModule } from '../src/auth/auth.module'; import { AuthModule } from '../src/auth/auth.module';
import { MockAuthGuard } from '../src/auth/mock-auth.guard'; import { MockAuthGuard } from '../src/auth/mock-auth.guard';
import { TokenAuthGuard } from '../src/auth/token.strategy'; import { TokenAuthGuard } from '../src/auth/token.strategy';
import { AuthorsModule } from '../src/authors/authors.module';
import { AuthConfig } from '../src/config/auth.config';
import appConfigMock from '../src/config/mock/app.config.mock'; import appConfigMock from '../src/config/mock/app.config.mock';
import authConfigMock from '../src/config/mock/auth.config.mock'; import authConfigMock from '../src/config/mock/auth.config.mock';
import customizationConfigMock from '../src/config/mock/customization.config.mock'; import customizationConfigMock from '../src/config/mock/customization.config.mock';
import externalServicesConfigMock from '../src/config/mock/external-services.config.mock'; import externalServicesConfigMock from '../src/config/mock/external-services.config.mock';
import mediaConfigMock from '../src/config/mock/media.config.mock'; import mediaConfigMock from '../src/config/mock/media.config.mock';
import { FrontendConfigModule } from '../src/frontend-config/frontend-config.module';
import { GroupsModule } from '../src/groups/groups.module'; import { GroupsModule } from '../src/groups/groups.module';
import { HistoryModule } from '../src/history/history.module'; import { HistoryModule } from '../src/history/history.module';
import { HistoryService } from '../src/history/history.service'; import { HistoryService } from '../src/history/history.service';
import { IdentityModule } from '../src/identity/identity.module';
import { IdentityService } from '../src/identity/identity.service'; import { IdentityService } from '../src/identity/identity.service';
import { ConsoleLoggerService } from '../src/logger/console-logger.service';
import { LoggerModule } from '../src/logger/logger.module'; import { LoggerModule } from '../src/logger/logger.module';
import { MediaModule } from '../src/media/media.module'; import { MediaModule } from '../src/media/media.module';
import { MediaService } from '../src/media/media.service'; import { MediaService } from '../src/media/media.service';
import { MonitoringModule } from '../src/monitoring/monitoring.module';
import { AliasService } from '../src/notes/alias.service'; import { AliasService } from '../src/notes/alias.service';
import { NotesModule } from '../src/notes/notes.module'; import { NotesModule } from '../src/notes/notes.module';
import { NotesService } from '../src/notes/notes.service'; import { NotesService } from '../src/notes/notes.service';
import { PermissionsModule } from '../src/permissions/permissions.module'; import { PermissionsModule } from '../src/permissions/permissions.module';
import { RevisionsModule } from '../src/revisions/revisions.module';
import { UsersModule } from '../src/users/users.module'; import { UsersModule } from '../src/users/users.module';
import { UsersService } from '../src/users/users.service'; import { UsersService } from '../src/users/users.service';
import { setupSessionMiddleware } from '../src/utils/session';
import { setupValidationPipe } from '../src/utils/setup-pipes';
export class TestSetup { export class TestSetup {
moduleRef: TestingModule; moduleRef: TestingModule;
@ -78,16 +87,21 @@ export class TestSetup {
externalServicesConfigMock, externalServicesConfigMock,
], ],
}), }),
NotesModule,
UsersModule,
RevisionsModule,
AuthorsModule,
PublicApiModule, PublicApiModule,
PrivateApiModule, PrivateApiModule,
NotesModule, HistoryModule,
MonitoringModule,
PermissionsModule, PermissionsModule,
GroupsModule, GroupsModule,
LoggerModule, LoggerModule,
AuthModule,
UsersModule,
MediaModule, MediaModule,
HistoryModule, AuthModule,
FrontendConfigModule,
IdentityModule,
], ],
}) })
.overrideGuard(TokenAuthGuard) .overrideGuard(TokenAuthGuard)
@ -110,6 +124,11 @@ export class TestSetup {
testSetup.app = testSetup.moduleRef.createNestApplication(); testSetup.app = testSetup.moduleRef.createNestApplication();
setupSessionMiddleware(
testSetup.app,
testSetup.configService.get<AuthConfig>('authConfig'),
);
return testSetup; return testSetup;
} }
} }