diff --git a/CHANGES b/CHANGES index 74c2f21d3..30983810d 100644 --- a/CHANGES +++ b/CHANGES @@ -2432,4 +2432,5 @@ [7.1.2] * Fix crash in cloudron-firewall when ports are whitelisted * eventlog: add event for certificate cleanup +* eventlog: log event for mailbox alias update diff --git a/src/mail.js b/src/mail.js index a243d8ab6..b4aaa3569 100644 --- a/src/mail.js +++ b/src/mail.js @@ -1257,10 +1257,11 @@ async function getAliases(name, domain) { return await database.query('SELECT name, domain FROM mailboxes WHERE type = ? AND aliasName = ? AND aliasDomain = ? ORDER BY name', [ exports.TYPE_ALIAS, name, domain ]); } -async function setAliases(name, domain, aliases) { +async function setAliases(name, domain, aliases, auditSource) { assert.strictEqual(typeof name, 'string'); assert.strictEqual(typeof domain, 'string'); assert(Array.isArray(aliases)); + assert.strictEqual(typeof auditSource, 'object'); for (let i = 0; i < aliases.length; i++) { const name = aliases[i].name.toLowerCase(); @@ -1278,13 +1279,13 @@ async function setAliases(name, domain, aliases) { const results = await database.query('SELECT ' + MAILBOX_FIELDS + ' FROM mailboxes WHERE name = ? AND domain = ?', [ name, domain ]); if (results.length === 0) throw new BoxError(BoxError.NOT_FOUND, 'Mailbox not found'); - let queries = []; + const queries = []; // clear existing aliases queries.push({ query: 'DELETE FROM mailboxes WHERE aliasName = ? AND aliasDomain = ? AND type = ?', args: [ name, domain, exports.TYPE_ALIAS ] }); - aliases.forEach(function (alias) { + for (const alias of aliases) { queries.push({ query: 'INSERT INTO mailboxes (name, domain, type, aliasName, aliasDomain, ownerId, ownerType) VALUES (?, ?, ?, ?, ?, ?, ?)', args: [ alias.name, alias.domain, exports.TYPE_ALIAS, name, domain, results[0].ownerId, results[0].ownerType ] }); - }); + } const [error] = await safe(database.transaction(queries)); if (error && error.code === 'ER_DUP_ENTRY' && error.message.indexOf('mailboxes_name_domain_unique_index') !== -1) { @@ -1294,6 +1295,8 @@ async function setAliases(name, domain, aliases) { throw new BoxError(BoxError.ALREADY_EXISTS, `Mailbox, mailinglist or alias for ${aliasMatch[1]} already exists`); } if (error) throw error; + + await eventlog.add(eventlog.ACTION_MAIL_MAILBOX_UPDATE, auditSource, { name, domain, aliases }); } async function getLists(domain, search, page, perPage) { diff --git a/src/routes/mail.js b/src/routes/mail.js index ef626538d..8a7c3f7a7 100644 --- a/src/routes/mail.js +++ b/src/routes/mail.js @@ -233,7 +233,7 @@ async function setAliases(req, res, next) { if (typeof alias.domain !== 'string') return next(new HttpError(400, 'domain must be a string')); } - const [error] = await safe(mail.setAliases(req.params.name, req.params.domain, req.body.aliases)); + const [error] = await safe(mail.setAliases(req.params.name, req.params.domain, req.body.aliases, AuditSource.fromRequest(req))); if (error) return next(BoxError.toHttpError(error)); next(new HttpSuccess(202)); diff --git a/src/test/mail-test.js b/src/test/mail-test.js index 9aeb035ef..25a28b0bf 100644 --- a/src/test/mail-test.js +++ b/src/test/mail-test.js @@ -141,7 +141,7 @@ describe('Mail', function () { }); it('can set alias', async function () { - await mail.setAliases('support', domain.domain, [ { name: 'support2', domain: domain.domain }, { name: 'help', domain: domain.domain } ]); + await mail.setAliases('support', domain.domain, [ { name: 'support2', domain: domain.domain }, { name: 'help', domain: domain.domain } ], auditSource); }); it('can get aliases of name', async function () { @@ -154,7 +154,7 @@ describe('Mail', function () { }); it('unset aliases', async function () { - await mail.setAliases('support', domain.domain, []); + await mail.setAliases('support', domain.domain, [], auditSource); const results = await mail.getAliases('support', domain.domain); expect(results.length).to.be(0);