209 lines
8.7 KiB
TypeScript
209 lines
8.7 KiB
TypeScript
import Controller from "swaf/Controller";
|
|
import {Request, Response} from "express";
|
|
import User from "swaf/auth/models/User";
|
|
import {WhereTest} from "swaf/db/ModelQuery";
|
|
import UserMailIdentityComponent from "../../models/UserMailIdentityComponent";
|
|
import {NotFoundHttpError} from "swaf/HttpError";
|
|
import MailDomain from "../../models/MailDomain";
|
|
import BackendController from "swaf/helpers/BackendController";
|
|
import MailIdentity from "../../models/MailIdentity";
|
|
import {RequireAdminMiddleware, RequireAuthMiddleware} from "swaf/auth/AuthComponent";
|
|
import UserNameComponent from "swaf/auth/models/UserNameComponent";
|
|
|
|
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', RequireAuthMiddleware, RequireAdminMiddleware);
|
|
this.get('/:id', this.getMailboxBackend, 'backend-mailbox', RequireAuthMiddleware, RequireAdminMiddleware);
|
|
|
|
this.post('/add-domain', this.postAddDomain, 'backend-add-domain', RequireAuthMiddleware, RequireAdminMiddleware);
|
|
this.get('/edit-domain/:id', this.getEditDomain, 'backend-edit-domain', RequireAuthMiddleware, RequireAdminMiddleware);
|
|
this.post('/edit-domain/:id', this.postEditDomain, 'backend-edit-domain', RequireAuthMiddleware, RequireAdminMiddleware);
|
|
this.post('/remove-domain', this.postRemoveDomain, 'backend-remove-domain', RequireAuthMiddleware, RequireAdminMiddleware);
|
|
|
|
this.post('/:id/create-mail-identity', this.postCreateMailIdentity, 'backend-create-mail-identity', RequireAuthMiddleware, RequireAdminMiddleware);
|
|
this.post('/delete-mail-identity', this.postDeleteMailIdentity, 'backend-delete-mail-identity', RequireAuthMiddleware, RequireAdminMiddleware);
|
|
}
|
|
|
|
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);
|
|
|
|
const mainMailIdentity = await user.as(UserMailIdentityComponent).mainMailIdentity.get();
|
|
const mailDomains = await MailDomain.select().get();
|
|
const mailIdentities = await user.as(UserMailIdentityComponent).mailIdentities.get();
|
|
res.render('backend/mailbox', {
|
|
mailbox: {
|
|
id: user.id,
|
|
userName: user.as(UserNameComponent).name,
|
|
name: await mainMailIdentity?.toEmail() || 'Not created.',
|
|
},
|
|
domains: mailDomains.map(d => ({
|
|
display: d.name,
|
|
value: d.id,
|
|
})),
|
|
identities: await Promise.all(mailIdentities.map(async i => ({
|
|
id: i.id,
|
|
email: await i.toEmail(),
|
|
}))),
|
|
});
|
|
}
|
|
|
|
protected async postAddDomain(req: Request, res: Response): Promise<void> {
|
|
const domain = MailDomain.create(req.body);
|
|
await domain.save();
|
|
req.flash('success', `Domain ${domain.name} successfully added with owner ${(await domain.owner.get())?.name}`);
|
|
res.redirect(Controller.route('backend-mailboxes'));
|
|
}
|
|
|
|
protected async getEditDomain(req: Request, res: Response): Promise<void> {
|
|
const domain = await MailDomain.getById(req.params.id);
|
|
if (!domain) throw new NotFoundHttpError('Domain', req.url);
|
|
|
|
res.render('backend/mail_domain', {
|
|
domain: domain,
|
|
users: [{
|
|
value: 0,
|
|
display: 'Public',
|
|
}, ...(await User.select().get()).map(u => ({
|
|
value: u.id,
|
|
display: u.name,
|
|
}))],
|
|
});
|
|
}
|
|
|
|
protected async postEditDomain(req: Request, res: Response): Promise<void> {
|
|
const domain = await MailDomain.select()
|
|
.where('id', req.params.id)
|
|
.first();
|
|
if (!domain) throw new NotFoundHttpError('Domain', req.url);
|
|
|
|
domain.updateWithData(req.body);
|
|
await domain.save();
|
|
|
|
req.flash('success', `Domain ${domain.name} updated successfully.`);
|
|
res.redirect(Controller.route('backend-mailboxes'));
|
|
}
|
|
|
|
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.redirect(Controller.route('backend-mailboxes'));
|
|
return;
|
|
}
|
|
|
|
await domain.delete();
|
|
|
|
req.flash('success', `Domain ${domain.name} successfully deleted.`);
|
|
res.redirect(Controller.route('backend-mailboxes'));
|
|
}
|
|
|
|
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.redirect(Controller.route('backend-mailbox', req.params.id));
|
|
}
|
|
|
|
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.redirect(Controller.route('backend-mailbox', req.params.id));
|
|
return;
|
|
}
|
|
|
|
await identity.delete();
|
|
req.flash('success', 'Identity ' + await identity.toEmail() + ' successfully deleted.');
|
|
res.redirect(Controller.route('backend-mailbox', req.params.id));
|
|
}
|
|
}
|