enable switch to pw totp in account settings
This commit is contained in:
parent
be22c78372
commit
ddb460f8d0
6 changed files with 165 additions and 4 deletions
|
@ -1,3 +1,5 @@
|
|||
import { LoginRoutineEnum } from "../../../enums/loginRoutineEnum";
|
||||
|
||||
export interface CreateUserCommand {
|
||||
mail: string;
|
||||
username: string;
|
||||
|
@ -18,6 +20,7 @@ export interface UpdateUserCommand {
|
|||
export interface UpdateUserSecretCommand {
|
||||
id: string;
|
||||
secret: string;
|
||||
routine: LoginRoutineEnum;
|
||||
}
|
||||
|
||||
export interface TransferUserOwnerCommand {
|
||||
|
|
|
@ -75,6 +75,7 @@ export default abstract class UserCommandHandler {
|
|||
.update(user)
|
||||
.set({
|
||||
secret: updateUser.secret,
|
||||
routine: updateUser.routine,
|
||||
})
|
||||
.where("id = :id", { id: updateUser.id })
|
||||
.execute()
|
||||
|
|
|
@ -50,6 +50,7 @@ export async function login(req: Request, res: Response): Promise<any> {
|
|||
window: 2,
|
||||
});
|
||||
} else {
|
||||
console.log(passedSecret, secret, passedSecret == secret);
|
||||
valid = passedSecret == secret;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import UserService from "../service/management/userService";
|
|||
import { UpdateUserSecretCommand } from "../command/management/user/userCommand";
|
||||
import UserCommandHandler from "../command/management/user/userCommandHandler";
|
||||
import SettingHelper from "../helpers/settingsHelper";
|
||||
import { LoginRoutineEnum } from "../enums/loginRoutineEnum";
|
||||
|
||||
/**
|
||||
* @description request totp reset
|
||||
|
@ -101,6 +102,7 @@ export async function finishReset(req: Request, res: Response): Promise<any> {
|
|||
let updateUserSecret: UpdateUserSecretCommand = {
|
||||
id,
|
||||
secret,
|
||||
routine: LoginRoutineEnum.totp,
|
||||
};
|
||||
await UserCommandHandler.updateSecret(updateUserSecret);
|
||||
|
||||
|
|
|
@ -4,10 +4,15 @@ import QRCode from "qrcode";
|
|||
import InternalException from "../exceptions/internalException";
|
||||
import UserService from "../service/management/userService";
|
||||
import UserFactory from "../factory/admin/management/user";
|
||||
import { TransferUserOwnerCommand, UpdateUserCommand } from "../command/management/user/userCommand";
|
||||
import {
|
||||
TransferUserOwnerCommand,
|
||||
UpdateUserCommand,
|
||||
UpdateUserSecretCommand,
|
||||
} from "../command/management/user/userCommand";
|
||||
import UserCommandHandler from "../command/management/user/userCommandHandler";
|
||||
import ForbiddenRequestException from "../exceptions/forbiddenRequestException";
|
||||
import SettingHelper from "../helpers/settingsHelper";
|
||||
import { LoginRoutineEnum } from "../enums/loginRoutineEnum";
|
||||
|
||||
/**
|
||||
* @description get my by id
|
||||
|
@ -22,6 +27,21 @@ export async function getMeById(req: Request, res: Response): Promise<any> {
|
|||
res.json(UserFactory.mapToSingle(user));
|
||||
}
|
||||
|
||||
/**
|
||||
* @description get my routine by id
|
||||
* @param req {Request} Express req object
|
||||
* @param res {Response} Express res object
|
||||
* @returns {Promise<*>}
|
||||
*/
|
||||
export async function getMyRoutine(req: Request, res: Response): Promise<any> {
|
||||
const id = req.userId;
|
||||
let user = await UserService.getById(id);
|
||||
|
||||
res.json({
|
||||
routine: user.routine,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description get my totp
|
||||
* @param req {Request} Express req object
|
||||
|
@ -33,8 +53,6 @@ export async function getMyTotp(req: Request, res: Response): Promise<any> {
|
|||
|
||||
let { secret, routine } = await UserService.getUserSecretAndRoutine(userId);
|
||||
|
||||
console.log(secret);
|
||||
|
||||
const url = `otpauth://totp/FF Admin ${SettingHelper.getSetting("club.name")}?secret=${secret}`;
|
||||
|
||||
QRCode.toDataURL(url)
|
||||
|
@ -60,6 +78,11 @@ export async function verifyMyTotp(req: Request, res: Response): Promise<any> {
|
|||
let totp = req.body.totp;
|
||||
|
||||
let { secret, routine } = await UserService.getUserSecretAndRoutine(userId);
|
||||
|
||||
if (routine != LoginRoutineEnum.totp) {
|
||||
throw new ForbiddenRequestException("only allowed for totp login");
|
||||
}
|
||||
|
||||
let valid = speakeasy.totp.verify({
|
||||
secret: secret,
|
||||
encoding: "base32",
|
||||
|
@ -73,6 +96,106 @@ export async function verifyMyTotp(req: Request, res: Response): Promise<any> {
|
|||
res.sendStatus(204);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description change my password
|
||||
* @param req {Request} Express req object
|
||||
* @param res {Response} Express res object
|
||||
* @returns {Promise<*>}
|
||||
*/
|
||||
export async function changeMyPassword(req: Request, res: Response): Promise<any> {
|
||||
const userId = req.userId;
|
||||
let current = req.body.current;
|
||||
let newpassword = req.body.newpassword;
|
||||
|
||||
let { secret, routine } = await UserService.getUserSecretAndRoutine(userId);
|
||||
|
||||
if (routine == LoginRoutineEnum.password && current != secret) {
|
||||
throw new ForbiddenRequestException("passwords do not match");
|
||||
}
|
||||
|
||||
let updateUser: UpdateUserSecretCommand = {
|
||||
id: userId,
|
||||
secret: newpassword,
|
||||
routine: LoginRoutineEnum.password,
|
||||
};
|
||||
await UserCommandHandler.updateSecret(updateUser);
|
||||
|
||||
res.sendStatus(204);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description get change to totp
|
||||
* @param req {Request} Express req object
|
||||
* @param res {Response} Express res object
|
||||
* @returns {Promise<*>}
|
||||
*/
|
||||
export async function getChangeToTOTP(req: Request, res: Response): Promise<any> {
|
||||
var secret = speakeasy.generateSecret({ length: 20, name: `FF Admin ${SettingHelper.getSetting("club.name")}` });
|
||||
|
||||
QRCode.toDataURL(secret.otpauth_url)
|
||||
.then((result) => {
|
||||
res.json({
|
||||
dataUrl: result,
|
||||
otp: secret.base32,
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
throw new InternalException("QRCode not created", err);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description change to totp
|
||||
* @param req {Request} Express req object
|
||||
* @param res {Response} Express res object
|
||||
* @returns {Promise<*>}
|
||||
*/
|
||||
export async function changeToTOTP(req: Request, res: Response): Promise<any> {
|
||||
const userId = req.userId;
|
||||
let otp = req.body.otp;
|
||||
let totp = req.body.totp;
|
||||
|
||||
let valid = speakeasy.totp.verify({
|
||||
secret: otp,
|
||||
encoding: "base32",
|
||||
token: totp,
|
||||
window: 2,
|
||||
});
|
||||
|
||||
if (!valid) {
|
||||
throw new InternalException("Token not valid or expired");
|
||||
}
|
||||
|
||||
let updateUser: UpdateUserSecretCommand = {
|
||||
id: userId,
|
||||
secret: otp,
|
||||
routine: LoginRoutineEnum.totp,
|
||||
};
|
||||
await UserCommandHandler.updateSecret(updateUser);
|
||||
|
||||
res.sendStatus(204);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description change to password
|
||||
* @param req {Request} Express req object
|
||||
* @param res {Response} Express res object
|
||||
* @returns {Promise<*>}
|
||||
*/
|
||||
export async function changeToPW(req: Request, res: Response): Promise<any> {
|
||||
const userId = req.userId;
|
||||
let newpassword = req.body.newpassword;
|
||||
|
||||
let updateUser: UpdateUserSecretCommand = {
|
||||
id: userId,
|
||||
secret: newpassword,
|
||||
routine: LoginRoutineEnum.password,
|
||||
};
|
||||
await UserCommandHandler.updateSecret(updateUser);
|
||||
|
||||
res.sendStatus(204);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description transferOwnership
|
||||
* @param req {Request} Express req object
|
||||
|
|
|
@ -1,5 +1,16 @@
|
|||
import express from "express";
|
||||
import { getMeById, getMyTotp, transferOwnership, updateMe, verifyMyTotp } from "../controller/userController";
|
||||
import {
|
||||
changeMyPassword,
|
||||
changeToPW,
|
||||
changeToTOTP,
|
||||
getChangeToTOTP,
|
||||
getMeById,
|
||||
getMyRoutine,
|
||||
getMyTotp,
|
||||
transferOwnership,
|
||||
updateMe,
|
||||
verifyMyTotp,
|
||||
} from "../controller/userController";
|
||||
|
||||
var router = express.Router({ mergeParams: true });
|
||||
|
||||
|
@ -7,14 +18,34 @@ router.get("/me", async (req, res) => {
|
|||
await getMeById(req, res);
|
||||
});
|
||||
|
||||
router.get("/routine", async (req, res) => {
|
||||
await getMyRoutine(req, res);
|
||||
});
|
||||
|
||||
router.get("/totp", async (req, res) => {
|
||||
await getMyTotp(req, res);
|
||||
});
|
||||
|
||||
router.get("/changeToTOTP", async (req, res) => {
|
||||
await getChangeToTOTP(req, res);
|
||||
});
|
||||
|
||||
router.post("/verify", async (req, res) => {
|
||||
await verifyMyTotp(req, res);
|
||||
});
|
||||
|
||||
router.post("/changepw", async (req, res) => {
|
||||
await changeMyPassword(req, res);
|
||||
});
|
||||
|
||||
router.post("/changeToTOTP", async (req, res) => {
|
||||
await changeToTOTP(req, res);
|
||||
});
|
||||
|
||||
router.post("/changeToPW", async (req, res) => {
|
||||
await changeToPW(req, res);
|
||||
});
|
||||
|
||||
router.put("/transferOwner", async (req, res) => {
|
||||
await transferOwnership(req, res);
|
||||
});
|
||||
|
|
Loading…
Add table
Reference in a new issue