101 lines
3.0 KiB
TypeScript
101 lines
3.0 KiB
TypeScript
import { Router } from "express";
|
|
import Stacker from "../../../middlewares/stacker";
|
|
import { GetUserMiddleware } from "../../../middlewares/user";
|
|
import TwoFactor, {
|
|
TFATypes as TwoFATypes,
|
|
IBackupCode,
|
|
} from "../../../../models/twofactor";
|
|
import RequestError, { HttpStatusCode } from "../../../../helper/request_error";
|
|
import moment = require("moment");
|
|
import { upgradeToken } from "../helper";
|
|
import * as crypto from "crypto";
|
|
import Logging from "@hibas123/nodelogging";
|
|
|
|
const BackupCodeRoute = Router();
|
|
|
|
// TODO: Further checks if this is good enough randomness
|
|
function generateCode(length: number) {
|
|
let bytes = crypto.randomBytes(length);
|
|
let nrs = "";
|
|
bytes.forEach((b, idx) => {
|
|
let nr = Math.floor((b / 255) * 9.9999);
|
|
if (nr > 9) nr = 9;
|
|
nrs += String(nr);
|
|
});
|
|
return nrs;
|
|
}
|
|
|
|
BackupCodeRoute.post(
|
|
"/",
|
|
Stacker(GetUserMiddleware(true, true), async (req, res) => {
|
|
//Generating new
|
|
let codes = Array(10).map(() => generateCode(8));
|
|
console.log(codes);
|
|
let twofactor = TwoFactor.new(<IBackupCode>{
|
|
user: req.user._id,
|
|
type: TwoFATypes.OTC,
|
|
valid: true,
|
|
data: codes,
|
|
name: "",
|
|
});
|
|
await TwoFactor.save(twofactor);
|
|
res.json({
|
|
codes,
|
|
id: twofactor._id,
|
|
});
|
|
})
|
|
);
|
|
|
|
BackupCodeRoute.put(
|
|
"/",
|
|
Stacker(
|
|
GetUserMiddleware(true, false, undefined, false),
|
|
async (req, res) => {
|
|
let { login, special } = req.token;
|
|
let { id, code }: { id: string; code: string } = req.body;
|
|
|
|
let twofactor: IBackupCode = await TwoFactor.findById(id);
|
|
|
|
if (
|
|
!twofactor ||
|
|
!twofactor.valid ||
|
|
!twofactor.user.equals(req.user._id) ||
|
|
twofactor.type !== TwoFATypes.OTC
|
|
) {
|
|
throw new RequestError(
|
|
"Invalid Method!",
|
|
HttpStatusCode.BAD_REQUEST
|
|
);
|
|
}
|
|
|
|
if (twofactor.expires && moment().isAfter(twofactor.expires)) {
|
|
twofactor.valid = false;
|
|
await TwoFactor.save(twofactor);
|
|
throw new RequestError(
|
|
"Invalid Method!",
|
|
HttpStatusCode.BAD_REQUEST
|
|
);
|
|
}
|
|
code = code.replace(/\s/g, "");
|
|
let valid = twofactor.data.find((c) => c === code);
|
|
|
|
if (valid) {
|
|
twofactor.data = twofactor.data.filter((c) => c !== code);
|
|
await TwoFactor.save(twofactor);
|
|
let [login_exp, special_exp] = await Promise.all([
|
|
upgradeToken(login),
|
|
upgradeToken(special),
|
|
]);
|
|
res.json({ success: true, login_exp, special_exp });
|
|
} else {
|
|
throw new RequestError(
|
|
"Invalid or already used code!",
|
|
HttpStatusCode.BAD_REQUEST
|
|
);
|
|
}
|
|
}
|
|
)
|
|
);
|
|
|
|
export default BackupCodeRoute;
|