mirror of
https://github.com/Unleash/unleash.git
synced 2024-12-22 19:07:54 +01:00
feat: Add change-password endpoint to user-controller (#800)
fixes: #801 Co-authored-by: Fredrik Oseberg <fredrik.no@gmail.com>
This commit is contained in:
parent
185091174f
commit
18f66ef732
@ -4,7 +4,7 @@
|
||||
},
|
||||
"extends": [
|
||||
"airbnb-typescript/base",
|
||||
"prettier",
|
||||
"prettier"
|
||||
],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
|
@ -17,6 +17,8 @@ const currentUser = new User({ email: 'test@mail.com' });
|
||||
function getSetup() {
|
||||
const base = `/random${Math.round(Math.random() * 1000)}`;
|
||||
const stores = store.createStores();
|
||||
stores.userStore.insert(currentUser);
|
||||
|
||||
const config = createTestConfig({
|
||||
preHook: a => {
|
||||
a.use((req, res, next) => {
|
||||
@ -30,12 +32,12 @@ function getSetup() {
|
||||
const app = getApp(config, stores, services, eventBus);
|
||||
return {
|
||||
base,
|
||||
strategyStore: stores.strategyStore,
|
||||
userStore: stores.userStore,
|
||||
request: supertest(app),
|
||||
};
|
||||
}
|
||||
|
||||
test.only('should return current user', t => {
|
||||
test('should return current user', t => {
|
||||
t.plan(1);
|
||||
const { request, base } = getSetup();
|
||||
|
||||
@ -47,13 +49,35 @@ test.only('should return current user', t => {
|
||||
t.is(res.body.user.email, currentUser.email);
|
||||
});
|
||||
});
|
||||
const owaspPassword = 't7GTx&$Y9pcsnxRv6';
|
||||
|
||||
test('should logout and redirect', t => {
|
||||
test('should allow user to change password', async t => {
|
||||
t.plan(2);
|
||||
const { request, base, userStore } = getSetup();
|
||||
const before = await userStore.get(currentUser);
|
||||
t.falsy(before.passwordHash);
|
||||
await request
|
||||
.post(`${base}/api/admin/user/change-password`)
|
||||
.send({ password: owaspPassword, confirmPassword: owaspPassword })
|
||||
.expect(200);
|
||||
const updated = await userStore.get(currentUser);
|
||||
t.truthy(updated.passwordHash);
|
||||
});
|
||||
|
||||
test('should deny if password and confirmPassword are not equal', async t => {
|
||||
t.plan(0);
|
||||
const { request, base } = getSetup();
|
||||
|
||||
return request
|
||||
.get(`${base}/api/admin/user/logout`)
|
||||
.expect(302)
|
||||
.expect('Location', `${base}/`);
|
||||
.post(`${base}/api/admin/user/change-password`)
|
||||
.send({ password: owaspPassword, confirmPassword: 'somethingelse' })
|
||||
.expect(400);
|
||||
});
|
||||
|
||||
test('should deny if password does not fulfill owasp criteria', async t => {
|
||||
t.plan(0);
|
||||
const { request, base } = getSetup();
|
||||
return request
|
||||
.post(`${base}/api/admin/user/change-password`)
|
||||
.send({ password: 'hunter123', confirmPassword: 'hunter123' })
|
||||
.expect(400);
|
||||
});
|
||||
|
@ -1,24 +1,47 @@
|
||||
'use strict';
|
||||
|
||||
import { Response } from 'express';
|
||||
import { Request, Response } from 'express';
|
||||
import { IAuthRequest } from '../unleash-types';
|
||||
import Controller from '../controller';
|
||||
import { AccessService } from '../../services/access-service';
|
||||
import { IUnleashConfig } from '../../types/option';
|
||||
import { IUnleashServices } from '../../types/services';
|
||||
import UserService from '../../services/user-service';
|
||||
import User from '../../user';
|
||||
import { Logger } from '../../logger';
|
||||
import { handleErrors } from './util';
|
||||
|
||||
interface IService {
|
||||
accessService: AccessService;
|
||||
interface IChangeUserRequest {
|
||||
password: string;
|
||||
confirmPassword: string;
|
||||
}
|
||||
|
||||
interface UserRequest<PARAM, QUERY, BODY, RESPONSE>
|
||||
extends Request<PARAM, QUERY, BODY, RESPONSE> {
|
||||
user: User;
|
||||
}
|
||||
|
||||
class UserController extends Controller {
|
||||
private accessService: AccessService;
|
||||
|
||||
constructor(config: IUnleashConfig, { accessService }: IService) {
|
||||
private userService: UserService;
|
||||
|
||||
private logger: Logger;
|
||||
|
||||
constructor(
|
||||
config: IUnleashConfig,
|
||||
{
|
||||
accessService,
|
||||
userService,
|
||||
}: Pick<IUnleashServices, 'accessService' | 'userService'>,
|
||||
) {
|
||||
super(config);
|
||||
this.accessService = accessService;
|
||||
this.userService = userService;
|
||||
this.logger = config.getLogger('lib/routes/admin-api/user.ts');
|
||||
|
||||
this.get('/', this.getUser);
|
||||
this.get('/logout', this.logout);
|
||||
this.post('/change-password', this.updateUserPass);
|
||||
}
|
||||
|
||||
async getUser(req: IAuthRequest, res: Response): Promise<void> {
|
||||
@ -36,15 +59,27 @@ class UserController extends Controller {
|
||||
return res.status(404).end();
|
||||
}
|
||||
|
||||
// Deprecated, use "/logout" instead. Will be removed in v4.
|
||||
logout(req: IAuthRequest, res: Response): void {
|
||||
if (req.session) {
|
||||
req.session = null;
|
||||
async updateUserPass(
|
||||
req: UserRequest<any, any, IChangeUserRequest, any>,
|
||||
res: Response,
|
||||
): Promise<void> {
|
||||
const { user } = req;
|
||||
if (user) {
|
||||
const { password, confirmPassword } = req.body;
|
||||
try {
|
||||
if (password === confirmPassword) {
|
||||
this.userService.validatePassword(password);
|
||||
await this.userService.changePassword(user.id, password);
|
||||
res.status(200).end();
|
||||
} else {
|
||||
res.status(400).end();
|
||||
}
|
||||
} catch (e) {
|
||||
handleErrors(res, this.logger, e);
|
||||
}
|
||||
} else {
|
||||
res.status(401).end();
|
||||
}
|
||||
if (req.logout) {
|
||||
req.logout();
|
||||
}
|
||||
res.redirect(`${this.config.server.baseUriPath}/`);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user