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 { 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 { 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 { 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 { 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 { 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 { 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(); } }