rainbox.email/src/controllers/MailboxBackendController.ts
2020-07-27 16:02:09 +02:00

176 lines
7.2 KiB
TypeScript

import Controller from "wms-core/Controller";
import {REQUIRE_ADMIN_MIDDLEWARE, REQUIRE_AUTH_MIDDLEWARE} from "wms-core/auth/AuthComponent";
import {Request, Response} from "express";
import User from "wms-core/auth/models/User";
import {WhereTest} from "wms-core/db/ModelQuery";
import UserNameComponent from "../models/UserNameComponent";
import UserMailIdentityComponent from "../models/UserMailIdentityComponent";
import {NotFoundHttpError} from "wms-core/HttpError";
import MailDomain from "../models/MailDomain";
import BackendController from "wms-core/helpers/BackendController";
import MailIdentity from "../models/MailIdentity";
export default class MailboxBackendController extends Controller {
public constructor() {
super();
BackendController.registerMenuElement({
getLink: async () => Controller.route('backend-mailboxes'),
getDisplayString: async () => 'Mailboxes',
getDisplayIcon: async () => 'mail',
});
}
public getRoutesPrefix(): string {
return '/backend/mailboxes';
}
public routes(): void {
this.get('/', this.getMailboxesBackend, 'backend-mailboxes', REQUIRE_AUTH_MIDDLEWARE, REQUIRE_ADMIN_MIDDLEWARE);
this.get('/:id', this.getMailboxBackend, 'backend-mailbox', REQUIRE_AUTH_MIDDLEWARE, REQUIRE_ADMIN_MIDDLEWARE);
this.post('/add-domain', this.postAddDomain, 'backend-add-domain', REQUIRE_AUTH_MIDDLEWARE, REQUIRE_ADMIN_MIDDLEWARE)
this.post('/remove-domain', this.postRemoveDomain, 'backend-remove-domain', REQUIRE_AUTH_MIDDLEWARE, REQUIRE_ADMIN_MIDDLEWARE)
this.post('/:id/create-mail-identity', this.postCreateMailIdentity, 'backend-create-mail-identity', REQUIRE_AUTH_MIDDLEWARE, REQUIRE_ADMIN_MIDDLEWARE);
this.post('/delete-mail-identity', this.postDeleteMailIdentity, 'backend-delete-mail-identity', REQUIRE_AUTH_MIDDLEWARE, REQUIRE_ADMIN_MIDDLEWARE);
}
protected async getMailboxesBackend(req: Request, res: Response): Promise<void> {
const mailDomains = await MailDomain.select()
.with('owner')
.with('identities')
.get();
const users = await User.select()
.where('main_mail_identity_id', null, WhereTest.NE)
.with('mainMailIdentity')
.with('mailIdentities')
.get();
res.render('backend/mailboxes', {
domains: await Promise.all(mailDomains.map(async domain => ({
id: domain.id,
name: domain.name,
owner_name: (await domain.owner.get())?.as(UserNameComponent).name,
identity_count: (await domain.identities.get()).length,
}))),
users: [{
value: 0,
display: 'Public',
}, ...(await User.select().get()).map(u => ({
value: u.id,
display: u.name,
}))],
mailboxes: await Promise.all(users.map(async user => ({
id: user.id,
username: user.as(UserNameComponent).name,
name: await (await user.as(UserMailIdentityComponent).mainMailIdentity.get())?.toEmail(),
identity_count: (await user.as(UserMailIdentityComponent).mailIdentities.get()).length,
domain_count: (await user.as(UserMailIdentityComponent).mailDomains.get()).length,
}))),
});
}
protected async getMailboxBackend(req: Request, res: Response): Promise<void> {
const user = await User.select()
.where('id', req.params.id)
.with('mailIdentities')
.first();
if (!user) throw new NotFoundHttpError('User', req.url);
res.render('backend/mailbox', {
mailbox: {
id: user.id,
name: await (await user.as(UserMailIdentityComponent).mainMailIdentity.get())?.toEmail() || 'Not created.',
},
domains: (await MailDomain.select().get()).map(d => ({
display: d.name,
value: d.id,
})),
identities: await Promise.all((await user.as(UserMailIdentityComponent).mailIdentities.get()).map(async i => ({
id: i.id,
email: await i.toEmail(),
}))),
});
}
protected async postAddDomain(req: Request, res: Response): Promise<void> {
const domain = MailDomain.create({
name: req.body.name,
user_id: req.body.user_id,
});
await domain.save();
req.flash('success', `Domain ${domain.name} successfully added with owner ${(await domain.owner.get())?.name}`);
res.redirectBack();
}
protected async postRemoveDomain(req: Request, res: Response): Promise<void> {
const domain = await MailDomain.select()
.where('id', req.body.id)
.with('identities')
.first();
if (!domain) throw new NotFoundHttpError('Domain', req.url);
// Don't delete that domain if it still has identities
if ((await domain.identities.get()).length > 0) {
req.flash('error', `This domain still has identities. Please remove all of these first (don't forget to rename mailboxes).`);
res.redirectBack();
return;
}
await domain.delete();
req.flash('success', `Domain ${domain.name} successfully deleted.`);
res.redirectBack();
}
protected async postCreateMailIdentity(req: Request, res: Response): Promise<void> {
const user = await User.select()
.where('id', req.params.id)
.first();
if (!user) throw new NotFoundHttpError('User', req.url);
const domain = await MailDomain.getById(req.body.mail_domain_id);
if (!domain) throw new NotFoundHttpError('domain', req.url);
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,
});
// 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', 'Mailbox created.');
}
req.flash('success', 'Mail identity ' + (await identity.toEmail()) + ' successfully created.')
res.redirectBack();
}
protected async postDeleteMailIdentity(req: Request, res: Response): Promise<void> {
const identity = await MailIdentity.select()
.where('id', req.body.id)
.with('user')
.first();
if (!identity) throw new NotFoundHttpError('Mail identity', req.url);
const user = await identity.user.get();
if (user?.as(UserMailIdentityComponent).main_mail_identity_id === identity.id) {
req.flash('error', `Cannot delete this user's mailbox identity.`);
res.redirectBack();
return;
}
await identity.delete();
req.flash('success', 'Identity ' + (await identity.toEmail()) + ' successfully deleted.');
res.redirectBack();
}
}