enable password on invite or reset
This commit is contained in:
parent
ddb460f8d0
commit
0ea12eaafc
8 changed files with 61 additions and 32 deletions
|
@ -7,6 +7,7 @@ export interface CreateUserCommand {
|
||||||
lastname: string;
|
lastname: string;
|
||||||
secret: string;
|
secret: string;
|
||||||
isOwner: boolean;
|
isOwner: boolean;
|
||||||
|
routine: LoginRoutineEnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UpdateUserCommand {
|
export interface UpdateUserCommand {
|
||||||
|
|
|
@ -31,6 +31,7 @@ export default abstract class UserCommandHandler {
|
||||||
lastname: createUser.lastname,
|
lastname: createUser.lastname,
|
||||||
secret: createUser.secret,
|
secret: createUser.secret,
|
||||||
isOwner: createUser.isOwner,
|
isOwner: createUser.isOwner,
|
||||||
|
routine: createUser.routine,
|
||||||
})
|
})
|
||||||
.execute()
|
.execute()
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
|
|
|
@ -41,6 +41,8 @@ export async function login(req: Request, res: Response): Promise<any> {
|
||||||
let { id } = await UserService.getByUsername(username);
|
let { id } = await UserService.getByUsername(username);
|
||||||
let { secret, routine } = await UserService.getUserSecretAndRoutine(id);
|
let { secret, routine } = await UserService.getUserSecretAndRoutine(id);
|
||||||
|
|
||||||
|
console.log(secret, passedSecret);
|
||||||
|
|
||||||
let valid = false;
|
let valid = false;
|
||||||
if (routine == LoginRoutineEnum.totp) {
|
if (routine == LoginRoutineEnum.totp) {
|
||||||
valid = speakeasy.totp.verify({
|
valid = speakeasy.totp.verify({
|
||||||
|
@ -50,7 +52,6 @@ export async function login(req: Request, res: Response): Promise<any> {
|
||||||
window: 2,
|
window: 2,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.log(passedSecret, secret, passedSecret == secret);
|
|
||||||
valid = passedSecret == secret;
|
valid = passedSecret == secret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ import UserService from "../service/management/userService";
|
||||||
import CustomRequestException from "../exceptions/customRequestException";
|
import CustomRequestException from "../exceptions/customRequestException";
|
||||||
import InviteFactory from "../factory/admin/management/invite";
|
import InviteFactory from "../factory/admin/management/invite";
|
||||||
import SettingHelper from "../helpers/settingsHelper";
|
import SettingHelper from "../helpers/settingsHelper";
|
||||||
|
import { LoginRoutineEnum } from "../enums/loginRoutineEnum";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description get all invites
|
* @description get all invites
|
||||||
|
@ -112,20 +113,26 @@ export async function verifyInvite(req: Request, res: Response): Promise<any> {
|
||||||
*/
|
*/
|
||||||
export async function finishInvite(req: Request, res: Response, grantAdmin: boolean = false): Promise<any> {
|
export async function finishInvite(req: Request, res: Response, grantAdmin: boolean = false): Promise<any> {
|
||||||
let mail = req.body.mail;
|
let mail = req.body.mail;
|
||||||
|
let routine = req.body.routine;
|
||||||
let token = req.body.token;
|
let token = req.body.token;
|
||||||
let totp = req.body.totp;
|
let passedSecret = req.body.secret;
|
||||||
|
|
||||||
let { secret, username, firstname, lastname } = await InviteService.getByMailAndToken(mail, token);
|
let { secret, username, firstname, lastname } = await InviteService.getByMailAndToken(mail, token);
|
||||||
|
|
||||||
let valid = speakeasy.totp.verify({
|
let valid = false;
|
||||||
|
if (routine == LoginRoutineEnum.totp) {
|
||||||
|
valid = speakeasy.totp.verify({
|
||||||
secret: secret,
|
secret: secret,
|
||||||
encoding: "base32",
|
encoding: "base32",
|
||||||
token: totp,
|
token: passedSecret,
|
||||||
window: 2,
|
window: 2,
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
valid = passedSecret != "";
|
||||||
|
}
|
||||||
|
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
throw new UnauthorizedRequestException("Token not valid or expired");
|
throw new UnauthorizedRequestException("Credentials not valid or expired");
|
||||||
}
|
}
|
||||||
|
|
||||||
let createUser: CreateUserCommand = {
|
let createUser: CreateUserCommand = {
|
||||||
|
@ -133,8 +140,9 @@ export async function finishInvite(req: Request, res: Response, grantAdmin: bool
|
||||||
firstname: firstname,
|
firstname: firstname,
|
||||||
lastname: lastname,
|
lastname: lastname,
|
||||||
mail: mail,
|
mail: mail,
|
||||||
secret: secret,
|
secret: routine == LoginRoutineEnum.totp ? secret : passedSecret,
|
||||||
isOwner: grantAdmin,
|
isOwner: grantAdmin,
|
||||||
|
routine,
|
||||||
};
|
};
|
||||||
let id = await UserCommandHandler.create(createUser);
|
let id = await UserCommandHandler.create(createUser);
|
||||||
|
|
||||||
|
|
|
@ -81,28 +81,34 @@ export async function verifyReset(req: Request, res: Response): Promise<any> {
|
||||||
*/
|
*/
|
||||||
export async function finishReset(req: Request, res: Response): Promise<any> {
|
export async function finishReset(req: Request, res: Response): Promise<any> {
|
||||||
let mail = req.body.mail;
|
let mail = req.body.mail;
|
||||||
|
let routine = req.body.routine;
|
||||||
let token = req.body.token;
|
let token = req.body.token;
|
||||||
let totp = req.body.totp;
|
let passedSecret = req.body.secret;
|
||||||
|
|
||||||
let { secret, username } = await ResetService.getByMailAndToken(mail, token);
|
let { secret, username } = await ResetService.getByMailAndToken(mail, token);
|
||||||
|
|
||||||
let valid = speakeasy.totp.verify({
|
let valid = false;
|
||||||
|
if (routine == LoginRoutineEnum.totp) {
|
||||||
|
valid = speakeasy.totp.verify({
|
||||||
secret: secret,
|
secret: secret,
|
||||||
encoding: "base32",
|
encoding: "base32",
|
||||||
token: totp,
|
token: passedSecret,
|
||||||
window: 2,
|
window: 2,
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
valid = passedSecret != "";
|
||||||
|
}
|
||||||
|
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
throw new UnauthorizedRequestException("Token not valid or expired");
|
throw new UnauthorizedRequestException("Credentials not valid or expired");
|
||||||
}
|
}
|
||||||
|
|
||||||
let { id } = await UserService.getByUsername(username);
|
let { id } = await UserService.getByUsername(username);
|
||||||
|
|
||||||
let updateUserSecret: UpdateUserSecretCommand = {
|
let updateUserSecret: UpdateUserSecretCommand = {
|
||||||
id,
|
id,
|
||||||
secret,
|
secret: routine == LoginRoutineEnum.totp ? secret : passedSecret,
|
||||||
routine: LoginRoutineEnum.totp,
|
routine,
|
||||||
};
|
};
|
||||||
await UserCommandHandler.updateSecret(updateUserSecret);
|
await UserCommandHandler.updateSecret(updateUserSecret);
|
||||||
|
|
||||||
|
|
|
@ -56,12 +56,17 @@ export default abstract class SettingHelper {
|
||||||
return rawValue as unknown as SettingValueMapping[K];
|
return rawValue as unknown as SettingValueMapping[K];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let processedValue = rawValue;
|
||||||
|
if (typeof settingType.type === "string" && settingType.type.includes("/crypt")) {
|
||||||
|
processedValue = CodingHelper.decrypt(APPLICATION_SECRET, processedValue);
|
||||||
|
}
|
||||||
|
|
||||||
const baseType =
|
const baseType =
|
||||||
typeof settingType.type === "string"
|
typeof settingType.type === "string"
|
||||||
? (settingType.type.split("/")[0] as SettingTypeAtom)
|
? (settingType.type.split("/")[0] as SettingTypeAtom)
|
||||||
: (settingType.type as SettingTypeAtom);
|
: (settingType.type as SettingTypeAtom);
|
||||||
|
|
||||||
return this.converters[baseType].fromString(rawValue) as unknown as SettingValueMapping[K];
|
return this.converters[baseType].fromString(processedValue) as unknown as SettingValueMapping[K];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -81,11 +86,11 @@ export default abstract class SettingHelper {
|
||||||
const settingType = settingsType[key];
|
const settingType = settingsType[key];
|
||||||
this.validateSetting(key, stringValue);
|
this.validateSetting(key, stringValue);
|
||||||
|
|
||||||
const oldValue = this.getSetting(key);
|
const oldValue = cloneDeep(this.settings[key]);
|
||||||
let finalValue = stringValue;
|
let newValue = stringValue;
|
||||||
|
|
||||||
if (typeof settingType.type === "string" && settingType.type.includes("/crypt")) {
|
if (typeof settingType.type === "string" && settingType.type.includes("/crypt")) {
|
||||||
finalValue = CodingHelper.encrypt(APPLICATION_SECRET, stringValue);
|
newValue = CodingHelper.encrypt(APPLICATION_SECRET, stringValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.settings[key] = stringValue;
|
this.settings[key] = stringValue;
|
||||||
|
@ -94,10 +99,9 @@ export default abstract class SettingHelper {
|
||||||
await SettingCommandHandler.create({
|
await SettingCommandHandler.create({
|
||||||
topic,
|
topic,
|
||||||
key: settingKey,
|
key: settingKey,
|
||||||
value: finalValue,
|
value: newValue,
|
||||||
});
|
});
|
||||||
|
|
||||||
const newValue = this.getSetting(key);
|
|
||||||
this.notifyListeners(key, newValue, oldValue);
|
this.notifyListeners(key, newValue, oldValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,12 @@ router.post("/verify", ParamaterPassCheckHelper.requiredIncludedMiddleware(["mai
|
||||||
await verifyInvite(req, res);
|
await verifyInvite(req, res);
|
||||||
});
|
});
|
||||||
|
|
||||||
router.put("/", ParamaterPassCheckHelper.requiredIncludedMiddleware(["mail", "token", "totp"]), async (req, res) => {
|
router.put(
|
||||||
|
"/",
|
||||||
|
ParamaterPassCheckHelper.requiredIncludedMiddleware(["mail", "token", "secret", "routine "]),
|
||||||
|
async (req, res) => {
|
||||||
await finishInvite(req, res);
|
await finishInvite(req, res);
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|
|
@ -12,8 +12,12 @@ router.post("/", ParamaterPassCheckHelper.requiredIncludedMiddleware(["username"
|
||||||
await startReset(req, res);
|
await startReset(req, res);
|
||||||
});
|
});
|
||||||
|
|
||||||
router.put("/", ParamaterPassCheckHelper.requiredIncludedMiddleware(["mail", "token", "totp"]), async (req, res) => {
|
router.put(
|
||||||
|
"/",
|
||||||
|
ParamaterPassCheckHelper.requiredIncludedMiddleware(["mail", "token", "secret", "routine"]),
|
||||||
|
async (req, res) => {
|
||||||
await finishReset(req, res);
|
await finishReset(req, res);
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|
Loading…
Add table
Reference in a new issue