rainbox.email/src/controllers/AuthController.ts

103 lines
4.5 KiB
TypeScript

import Controller from "wms-core/Controller";
import {REQUIRE_AUTH_MIDDLEWARE, REQUIRE_GUEST_MIDDLEWARE} from "wms-core/auth/AuthComponent";
import {Request, Response} from "express";
import Validator from "wms-core/db/Validator";
import {EMAIL_REGEX} from "wms-core/db/Model";
import {PasswordAuthProof} from "../models/UserPassword";
import UserEmail from "wms-core/auth/models/UserEmail";
import Username, {USERNAME_REGEXP} from "../models/Username";
export default class AuthController extends Controller {
routes(): void {
this.get('/login', this.getLogin, 'login', REQUIRE_GUEST_MIDDLEWARE);
this.post('/login', this.postLogin, 'login', REQUIRE_GUEST_MIDDLEWARE);
this.get('/register', this.getRegister, 'register', REQUIRE_GUEST_MIDDLEWARE);
this.post('/register', this.postRegister, 'register', REQUIRE_GUEST_MIDDLEWARE);
this.get('/logout', this.getLogout, 'logout', REQUIRE_AUTH_MIDDLEWARE);
}
private async getLogin(req: Request, res: Response): Promise<void> {
res.render('login');
}
private async postLogin(req: Request, res: Response): Promise<void> {
await this.validate({
email: new Validator().defined().regexp(EMAIL_REGEX),
password: new Validator().acceptUndefined(),
}, req.body);
const passwordAuthProof = new PasswordAuthProof(req.body.email);
const user = await passwordAuthProof.getUser();
if (!user) {
req.flash('error', 'Unknown email address');
res.redirect(Controller.route('login'));
return;
}
await passwordAuthProof.authorize(req.body.password, req.session);
await req.authGuard.authenticateOrRegister(req.session!, passwordAuthProof);
req.flash('success', `Welcome, ${user.name}.`);
res.redirect(Controller.route('home'));
}
private async getRegister(req: Request, res: Response): Promise<void> {
res.render('register');
}
private async postRegister(req: Request, res: Response): Promise<void> {
const validationMap: any = {
username: new Validator().defined().between(3, 64).regexp(USERNAME_REGEXP).unique(Username),
password: new Validator().defined().minLength(8),
password_confirmation: new Validator().defined().sameAs('password', req.body.password),
terms: new Validator().defined(),
};
let email: string;
if (req.body.create_email) {
validationMap['domain'] = new Validator().defined().regexp(/^(toot\.party)$/);
validationMap['recovery_email'] = new Validator().acceptUndefined(true).regexp(EMAIL_REGEX).unique(UserEmail, 'email');
email = req.body.email = req.body.username + '@' + req.body.domain;
validationMap['email'] = new Validator().defined().regexp(EMAIL_REGEX).unique(UserEmail, 'email');
} else {
validationMap['recovery_email'] = new Validator().defined().regexp(EMAIL_REGEX).unique(UserEmail, 'email');
email = req.body.recovery_email;
}
await this.validate(validationMap, req.body);
const passwordAuthProof = new PasswordAuthProof(email, false);
const userPassword = await passwordAuthProof.register(req.body.password);
await passwordAuthProof.authorize(req.body.password_confirmation, req.session);
await req.authGuard.authenticateOrRegister(req.session!, passwordAuthProof, async (connection, userID) => {
const callbacks: (() => Promise<void>)[] = [];
// Password
await userPassword.setUser(userID);
await userPassword.save(connection, c => callbacks.push(c));
// Username
await new Username({user_id: userID, username: req.body.username}).save(connection, c => callbacks.push(c));
// Email
if (req.body.create_email && req.body.recovery_email) {
await new UserEmail({
user_id: userID,
email: req.body.recovery_email,
main: false,
}).save(connection, c => callbacks.push(c));
}
return callbacks;
});
const user = (await passwordAuthProof.getUser())!;
req.flash('success', `Your account was successfully created! Welcome, ${user.name}.`);
res.redirect(Controller.route('home'));
}
private async getLogout(req: Request, res: Response): Promise<void> {
await req.authGuard.logout(req.session!);
res.redirect(Controller.route('home'));
}
}