rainbox.email/src/controllers/AccountMailboxController.ts

107 lines
4.7 KiB
TypeScript

import Controller from "swaf/Controller";
import {RequireAuthMiddleware} from "swaf/auth/AuthComponent";
import {Request, Response} from "express";
import Validator from "swaf/db/Validator";
import {ForbiddenHttpError, NotFoundHttpError} from "swaf/HttpError";
import MailDomain from "../models/MailDomain";
import UserMailIdentityComponent from "../models/UserMailIdentityComponent";
import MailIdentity from "../models/MailIdentity";
import {WhereOperator, WhereTest} from "swaf/db/ModelQuery";
import UserNameComponent from "swaf/auth/models/UserNameComponent";
export default class AccountMailboxController extends Controller {
public getRoutesPrefix(): string {
return '/account/mailbox';
}
public routes(): void {
this.get('/', this.getAccountMailbox, 'account-mailbox', RequireAuthMiddleware);
this.post('/create-mail-identity', this.postCreateMailIdentity, 'create-mail-identity', RequireAuthMiddleware);
this.post('/delete-mail-identity', this.postDeleteMailIdentity, 'delete-mail-identity', RequireAuthMiddleware);
}
protected async getAccountMailbox(req: Request, res: Response): Promise<void> {
const user = req.as(RequireAuthMiddleware).getUser();
const userMailIdentity = user.as(UserMailIdentityComponent);
res.render('account-mailbox', {
mailboxIdentity: await (await userMailIdentity.mainMailIdentity.get())?.toEmail(),
identities: await Promise.all((await userMailIdentity.mailIdentities.get()).map(async identity => ({
id: identity.id,
email: await identity.toEmail(),
}))),
domains: (await MailDomain.select()
.where('user_id', user.id)
.where('user_id', null, WhereTest.EQ, WhereOperator.OR)
.sortBy('user_id', 'DESC')
.get())
.map(d => ({
value: d.id,
display: d.name,
})),
});
}
protected async postCreateMailIdentity(req: Request, res: Response): Promise<void> {
const domain = await MailDomain.getById(req.body.mail_domain_id);
if (!domain) throw new NotFoundHttpError('domain', req.url);
const user = req.as(RequireAuthMiddleware).getUser();
const mailIdentityComponent = user.as(UserMailIdentityComponent);
const identity = MailIdentity.create({
user_id: user.id,
name: req.body.name,
mail_domain_id: req.body.mail_domain_id,
});
// Check whether this identity can be created by this user
if (!domain.canCreateAddresses(user)) {
throw new ForbiddenHttpError('domain', req.url);
}
if (domain.isPublic()) {
await Validator.validate({
name: new Validator<string>().defined().equals(user.as(UserNameComponent).getName()),
}, req.body);
const actualPublicAddressesCount = await mailIdentityComponent.getPublicAddressesCount();
const maxPublicAddressesCount = mailIdentityComponent.getMaxPublicAddressesCount();
if (maxPublicAddressesCount >= 0 && actualPublicAddressesCount >= maxPublicAddressesCount) {
req.flash('error', 'You have reached maximum public email addresses.');
res.redirect(Controller.route('account-mailbox'));
return;
}
}
// Save identity
await identity.save();
// Set main mail identity if not already set
if (!mailIdentityComponent.main_mail_identity_id) {
mailIdentityComponent.main_mail_identity_id = identity.id;
await user.save();
req.flash('info', 'Congratulations! You just created your mailbox.');
}
req.flash('success', 'Mail identity ' + await identity.toEmail() + ' successfully created.');
res.redirect(Controller.route('account-mailbox'));
}
protected async postDeleteMailIdentity(req: Request, res: Response): Promise<void> {
const user = req.as(RequireAuthMiddleware).getUser();
const identity = await MailIdentity.getById(req.body.id);
if (!identity) throw new NotFoundHttpError('Mail identity', req.url);
if (identity.user_id !== user.id) throw new ForbiddenHttpError('mail identity', req.url);
if (user.as(UserMailIdentityComponent).main_mail_identity_id === identity.id) {
req.flash('error', 'Cannot delete your mailbox identity.');
res.redirect(Controller.route('account-mailbox'));
return;
}
await identity.delete();
req.flash('success', 'Identity ' + await identity.toEmail() + ' successfully deleted.');
res.redirect(Controller.route('account-mailbox'));
}
}