From f2afaedf90a2166bcc0be3bd1c5828697bd6e693 Mon Sep 17 00:00:00 2001 From: Nikolai Ovtsinnikov Date: Thu, 26 Sep 2024 14:46:36 +0300 Subject: [PATCH 1/4] rebase --- lib/api/submit.js | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/lib/api/submit.js b/lib/api/submit.js index 8e35dd98..47af61c9 100644 --- a/lib/api/submit.js +++ b/lib/api/submit.js @@ -15,7 +15,7 @@ const Transform = require('stream').Transform; const { sessSchema, sessIPSchema, booleanSchema, metaDataSchema } = require('../schemas'); const { preprocessAttachments } = require('../data-url'); const { userId, mailboxId } = require('../schemas/request/general-schemas'); -const { AddressOptionalName, AddressOptionalNameArray, Header, ReferenceWithoutAttachments } = require('../schemas/request/messages-schemas'); +const { AddressOptionalName, AddressOptionalNameArray, Header, Attachment, ReferenceWithAttachments } = require('../schemas/request/messages-schemas'); const { successRes } = require('../schemas/response/general-schemas'); class StreamCollect extends Transform { @@ -631,7 +631,7 @@ module.exports = (db, server, messageHandler, userHandler, settingsHandler) => { description: 'Use this method to send emails from a user account', validationObjs: { requestBody: { - mailbox: Joi.string().hex().lowercase().length(24).description('ID of the Mailbox'), + mailbox: mailboxId, from: AddressOptionalName.description('Addres for the From: header'), replyTo: AddressOptionalName.description('Address for the Reply-To: header'), to: Joi.array() @@ -664,27 +664,12 @@ module.exports = (db, server, messageHandler, userHandler, settingsHandler) => { .empty('') .max(1024 * 1024) .description('HTML formatted message'), - attachments: Joi.array() - .items( - Joi.object({ - filename: Joi.string().empty('').max(255).description('Attachment filename'), - contentType: Joi.string().empty('').max(255).description('MIME type for the attachment file'), - encoding: Joi.string().empty('').default('base64').description('Encoding to use to store the attachments'), - contentTransferEncoding: Joi.string().empty('').description('Transfer encoding'), - contentDisposition: Joi.string().empty('').trim().lowercase().valid('inline', 'attachment').description('Content Disposition'), - content: Joi.string().required().description('Base64 encoded attachment content'), - cid: Joi.string() - .empty('') - .max(255) - .description('Content-ID value if you want to reference to this attachment from HTML formatted message') - }) - ) - .description('Attachments for the message'), + attachments: Joi.array().items(Attachment).description('Attachments for the message'), meta: metaDataSchema.label('metaData').description('Optional metadata, must be an object or JSON formatted string'), sess: sessSchema, ip: sessIPSchema, - reference: ReferenceWithoutAttachments.description( + reference: ReferenceWithAttachments.description( 'Optional referenced email. If uploaded message is a reply draft and relevant fields are not provided then these are resolved from the message to be replied to' ), // if true then treat this message as a draft From de9659a5c5f7ee6e807f33a88f329e5a195b9532 Mon Sep 17 00:00:00 2001 From: Nikolai Ovtsinnikov Date: Thu, 26 Sep 2024 14:42:58 +0300 Subject: [PATCH 2/4] preauth and authenticate now also return the email address of the user --- lib/api/auth.js | 4 ++++ lib/user-handler.js | 2 ++ 2 files changed, 6 insertions(+) diff --git a/lib/api/auth.js b/lib/api/auth.js index 08571960..5677eaf6 100644 --- a/lib/api/auth.js +++ b/lib/api/auth.js @@ -37,6 +37,7 @@ module.exports = (db, server, userHandler) => { success: successRes, id: userId, username: Joi.string().required().description('Username of authenticated User'), + address: Joi.string().required().description('Default email address of authenticated User'), scope: Joi.string().required().description('The scope this authentication is valid for'), require2fa: Joi.array().items(Joi.string()).required().description('List of enabled 2FA mechanisms') }) @@ -109,6 +110,7 @@ module.exports = (db, server, userHandler) => { success: true, id: authData.user.toString(), username: authData.username, + address: authData.address, scope: authData.scope, require2fa: authData.require2fa }; @@ -158,6 +160,7 @@ module.exports = (db, server, userHandler) => { success: successRes, id: userId, username: Joi.string().required().description('Username of authenticated User'), + address: Joi.string().required().description('Default email address of authenticated User'), scope: Joi.string().required().description('The scope this authentication is valid for'), require2fa: Joi.array().items(Joi.string()).required().description('List of enabled 2FA mechanisms'), requirePasswordChange: booleanSchema.required().description('Indicates if account hassword has been reset and should be replaced'), @@ -246,6 +249,7 @@ module.exports = (db, server, userHandler) => { success: true, id: authData.user.toString(), username: authData.username, + address: authData.address, scope: authData.scope, require2fa: authData.require2fa, requirePasswordChange: authData.requirePasswordChange diff --git a/lib/user-handler.js b/lib/user-handler.js index e1df616f..7db82ae5 100644 --- a/lib/user-handler.js +++ b/lib/user-handler.js @@ -853,6 +853,7 @@ class UserHandler { user: userData._id, username: userData.username, scope: meta.requiredScope, + address: userData.address, // if 2FA is enabled then require token validation require2fa: enabled2fa.length && !usingTemporaryPassword ? enabled2fa : false, requirePasswordChange // true, if password was reset and using temporary password @@ -1105,6 +1106,7 @@ class UserHandler { let authResponse = { user: userData._id, username: userData.username, + address: userData.address, scope: requiredScope, // if 2FA is enabled then require token validation require2fa: requiredScope === 'master' && enabled2fa.length ? enabled2fa : false From dd605773a705997a116cf4501930c3dfa6df1ed9 Mon Sep 17 00:00:00 2001 From: Nikolai Ovtsinnikov Date: Thu, 26 Sep 2024 15:08:32 +0300 Subject: [PATCH 3/4] fix user tests --- test/api/users-test.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/api/users-test.js b/test/api/users-test.js index 8c8b8021..942f4f3b 100644 --- a/test/api/users-test.js +++ b/test/api/users-test.js @@ -11,6 +11,8 @@ const config = require('wild-config'); const server = supertest.agent(`http://127.0.0.1:${config.api.port}`); +const os = require('os'); + describe('API Users', function () { this.timeout(10000); // eslint-disable-line no-invalid-this @@ -81,6 +83,7 @@ describe('API Users', function () { expect(authResponse.body.success).to.be.true; expect(authResponse.body).to.deep.equal({ success: true, + address: 'john@example.com', id: user, username: 'myuser2', scope: 'master', @@ -155,6 +158,7 @@ describe('API Users', function () { expect(authResponse.body.success).to.be.true; expect(authResponse.body).to.deep.equal({ success: true, + address: `myuser2hash@${os.hostname().toLowerCase()}`, id: user2, username: 'myuser2hash', scope: 'master', @@ -332,6 +336,7 @@ describe('API Users', function () { expect(authResponse.body.success).to.be.true; expect(authResponse.body).to.deep.equal({ success: true, + address: 'john@example.com', id: user, username: 'myuser2', scope: 'master', From 04a1b59daccde9af100f32bbb7b585b7eb566623 Mon Sep 17 00:00:00 2001 From: Nikolai Ovtsinnikov Date: Thu, 26 Sep 2024 15:12:41 +0300 Subject: [PATCH 4/4] fix git divergence issues: submit.js --- lib/api/submit.js | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/lib/api/submit.js b/lib/api/submit.js index 47af61c9..8e35dd98 100644 --- a/lib/api/submit.js +++ b/lib/api/submit.js @@ -15,7 +15,7 @@ const Transform = require('stream').Transform; const { sessSchema, sessIPSchema, booleanSchema, metaDataSchema } = require('../schemas'); const { preprocessAttachments } = require('../data-url'); const { userId, mailboxId } = require('../schemas/request/general-schemas'); -const { AddressOptionalName, AddressOptionalNameArray, Header, Attachment, ReferenceWithAttachments } = require('../schemas/request/messages-schemas'); +const { AddressOptionalName, AddressOptionalNameArray, Header, ReferenceWithoutAttachments } = require('../schemas/request/messages-schemas'); const { successRes } = require('../schemas/response/general-schemas'); class StreamCollect extends Transform { @@ -631,7 +631,7 @@ module.exports = (db, server, messageHandler, userHandler, settingsHandler) => { description: 'Use this method to send emails from a user account', validationObjs: { requestBody: { - mailbox: mailboxId, + mailbox: Joi.string().hex().lowercase().length(24).description('ID of the Mailbox'), from: AddressOptionalName.description('Addres for the From: header'), replyTo: AddressOptionalName.description('Address for the Reply-To: header'), to: Joi.array() @@ -664,12 +664,27 @@ module.exports = (db, server, messageHandler, userHandler, settingsHandler) => { .empty('') .max(1024 * 1024) .description('HTML formatted message'), - attachments: Joi.array().items(Attachment).description('Attachments for the message'), + attachments: Joi.array() + .items( + Joi.object({ + filename: Joi.string().empty('').max(255).description('Attachment filename'), + contentType: Joi.string().empty('').max(255).description('MIME type for the attachment file'), + encoding: Joi.string().empty('').default('base64').description('Encoding to use to store the attachments'), + contentTransferEncoding: Joi.string().empty('').description('Transfer encoding'), + contentDisposition: Joi.string().empty('').trim().lowercase().valid('inline', 'attachment').description('Content Disposition'), + content: Joi.string().required().description('Base64 encoded attachment content'), + cid: Joi.string() + .empty('') + .max(255) + .description('Content-ID value if you want to reference to this attachment from HTML formatted message') + }) + ) + .description('Attachments for the message'), meta: metaDataSchema.label('metaData').description('Optional metadata, must be an object or JSON formatted string'), sess: sessSchema, ip: sessIPSchema, - reference: ReferenceWithAttachments.description( + reference: ReferenceWithoutAttachments.description( 'Optional referenced email. If uploaded message is a reply draft and relevant fields are not provided then these are resolved from the message to be replied to' ), // if true then treat this message as a draft