From 7ae401740ced43761e325c004e998bd85dd332d1 Mon Sep 17 00:00:00 2001 From: Andris Reinman Date: Fri, 21 Jul 2017 16:29:57 +0300 Subject: [PATCH] Added message DELETE Api call --- api.js | 123 ++++++++++++++++++++++++++++++++++++++++- lib/message-handler.js | 73 +++++++++++++++++++++--- 2 files changed, 187 insertions(+), 9 deletions(-) diff --git a/api.js b/api.js index 1943870..0f3f383 100644 --- a/api.js +++ b/api.js @@ -10,6 +10,7 @@ const tools = require('./lib/tools'); const consts = require('./lib/consts'); const UserHandler = require('./lib/user-handler'); const MailboxHandler = require('./lib/mailbox-handler'); +const MessageHandler = require('./lib/message-handler'); const ImapNotifier = require('./lib/imap-notifier'); const db = require('./lib/db'); const MongoPaging = require('mongo-cursor-pagination'); @@ -44,6 +45,7 @@ const server = restify.createServer(serverOptions); let userHandler; let mailboxHandler; +let messageHandler; let notifier; // disable compression for EventSource response @@ -1894,14 +1896,14 @@ server.get('/users/:user/mailboxes/:mailbox/messages/:message', (req, res, next) if (parsedHeader['list-id'] || parsedHeader['list-unsubscribe']) { let listId = parsedHeader['list-id']; if (listId) { - listId = addressparser(listId); + listId = addressparser(listId.toString()); decodeAddresses(listId); listId = listId.shift(); } let listUnsubscribe = parsedHeader['list-unsubscribe']; if (listUnsubscribe) { - listUnsubscribe = addressparser(listUnsubscribe); + listUnsubscribe = addressparser(listUnsubscribe.toString()); decodeAddresses(listUnsubscribe); } @@ -1959,6 +1961,7 @@ server.put('/users/:user/mailboxes/:mailbox/messages/:message', (req, res, next) const schema = Joi.object().keys({ user: Joi.string().hex().lowercase().length(24).required(), mailbox: Joi.string().hex().lowercase().length(24).required(), + newMailbox: Joi.string().hex().lowercase().length(24), message: Joi.string().regex(/^[0-9a-f]{24}:\d{1,10}/).lowercase().required(), seen: Joi.boolean().truthy(['Y', 'true', 'yes', 1]), deleted: Joi.boolean().truthy(['Y', 'true', 'yes', 1]), @@ -1982,9 +1985,45 @@ server.put('/users/:user/mailboxes/:mailbox/messages/:message', (req, res, next) let messageparts = result.value.message.split(':'); let user = new ObjectID(result.value.user); let mailbox = new ObjectID(result.value.mailbox); + let newMailbox = result.value.newMailbox ? new ObjectID(result.value.newMailbox) : false; let message = new ObjectID(messageparts[0]); let uid = Number(messageparts[1]); + if (newMailbox) { + return messageHandler.move( + { + user, + source: { user, mailbox }, + destination: { user, mailbox: newMailbox }, + updates: result.value, + returnIds: true, + messages: [uid] + }, + (err, result, info) => { + if (err) { + res.json({ + error: err.message + }); + return next(); + } + + if (!info || !info.destinationUid || !info.destinationUid.length) { + res.json({ + error: 'Could not move message, check if message exists' + }); + return next(); + } + + res.json({ + success: true, + mailbox: newMailbox, + id: info && info.destinationUid && info.destinationUid[0] + }); + return next(); + } + ); + } + let updates = { $set: {} }; let update = false; let addFlags = []; @@ -2149,6 +2188,85 @@ server.put('/users/:user/mailboxes/:mailbox/messages/:message', (req, res, next) }); }); +server.del('/users/:user/mailboxes/:mailbox/messages/:message', (req, res, next) => { + res.charSet('utf-8'); + + const schema = Joi.object().keys({ + user: Joi.string().hex().lowercase().length(24).required(), + mailbox: Joi.string().hex().lowercase().length(24).required(), + message: Joi.string().regex(/^[0-9a-f]{24}:\d{1,10}/).lowercase().required() + }); + + const result = Joi.validate(req.params, schema, { + abortEarly: false, + convert: true + }); + + if (result.error) { + res.json({ + error: result.error.message + }); + return next(); + } + + let messageparts = result.value.message.split(':'); + let user = new ObjectID(result.value.user); + let mailbox = new ObjectID(result.value.mailbox); + let message = new ObjectID(messageparts[0]); + let uid = Number(messageparts[1]); + + db.database.collection('messages').findOne({ + _id: message, + mailbox, + uid + }, { + fields: { + _id: true, + mailbox: true, + uid: true, + size: true, + map: true, + magic: true, + unseen: true + } + }, (err, messageData) => { + if (err) { + res.json({ + error: err.message + }); + return next(); + } + + if (!messageData) { + res.json({ + error: 'Message was not found' + }); + return next(); + } + + return messageHandler.del( + { + user, + mailbox: { user, mailbox }, + message: messageData + }, + (err, result, info) => { + if (err) { + res.json({ + error: err.message + }); + return next(); + } + + res.json({ + success: true + }); + return next(); + } + ); + }); +}); + server.get('/users/:user/updates', (req, res, next) => { res.charSet('utf-8'); @@ -2477,6 +2595,7 @@ module.exports = done => { }); userHandler = new UserHandler({ database: db.database, users: db.users, redis: db.redis }); mailboxHandler = new MailboxHandler({ database: db.database, users: db.users, redis: db.redis, notifier }); + messageHandler = new MessageHandler({ database: db.database, gridfs: db.gridfs, redis: db.redis }); server.on('error', err => { if (!started) { diff --git a/lib/message-handler.js b/lib/message-handler.js index c98f0a3..047327c 100644 --- a/lib/message-handler.js +++ b/lib/message-handler.js @@ -38,6 +38,9 @@ class MessageHandler { return setImmediate(() => callback(null, options.mailbox)); } query._id = options.mailbox; + if (options.user) { + query.user = options.user; + } } else { query.user = options.user; if (options.specialUse) { @@ -463,8 +466,8 @@ class MessageHandler { del(options, callback) { let message = options.message; this.getMailbox( - { - mailbox: options.mailbox || message.mailbox + options.mailbox || { + mailbox: message.mailbox }, (err, mailbox) => { if (err) { @@ -621,7 +624,12 @@ class MessageHandler { let messageId = message._id; let messageUid = message.uid; - sourceUid.unshift(messageUid); + if (options.returnIds) { + sourceUid.unshift(message._id); + } else { + sourceUid.unshift(messageUid); + } + this.database.collection('mailboxes').findOneAndUpdate({ _id: target._id }, { @@ -639,12 +647,16 @@ class MessageHandler { return cursor.close(() => done(new Error('Mailbox disappeared'))); } - let uidNext = item.value.uidNext; - destinationUid.unshift(uidNext); - - // set new id message._id = new ObjectID(); + let uidNext = item.value.uidNext; + + if (options.returnIds) { + destinationUid.unshift(message._id); + } else { + destinationUid.unshift(uidNext); + } + // set new mailbox message.mailbox = target._id; @@ -675,6 +687,53 @@ class MessageHandler { junk = -1; } + Object.keys(options.updates || []).forEach(key => { + switch (key) { + case 'seen': + case 'deleted': + { + let fname = '\\' + key.charAt(0).toUpperCase() + key.substr(1); + if (!options.updates[key] && !message.flags.includes(fname)) { + // add missing flag + message.flags.push(fname); + } else if (options.updates[key] && message.flags.includes(fname)) { + // remove non-needed flag + let flags = new Set(message.flags); + flags.delete(fname); + message.flags = Array.from(flags); + } + message['un' + key] = options.updates[key]; + } + break; + case 'flagged': + case 'draft': + { + let fname = '\\' + key.charAt(0).toUpperCase() + key.substr(1); + if (options.updates[key] && !message.flags.includes(fname)) { + // add missing flag + message.flags.push(fname); + } else if (!options.updates[key] && message.flags.includes(fname)) { + // remove non-needed flag + let flags = new Set(message.flags); + flags.delete(fname); + message.flags = Array.from(flags); + } + message[key] = options.updates[key]; + } + break; + case 'expires': + { + if (options.updates.expires) { + message.exp = true; + message.rdate = options.updates.expires.getTime(); + } else { + message.exp = false; + } + } + break; + } + }); + if (options.markAsSeen) { message.unseen = false; if (!message.flags.includes('\\Seen')) {