From 9a4e20bb31b25e6169a04660572637081e5d9ca6 Mon Sep 17 00:00:00 2001 From: Bernat Exposito Domenech Date: Tue, 11 Aug 2020 11:03:43 +0200 Subject: [PATCH 01/11] new models and fixtures --- back/model-config.json | 9 +++++ back/models/mail.json | 36 +++++++++++++++++ back/models/worker-time-control-mail.json | 39 +++++++++++++++++++ back/models/worker-time-control-params.js | 3 ++ back/models/worker-time-control-params.json | 35 +++++++++++++++++ .../00-workerTimeControlParams.sql | 6 +++ db/dump/fixtures.sql | 4 +- 7 files changed, 130 insertions(+), 2 deletions(-) create mode 100644 back/models/mail.json create mode 100644 back/models/worker-time-control-mail.json create mode 100644 back/models/worker-time-control-params.js create mode 100644 back/models/worker-time-control-params.json create mode 100644 db/changes/12300-Summer/00-workerTimeControlParams.sql diff --git a/back/model-config.json b/back/model-config.json index 323e5f233..3d0085fc2 100644 --- a/back/model-config.json +++ b/back/model-config.json @@ -67,6 +67,15 @@ }, "UserLog": { "dataSource": "vn" + }, + "WorkerTimeControlParams": { + "dataSource": "vn" + }, + "WorkerTimeControlMail": { + "dataSource": "vn" + }, + "Mail": { + "dataSource": "vn" } } diff --git a/back/models/mail.json b/back/models/mail.json new file mode 100644 index 000000000..cf5c11993 --- /dev/null +++ b/back/models/mail.json @@ -0,0 +1,36 @@ +{ + "name": "Mail", + "base": "VnModel", + "options": { + "mysql": { + "table": "mail" + } + }, + "properties": { + "id": { + "id": true, + "type": "Number", + "required": true + }, + "sender": { + "type": "String" + }, + "replyTo": { + "type": "String" + }, + "subject": { + "type": "String" + }, + "body": { + "type": "String" + } + }, + "acls": [ + { + "accessType": "READ", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "ALLOW" + } + ] +} diff --git a/back/models/worker-time-control-mail.json b/back/models/worker-time-control-mail.json new file mode 100644 index 000000000..4a0fd31f1 --- /dev/null +++ b/back/models/worker-time-control-mail.json @@ -0,0 +1,39 @@ +{ + "name": "WorkerTimeControlMail", + "base": "VnModel", + "options": { + "mysql": { + "table": "workerTimeControlMail" + } + }, + "properties": { + "id": { + "id": true, + "type": "Number", + "required": true + }, + "workerFk": { + "type": "Number" + }, + "year": { + "type": "Number" + }, + "week": { + "type": "Number" + }, + "state": { + "type": "String" + }, + "updated": { + "type": "Date" + } + }, + "acls": [ + { + "accessType": "READ", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "ALLOW" + } + ] +} diff --git a/back/models/worker-time-control-params.js b/back/models/worker-time-control-params.js new file mode 100644 index 000000000..c71d4c237 --- /dev/null +++ b/back/models/worker-time-control-params.js @@ -0,0 +1,3 @@ +module.exports = Self => { + require('../methods/imap-time-control/checkInbox')(Self); +}; diff --git a/back/models/worker-time-control-params.json b/back/models/worker-time-control-params.json new file mode 100644 index 000000000..cc904cf40 --- /dev/null +++ b/back/models/worker-time-control-params.json @@ -0,0 +1,35 @@ +{ + "name": "WorkerTimeControlParams", + "description": "imap config", + "base": "VnModel", + "options": { + "mysql": { + "table": "workerTimeControlParams" + } + }, + "properties": { + "mailHost": { + "type": "String" + }, + "mailUser": { + "type": "String" + }, + "mailPass": { + "type": "String" + }, + "mailSuccessFolder": { + "type": "String" + }, + "mailErrorFolder": { + "type": "String" + } + }, + "acls": [ + { + "accessType": "READ", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "ALLOW" + } + ] +} diff --git a/db/changes/12300-Summer/00-workerTimeControlParams.sql b/db/changes/12300-Summer/00-workerTimeControlParams.sql new file mode 100644 index 000000000..47ef2e3ea --- /dev/null +++ b/db/changes/12300-Summer/00-workerTimeControlParams.sql @@ -0,0 +1,6 @@ +ALTER TABLE `vn`.`workerTimeControlParams` +ADD COLUMN `mailUser` VARCHAR(45) NOT NULL AFTER `askInOut`, +ADD COLUMN `mailPass` VARCHAR(45) NOT NULL AFTER `mailUser`, +ADD COLUMN `mailHost` VARCHAR(45) NOT NULL AFTER `mailPass`, +ADD COLUMN `mailSuccessFolder` VARCHAR(45) NOT NULL AFTER `mailHost`, +ADD COLUMN `mailErrorFolder` VARCHAR(45) NOT NULL AFTER `mailSuccessFolder`; diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index a1018ab5a..80f21297f 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2034,9 +2034,9 @@ INSERT INTO `vn`.`queuePriority`(`id`, `priority`) (2, 'Normal'), (3, 'Baja'); -INSERT INTO `vn`.`workerTimeControlParams` (`id`, `dayBreak`, `weekBreak`, `weekScope`, `dayWorkMax`, `dayStayMax`, `weekMaxBreak`, `weekMaxScope`, `askInOut`) +INSERT INTO `vn`.`workerTimeControlParams` (`id`, `dayBreak`, `weekBreak`, `weekScope`, `dayWorkMax`, `dayStayMax`, `weekMaxBreak`, `weekMaxScope`, `askInOut`, `mailSuccessFolder`, `mailErrorFolder`) VALUES - (1, 43200, 129600, 734400, 43200, 50400, 259200, 1296000, 36000); + (1, 43200, 129600, 734400, 43200, 50400, 259200, 1296000, 36000, 'Leidos.exito', 'Leidos.error'); INSERT IGNORE INTO `vn`.`greugeConfig` (`id`, `freightPickUpPrice`) VALUES ('1', '11'); From 860f9f4e874288ca05cf55668ff79b289a443136 Mon Sep 17 00:00:00 2001 From: Bernat Exposito Domenech Date: Tue, 11 Aug 2020 11:12:40 +0200 Subject: [PATCH 02/11] new method for imap --- back/methods/imap-time-control/checkInbox.js | 129 +++++++++++ package-lock.json | 215 +++++++++++++++++-- package.json | 2 + 3 files changed, 325 insertions(+), 21 deletions(-) create mode 100644 back/methods/imap-time-control/checkInbox.js diff --git a/back/methods/imap-time-control/checkInbox.js b/back/methods/imap-time-control/checkInbox.js new file mode 100644 index 000000000..ff0b0a46e --- /dev/null +++ b/back/methods/imap-time-control/checkInbox.js @@ -0,0 +1,129 @@ +const Imap = require('imap'); + +module.exports = Self => { + Self.remoteMethod('checkInbox', { + description: 'Check an email inbox and process it', + accessType: 'READ', + returns: + { + arg: 'body', + type: 'file', + root: true + }, + http: { + path: `/checkInbox`, + verb: 'GET' + } + }); + + Self.checkInbox = async() => { + let imapConfig = await Self.app.models.WorkerTimeControlParams.findOne(); + let imap = new Imap({ + user: imapConfig.mailUser, + password: imapConfig.mailPass, + host: imapConfig.mailHost, + port: 993, + tls: true + }); + let isEmailOk; + let emailText = ''; + + function openInbox(cb) { + imap.openBox('INBOX', true, cb); + } + + imap.once('ready', function() { + openInbox(function(err, box) { + if (err) throw err; + let f = imap.seq.fetch('1:3', { + bodies: ['HEADER.FIELDS (FROM SUBJECT)', '1'], + struct: true + }); + f.on('message', function(msg, seqno) { + isEmailOk = false; + msg.on('body', function(stream, info) { + let buffer = ''; + stream.on('data', function(chunk) { + buffer = chunk.toString('utf8'); + if (info.which === '1') { + emailText = buffer.split('\n')[0]; + emailText = emailText.toUpperCase(); + emailText = emailText.replace(/\s/g, ''); + if (emailText === 'OK') + isEmailOk = true; // isEmailOk + } + }); + stream.once('end', function() { + if (info.which === 'HEADER.FIELDS (FROM SUBJECT)') { + console.log('isEmailOk', isEmailOk); + if (isEmailOk) { + emailConfirm(buffer); + imap.seq.move(seqno, 'exito', function(err) { + console.log('Move correcte: ' + err); + console.log('Move error: ' + seqno); + }); + } else { + emailReply(buffer); + imap.seq.move(seqno, 'error', function(err) { + console.log('Move error: ' + err); + console.log('Move error: ' + seqno); + }); + } + } + }); + }); + }); + // msg.on('attributes', function(attrs) { + // console.log('ATRIBUTO', attrs.struct[0]); + // console.log('ATRIBUTO', attrs.struct[0].params); + // }); + }); + }); + + imap.connect(); + return 'pepinillos'; + }; + async function getUser(workerEmail) { + let firstPosition = workerEmail.search('<') + 1; + let lastPosition = workerEmail.search('@') - firstPosition; + let userName = workerEmail.substr(firstPosition, lastPosition); + let user = await Self.app.models.Account.findOne({where: {name: userName}}); + return user; + } + + async function getEmailDate(subject) { + let date = subject.match(/\d+/g); + return date; + } + + async function emailConfirm(buffer) { + let now = new Date(); + let from = JSON.stringify(Imap.parseHeader(buffer).from); + let subject = JSON.stringify(Imap.parseHeader(buffer).subject); + + let timeControlDate = await getEmailDate(subject); + let week = timeControlDate[0]; + let year = timeControlDate[1]; + let user = await getUser(from); + + let workerMail = await Self.app.models.WorkerTimeControlMail.findOne({ + where: { + week: week, + year: year, + worker: user.id + } + }); + await workerMail.updateAttributes({ + updated: now, + state: 'CONFIRMED' + }); + // MOVER A CARPETA EXITO + } + async function emailReply(subject, workerEmail) { + console.log('bbbbb'); + + // INSERT EN VN.MAIL + // UPDATE EN WORKERTIMECONTROLMAIL + // MOVER A CARPETA ERROR + } +}; diff --git a/package-lock.json b/package-lock.json index 92030199a..28cfafa08 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4955,7 +4955,7 @@ }, "util": { "version": "0.10.3", - "resolved": "http://registry.npmjs.org/util/-/util-0.10.3.tgz", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", "dev": true, "requires": { @@ -5917,7 +5917,7 @@ "base": { "version": "0.11.2", "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=", "dev": true, "requires": { "cache-base": "^1.0.1", @@ -6423,7 +6423,7 @@ "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=", "dev": true, "requires": { "collection-visit": "^1.0.0", @@ -6637,7 +6637,7 @@ "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=", "dev": true, "requires": { "arr-union": "^3.1.0", @@ -7762,7 +7762,7 @@ "dot-prop": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", - "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "integrity": "sha1-HxngwuGqDjJ5fEl5nyg3rGr2nFc=", "requires": { "is-obj": "^1.0.0" } @@ -7925,6 +7925,11 @@ "iconv-lite": "~0.4.13" } }, + "encoding-japanese": { + "version": "1.0.30", + "resolved": "https://registry.npmjs.org/encoding-japanese/-/encoding-japanese-1.0.30.tgz", + "integrity": "sha512-bd/DFLAoJetvv7ar/KIpE3CNO8wEuyrt9Xuw6nSMiZ+Vrz/Q21BPsMHvARL2Wz6IKHKXgb+DWZqtRg1vql9cBg==" + }, "end-of-stream": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", @@ -8889,7 +8894,7 @@ }, "file-loader": { "version": "1.1.11", - "resolved": "http://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz", "integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==", "dev": true, "requires": { @@ -10075,7 +10080,7 @@ "global-modules": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "integrity": "sha1-bXcPDrUjrHgWTXK15xqIdyZcw+o=", "dev": true, "requires": { "global-prefix": "^1.0.1", @@ -11412,8 +11417,7 @@ "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" }, "helmet": { "version": "3.21.2", @@ -11613,6 +11617,17 @@ } } }, + "html-to-text": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-5.1.1.tgz", + "integrity": "sha512-Bci6bD/JIfZSvG4s0gW/9mMKwBRoe/1RWLxUME/d6WUSZCdY7T60bssf/jFf7EYXRyqU4P5xdClVqiYU0/ypdA==", + "requires": { + "he": "^1.2.0", + "htmlparser2": "^3.10.1", + "lodash": "^4.17.11", + "minimist": "^1.2.0" + } + }, "html-webpack-plugin": { "version": "4.0.0-beta.11", "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-4.0.0-beta.11.tgz", @@ -11848,6 +11863,38 @@ "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", "dev": true }, + "imap": { + "version": "0.8.19", + "resolved": "https://registry.npmjs.org/imap/-/imap-0.8.19.tgz", + "integrity": "sha1-NniHOTSrCc6mukh0HyhNoq9Z2NU=", + "requires": { + "readable-stream": "1.1.x", + "utf7": ">=1.0.2" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, "import-fresh": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz", @@ -12258,7 +12305,7 @@ "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=", "dev": true, "requires": { "isobject": "^3.0.1" @@ -12612,7 +12659,7 @@ "jasmine-spec-reporter": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-4.2.1.tgz", - "integrity": "sha512-FZBoZu7VE5nR7Nilzy+Np8KuVIOxF4oXDPDknehCYBDE080EnlPu0afdZNmpGDBRCUBv3mj5qgqCRmk6W/K8vg==", + "integrity": "sha1-HWMq7ANBZwrTJPkrqEtLMrNeniI=", "dev": true, "requires": { "colors": "1.1.2" @@ -17602,6 +17649,32 @@ "type-check": "~0.3.2" } }, + "libbase64": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-1.2.1.tgz", + "integrity": "sha512-l+nePcPbIG1fNlqMzrh68MLkX/gTxk/+vdvAb388Ssi7UuUN31MI44w4Yf33mM3Cm4xDfw48mdf3rkdHszLNew==" + }, + "libmime": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/libmime/-/libmime-5.0.0.tgz", + "integrity": "sha512-2Bm96d5ktnE217Ib1FldvUaPAaOst6GtZrsxJCwnJgi9lnsoAKIHyU0sae8rNx6DNYbjdqqh8lv5/b9poD8qOg==", + "requires": { + "encoding-japanese": "1.0.30", + "iconv-lite": "0.6.2", + "libbase64": "1.2.1", + "libqp": "1.1.0" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", + "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + } + } + }, "liboneandone": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/liboneandone/-/liboneandone-1.2.0.tgz", @@ -17611,6 +17684,11 @@ "request": "^2.74.0" } }, + "libqp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz", + "integrity": "sha1-9ebgatdLeU+1tbZpiL9yjvHe2+g=" + }, "liftoff": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", @@ -17633,6 +17711,14 @@ "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", "dev": true }, + "linkify-it": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.2.tgz", + "integrity": "sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ==", + "requires": { + "uc.micro": "^1.0.1" + } + }, "load-json-file": { "version": "1.1.0", "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", @@ -18379,6 +18465,68 @@ "yallist": "^3.0.2" } }, + "mailparser": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/mailparser/-/mailparser-2.8.0.tgz", + "integrity": "sha512-Ja5H6/I1NKIFdFJF5HdZkaMGCN8F+1lu3870ZmrabkHQshhrPk4OWeEMiF0OVo82+6XJqemJPCg6pqgXaj3B6Q==", + "requires": { + "encoding-japanese": "1.0.30", + "he": "1.2.0", + "html-to-text": "5.1.1", + "iconv-lite": "0.6.2", + "libmime": "5.0.0", + "linkify-it": "3.0.2", + "mailsplit": "5.0.0", + "nodemailer": "6.4.10", + "tlds": "1.207.0" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", + "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, + "nodemailer": { + "version": "6.4.10", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.4.10.tgz", + "integrity": "sha512-j+pS9CURhPgk6r0ENr7dji+As2xZiHSvZeVnzKniLOw1eRAyM/7flP0u65tCnsapV8JFu+t0l/5VeHsCZEeh9g==" + } + } + }, + "mailsplit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mailsplit/-/mailsplit-5.0.0.tgz", + "integrity": "sha512-HeXA0eyCKBtZqbr7uoeb3Nn2L7VV8Vm27x6/YBb0ZiNzRzLoNS2PqRgGYADwh0cBzLYtqddq40bSSirqLO2LGw==", + "requires": { + "libbase64": "1.2.1", + "libmime": "4.2.1", + "libqp": "1.1.0" + }, + "dependencies": { + "iconv-lite": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.0.tgz", + "integrity": "sha512-NnEhI9hIEKHOzJ4f697DMz9IQEXr/MMJ5w64vN2/4Ai+wRnvV7SBrL0KLoRlwaKVghOc7LQ5YkPLuX146b6Ydw==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "libmime": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/libmime/-/libmime-4.2.1.tgz", + "integrity": "sha512-09y7zjSc5im1aNsq815zgo4/G3DnIzym3aDOHsGq4Ee5vrX4PdgQRybAsztz9Rv0NhO+J5C0llEUloa3sUmjmA==", + "requires": { + "encoding-japanese": "1.0.30", + "iconv-lite": "0.5.0", + "libbase64": "1.2.1", + "libqp": "1.1.0" + } + } + } + }, "make-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", @@ -21087,7 +21235,7 @@ "dependencies": { "jsesc": { "version": "0.5.0", - "resolved": "http://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", "dev": true } @@ -21474,7 +21622,7 @@ }, "safe-regex": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { @@ -21675,7 +21823,7 @@ "dependencies": { "source-map": { "version": "0.4.4", - "resolved": "http://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", "dev": true, "requires": { @@ -22123,7 +22271,7 @@ "snapdragon-node": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=", "dev": true, "requires": { "define-property": "^1.0.0", @@ -22174,7 +22322,7 @@ "snapdragon-util": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=", "dev": true, "requires": { "kind-of": "^3.2.0" @@ -22458,7 +22606,7 @@ "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=", "dev": true, "requires": { "extend-shallow": "^3.0.0" @@ -23596,6 +23744,11 @@ "setimmediate": "^1.0.4" } }, + "tlds": { + "version": "1.207.0", + "resolved": "https://registry.npmjs.org/tlds/-/tlds-1.207.0.tgz", + "integrity": "sha512-k7d7Q1LqjtAvhtEOs3yN14EabsNO8ZCoY6RESSJDB9lst3bTx3as/m1UuAeCKzYxiyhR1qq72ZPhpSf+qlqiwg==" + }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -23731,7 +23884,7 @@ "touch": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", - "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "integrity": "sha1-/jZfX3XsntTlaCXgu3bSSrdK+Ds=", "dev": true, "requires": { "nopt": "~1.0.10" @@ -23880,6 +24033,11 @@ "is-typedarray": "^1.0.0" } }, + "uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" + }, "uglify-js": { "version": "3.4.10", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz", @@ -24220,6 +24378,21 @@ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", "dev": true }, + "utf7": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/utf7/-/utf7-1.0.2.tgz", + "integrity": "sha1-lV9JCq5lO6IguUVqCod2wZk2CZE=", + "requires": { + "semver": "~5.3.0" + }, + "dependencies": { + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" + } + } + }, "utf8-bytes": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/utf8-bytes/-/utf8-bytes-0.0.1.tgz", @@ -25009,7 +25182,7 @@ }, "globby": { "version": "6.1.0", - "resolved": "http://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", "dev": true, "requires": { @@ -25022,7 +25195,7 @@ "dependencies": { "pify": { "version": "2.3.0", - "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } @@ -25495,7 +25668,7 @@ }, "xmlbuilder": { "version": "9.0.7", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "resolved": "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" }, "xmlchars": { diff --git a/package.json b/package.json index b7cca0364..837eab8b3 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "fs-extra": "^5.0.0", "helmet": "^3.21.2", "i18n": "^0.8.4", + "imap": "^0.8.19", "loopback": "^3.26.0", "loopback-boot": "^2.27.1", "loopback-component-explorer": "^6.5.0", @@ -23,6 +24,7 @@ "loopback-connector-mysql": "^5.4.3", "loopback-connector-remote": "^3.4.1", "loopback-context": "^3.4.0", + "mailparser": "^2.8.0", "md5": "^2.2.1", "object-diff": "0.0.4", "object.pick": "^1.3.0", From 06f03c6b849c7d50afd49d8011aa2c1c0c93c13d Mon Sep 17 00:00:00 2001 From: Bernat Exposito Domenech Date: Tue, 22 Sep 2020 13:59:00 +0200 Subject: [PATCH 03/11] mail models and fix checkInbox --- back/methods/imap-time-control/checkInbox.js | 165 +++++++++++++------ back/model-config.json | 3 + back/models/mail-forward.json | 26 +++ back/models/mail.json | 3 +- db/tests/vn/workerTimeControlCheck.spec.js | 2 +- modules/worker/back/models/worker.json | 3 + 6 files changed, 145 insertions(+), 57 deletions(-) create mode 100644 back/models/mail-forward.json diff --git a/back/methods/imap-time-control/checkInbox.js b/back/methods/imap-time-control/checkInbox.js index ff0b0a46e..4f3cb06b0 100644 --- a/back/methods/imap-time-control/checkInbox.js +++ b/back/methods/imap-time-control/checkInbox.js @@ -1,5 +1,5 @@ const Imap = require('imap'); - +const {NULL} = require('node-sass'); module.exports = Self => { Self.remoteMethod('checkInbox', { description: 'Check an email inbox and process it', @@ -26,7 +26,8 @@ module.exports = Self => { tls: true }); let isEmailOk; - let emailText = ''; + let uid; + let emailBody; function openInbox(cb) { imap.openBox('INBOX', true, cb); @@ -35,7 +36,7 @@ module.exports = Self => { imap.once('ready', function() { openInbox(function(err, box) { if (err) throw err; - let f = imap.seq.fetch('1:3', { + let f = imap.seq.fetch('1:*', { bodies: ['HEADER.FIELDS (FROM SUBJECT)', '1'], struct: true }); @@ -43,87 +44,143 @@ module.exports = Self => { isEmailOk = false; msg.on('body', function(stream, info) { let buffer = ''; + let bufferCopy = ''; stream.on('data', function(chunk) { + // console.log('chunk', chunk); buffer = chunk.toString('utf8'); - if (info.which === '1') { - emailText = buffer.split('\n')[0]; - emailText = emailText.toUpperCase(); - emailText = emailText.replace(/\s/g, ''); - if (emailText === 'OK') - isEmailOk = true; // isEmailOk + // console.log('buffer', buffer); + if (info.which === '1' && bufferCopy.length == 0) + bufferCopy = buffer.replace(/\s/g, ' '); + }); + stream.on('end', function() { + if (bufferCopy.length > 0) { + emailBody = bufferCopy.toUpperCase().trim(); + + const bodyPositionOK = emailBody.match(/\bOK\b/i); + + if (bodyPositionOK != null && (bodyPositionOK.index == 0 || bodyPositionOK.index == 122)) + isEmailOk = true; + else + isEmailOk = false; } }); - stream.once('end', function() { + msg.once('attributes', function(attrs) { + uid = attrs.uid; + // let structure = attrs.struct[2][0]; + // console.log('attrs.struct', structure); + // console.log('attrs', structure.params); + // console.log('attrs.struct', structure.find(item => item.subtype === 'html')); + }); + msg.once('end', function() { if (info.which === 'HEADER.FIELDS (FROM SUBJECT)') { - console.log('isEmailOk', isEmailOk); if (isEmailOk) { + imap.move(uid, 'exito', function(err) { + }); emailConfirm(buffer); - imap.seq.move(seqno, 'exito', function(err) { - console.log('Move correcte: ' + err); - console.log('Move error: ' + seqno); - }); } else { - emailReply(buffer); - imap.seq.move(seqno, 'error', function(err) { - console.log('Move error: ' + err); - console.log('Move error: ' + seqno); + imap.move(uid, 'error', function(err) { }); + emailReply(buffer, emailBody); } } }); }); }); - // msg.on('attributes', function(attrs) { - // console.log('ATRIBUTO', attrs.struct[0]); - // console.log('ATRIBUTO', attrs.struct[0].params); - // }); + f.once('end', function() { + imap.end(); + }); }); }); imap.connect(); - return 'pepinillos'; + return 'Leer emails de gestion horaria'; }; - async function getUser(workerEmail) { - let firstPosition = workerEmail.search('<') + 1; - let lastPosition = workerEmail.search('@') - firstPosition; - let userName = workerEmail.substr(firstPosition, lastPosition); - let user = await Self.app.models.Account.findOne({where: {name: userName}}); - return user; - } - - async function getEmailDate(subject) { - let date = subject.match(/\d+/g); - return date; - } async function emailConfirm(buffer) { - let now = new Date(); - let from = JSON.stringify(Imap.parseHeader(buffer).from); - let subject = JSON.stringify(Imap.parseHeader(buffer).subject); + // try { + const now = new Date(); + const from = JSON.stringify(Imap.parseHeader(buffer).from); + const subject = JSON.stringify(Imap.parseHeader(buffer).subject); - let timeControlDate = await getEmailDate(subject); - let week = timeControlDate[0]; - let year = timeControlDate[1]; - let user = await getUser(from); + const timeControlDate = await getEmailDate(subject); + const week = timeControlDate[0]; + const year = timeControlDate[1]; + const user = await getUser(from); let workerMail = await Self.app.models.WorkerTimeControlMail.findOne({ where: { week: week, year: year, - worker: user.id + workerFk: user.id } }); - await workerMail.updateAttributes({ - updated: now, - state: 'CONFIRMED' - }); - // MOVER A CARPETA EXITO + if (workerMail != NULL) { + await workerMail.updateAttributes({ + updated: now, + state: 'CONFIRMED' + }); + } + // } catch (err) { + // throw err; + // } } - async function emailReply(subject, workerEmail) { - console.log('bbbbb'); - // INSERT EN VN.MAIL - // UPDATE EN WORKERTIMECONTROLMAIL - // MOVER A CARPETA ERROR + async function emailReply(buffer, emailBody) { + // try { + const now = new Date(); + const from = JSON.stringify(Imap.parseHeader(buffer).from); + const subject = JSON.stringify(Imap.parseHeader(buffer).subject); + + const timeControlDate = await getEmailDate(subject); + const week = timeControlDate[0]; + const year = timeControlDate[1]; + const user = await getUser(from); + + let workerMail = await Self.app.models.WorkerTimeControlMail.findOne({ + where: { + week: week, + year: year, + workerFk: user.id + } + }); + if (workerMail != NULL) { + await workerMail.updateAttributes({ + updated: now, + state: 'REVISE' + }); + } + + await sendMail(user, subject, emailBody); + // } catch (err) { + // throw err; + // } + } + + async function getUser(workerEmail) { + const userEmail = workerEmail.match(/(?<=<)(.*?)(?=>)/); + + let [user] = await Self.rawSql(`SELECT u.id,u.name FROM account.user u + LEFT JOIN account.mailForward m on m.account = u.id + WHERE forwardTo =? OR + CONCAT(u.name,'@verdnatura.es') = ?`, + [userEmail[0], userEmail[0]]); + + return user; + } + + async function getEmailDate(subject) { + const date = subject.match(/\d+/g); + return date; + } + + async function sendMail(user, subject, emailBody) { + const sendTo = 'rrhh@verdnatura.es'; + const emailSubject = subject + ' ' + user.name; + + await Self.app.models.Mail.create({ + sender: sendTo, + subject: emailSubject, + body: emailBody + }); } }; diff --git a/back/model-config.json b/back/model-config.json index 46733696f..07900448c 100644 --- a/back/model-config.json +++ b/back/model-config.json @@ -79,6 +79,9 @@ }, "Mail": { "dataSource": "vn" + }, + "MailForward": { + "dataSource": "vn" } } diff --git a/back/models/mail-forward.json b/back/models/mail-forward.json new file mode 100644 index 000000000..40b695a7a --- /dev/null +++ b/back/models/mail-forward.json @@ -0,0 +1,26 @@ +{ + "name": "MailForward", + "base": "VnModel", + "options": { + "mysql": { + "table": "account.mailForward" + } + }, + "properties": { + "account": { + "id": true, + "type": "Number" + }, + "forwardTo": { + "type": "String" + } + }, + "acls": [ + { + "accessType": "READ", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "ALLOW" + } + ] +} diff --git a/back/models/mail.json b/back/models/mail.json index cf5c11993..3861460f3 100644 --- a/back/models/mail.json +++ b/back/models/mail.json @@ -9,8 +9,7 @@ "properties": { "id": { "id": true, - "type": "Number", - "required": true + "type": "Number" }, "sender": { "type": "String" diff --git a/db/tests/vn/workerTimeControlCheck.spec.js b/db/tests/vn/workerTimeControlCheck.spec.js index 4869e38a6..f70a0b1c3 100644 --- a/db/tests/vn/workerTimeControlCheck.spec.js +++ b/db/tests/vn/workerTimeControlCheck.spec.js @@ -1,7 +1,7 @@ const app = require('vn-loopback/server/server'); const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; -// #2257 xdescribe dbtest workerTimeControl_check() +// #2261 xdescribe dbtest workerTimeControl_check() xdescribe('worker workerTimeControl_check()', () => { it(`should throw an error if the worker can't sign on that tablet`, async() => { let stmts = []; diff --git a/modules/worker/back/models/worker.json b/modules/worker/back/models/worker.json index 6af7e8608..45eee23bf 100644 --- a/modules/worker/back/models/worker.json +++ b/modules/worker/back/models/worker.json @@ -31,6 +31,9 @@ "userFk": { "type" : "Number", "required": true + }, + "bossFk": { + "type" : "Number" } }, "relations": { From 2b2970bfcd1af3c6db22f8a941eef213bc585c4a Mon Sep 17 00:00:00 2001 From: Bernat Exposito Domenech Date: Wed, 23 Sep 2020 07:35:45 +0200 Subject: [PATCH 04/11] fix checkInbox --- back/methods/imap-time-control/checkInbox.js | 64 +++++++++----------- back/models/worker-time-control-mail.json | 3 + 2 files changed, 33 insertions(+), 34 deletions(-) diff --git a/back/methods/imap-time-control/checkInbox.js b/back/methods/imap-time-control/checkInbox.js index 4f3cb06b0..a79fe4418 100644 --- a/back/methods/imap-time-control/checkInbox.js +++ b/back/methods/imap-time-control/checkInbox.js @@ -46,9 +46,7 @@ module.exports = Self => { let buffer = ''; let bufferCopy = ''; stream.on('data', function(chunk) { - // console.log('chunk', chunk); buffer = chunk.toString('utf8'); - // console.log('buffer', buffer); if (info.which === '1' && bufferCopy.length == 0) bufferCopy = buffer.replace(/\s/g, ' '); }); @@ -66,10 +64,6 @@ module.exports = Self => { }); msg.once('attributes', function(attrs) { uid = attrs.uid; - // let structure = attrs.struct[2][0]; - // console.log('attrs.struct', structure); - // console.log('attrs', structure.params); - // console.log('attrs.struct', structure.find(item => item.subtype === 'html')); }); msg.once('end', function() { if (info.which === 'HEADER.FIELDS (FROM SUBJECT)') { @@ -97,7 +91,7 @@ module.exports = Self => { }; async function emailConfirm(buffer) { - // try { + console.log('buffer', buffer); const now = new Date(); const from = JSON.stringify(Imap.parseHeader(buffer).from); const subject = JSON.stringify(Imap.parseHeader(buffer).subject); @@ -106,27 +100,28 @@ module.exports = Self => { const week = timeControlDate[0]; const year = timeControlDate[1]; const user = await getUser(from); + let workerMail; - let workerMail = await Self.app.models.WorkerTimeControlMail.findOne({ - where: { - week: week, - year: year, - workerFk: user.id - } - }); + if (user.id != NULL) { + workerMail = await Self.app.models.WorkerTimeControlMail.findOne({ + where: { + week: week, + year: year, + workerFk: user.id + } + }); + } if (workerMail != NULL) { await workerMail.updateAttributes({ updated: now, state: 'CONFIRMED' }); } - // } catch (err) { - // throw err; - // } } async function emailReply(buffer, emailBody) { - // try { + console.log('buffer', buffer); + console.log('emailBody', emailBody); const now = new Date(); const from = JSON.stringify(Imap.parseHeader(buffer).from); const subject = JSON.stringify(Imap.parseHeader(buffer).subject); @@ -135,25 +130,26 @@ module.exports = Self => { const week = timeControlDate[0]; const year = timeControlDate[1]; const user = await getUser(from); + let workerMail; - let workerMail = await Self.app.models.WorkerTimeControlMail.findOne({ - where: { - week: week, - year: year, - workerFk: user.id - } - }); - if (workerMail != NULL) { - await workerMail.updateAttributes({ - updated: now, - state: 'REVISE' + if (user.id != NULL) { + workerMail = await Self.app.models.WorkerTimeControlMail.findOne({ + where: { + week: week, + year: year, + workerFk: user.id + } }); - } - await sendMail(user, subject, emailBody); - // } catch (err) { - // throw err; - // } + if (workerMail != NULL) { + await workerMail.updateAttributes({ + updated: now, + state: 'REVISE', + emailResponse: emailBody + }); + } else + await sendMail(user, subject, emailBody); + } } async function getUser(workerEmail) { diff --git a/back/models/worker-time-control-mail.json b/back/models/worker-time-control-mail.json index 4a0fd31f1..81ca235d7 100644 --- a/back/models/worker-time-control-mail.json +++ b/back/models/worker-time-control-mail.json @@ -26,6 +26,9 @@ }, "updated": { "type": "Date" + }, + "emailResponse": { + "type": "String" } }, "acls": [ From d4c819ebf722e7c8cd185cd26f4f00ac711aa271 Mon Sep 17 00:00:00 2001 From: Bernat Exposito Domenech Date: Tue, 11 Aug 2020 11:03:43 +0200 Subject: [PATCH 05/11] new models and fixtures --- back/model-config.json | 9 +++++ back/models/mail.json | 36 +++++++++++++++++ back/models/worker-time-control-mail.json | 39 +++++++++++++++++++ back/models/worker-time-control-params.js | 3 ++ back/models/worker-time-control-params.json | 35 +++++++++++++++++ .../00-workerTimeControlParams.sql | 6 +++ db/dump/fixtures.sql | 4 +- 7 files changed, 130 insertions(+), 2 deletions(-) create mode 100644 back/models/mail.json create mode 100644 back/models/worker-time-control-mail.json create mode 100644 back/models/worker-time-control-params.js create mode 100644 back/models/worker-time-control-params.json create mode 100644 db/changes/12300-Summer/00-workerTimeControlParams.sql diff --git a/back/model-config.json b/back/model-config.json index dc5cde217..46733696f 100644 --- a/back/model-config.json +++ b/back/model-config.json @@ -70,6 +70,15 @@ }, "UserLog": { "dataSource": "vn" + }, + "WorkerTimeControlParams": { + "dataSource": "vn" + }, + "WorkerTimeControlMail": { + "dataSource": "vn" + }, + "Mail": { + "dataSource": "vn" } } diff --git a/back/models/mail.json b/back/models/mail.json new file mode 100644 index 000000000..cf5c11993 --- /dev/null +++ b/back/models/mail.json @@ -0,0 +1,36 @@ +{ + "name": "Mail", + "base": "VnModel", + "options": { + "mysql": { + "table": "mail" + } + }, + "properties": { + "id": { + "id": true, + "type": "Number", + "required": true + }, + "sender": { + "type": "String" + }, + "replyTo": { + "type": "String" + }, + "subject": { + "type": "String" + }, + "body": { + "type": "String" + } + }, + "acls": [ + { + "accessType": "READ", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "ALLOW" + } + ] +} diff --git a/back/models/worker-time-control-mail.json b/back/models/worker-time-control-mail.json new file mode 100644 index 000000000..4a0fd31f1 --- /dev/null +++ b/back/models/worker-time-control-mail.json @@ -0,0 +1,39 @@ +{ + "name": "WorkerTimeControlMail", + "base": "VnModel", + "options": { + "mysql": { + "table": "workerTimeControlMail" + } + }, + "properties": { + "id": { + "id": true, + "type": "Number", + "required": true + }, + "workerFk": { + "type": "Number" + }, + "year": { + "type": "Number" + }, + "week": { + "type": "Number" + }, + "state": { + "type": "String" + }, + "updated": { + "type": "Date" + } + }, + "acls": [ + { + "accessType": "READ", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "ALLOW" + } + ] +} diff --git a/back/models/worker-time-control-params.js b/back/models/worker-time-control-params.js new file mode 100644 index 000000000..c71d4c237 --- /dev/null +++ b/back/models/worker-time-control-params.js @@ -0,0 +1,3 @@ +module.exports = Self => { + require('../methods/imap-time-control/checkInbox')(Self); +}; diff --git a/back/models/worker-time-control-params.json b/back/models/worker-time-control-params.json new file mode 100644 index 000000000..cc904cf40 --- /dev/null +++ b/back/models/worker-time-control-params.json @@ -0,0 +1,35 @@ +{ + "name": "WorkerTimeControlParams", + "description": "imap config", + "base": "VnModel", + "options": { + "mysql": { + "table": "workerTimeControlParams" + } + }, + "properties": { + "mailHost": { + "type": "String" + }, + "mailUser": { + "type": "String" + }, + "mailPass": { + "type": "String" + }, + "mailSuccessFolder": { + "type": "String" + }, + "mailErrorFolder": { + "type": "String" + } + }, + "acls": [ + { + "accessType": "READ", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "ALLOW" + } + ] +} diff --git a/db/changes/12300-Summer/00-workerTimeControlParams.sql b/db/changes/12300-Summer/00-workerTimeControlParams.sql new file mode 100644 index 000000000..47ef2e3ea --- /dev/null +++ b/db/changes/12300-Summer/00-workerTimeControlParams.sql @@ -0,0 +1,6 @@ +ALTER TABLE `vn`.`workerTimeControlParams` +ADD COLUMN `mailUser` VARCHAR(45) NOT NULL AFTER `askInOut`, +ADD COLUMN `mailPass` VARCHAR(45) NOT NULL AFTER `mailUser`, +ADD COLUMN `mailHost` VARCHAR(45) NOT NULL AFTER `mailPass`, +ADD COLUMN `mailSuccessFolder` VARCHAR(45) NOT NULL AFTER `mailHost`, +ADD COLUMN `mailErrorFolder` VARCHAR(45) NOT NULL AFTER `mailSuccessFolder`; diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 22fa2076a..5d886c9d8 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2067,9 +2067,9 @@ INSERT INTO `vn`.`queuePriority`(`id`, `priority`) (2, 'Normal'), (3, 'Baja'); -INSERT INTO `vn`.`workerTimeControlParams` (`id`, `dayBreak`, `weekBreak`, `weekScope`, `dayWorkMax`, `dayStayMax`, `weekMaxBreak`, `weekMaxScope`, `askInOut`) +INSERT INTO `vn`.`workerTimeControlParams` (`id`, `dayBreak`, `weekBreak`, `weekScope`, `dayWorkMax`, `dayStayMax`, `weekMaxBreak`, `weekMaxScope`, `askInOut`, `mailSuccessFolder`, `mailErrorFolder`) VALUES - (1, 43200, 129600, 734400, 43200, 50400, 259200, 1296000, 36000); + (1, 43200, 129600, 734400, 43200, 50400, 259200, 1296000, 36000, 'Leidos.exito', 'Leidos.error'); INSERT IGNORE INTO `vn`.`greugeConfig` (`id`, `freightPickUpPrice`) VALUES ('1', '11'); From 01574b8967ff0332373c411a992eded5360c2ac0 Mon Sep 17 00:00:00 2001 From: Bernat Exposito Domenech Date: Tue, 11 Aug 2020 11:12:40 +0200 Subject: [PATCH 06/11] new method for imap --- back/methods/imap-time-control/checkInbox.js | 129 +++++++++++++ package-lock.json | 183 ++++++++++++++++++- package.json | 2 + 3 files changed, 309 insertions(+), 5 deletions(-) create mode 100644 back/methods/imap-time-control/checkInbox.js diff --git a/back/methods/imap-time-control/checkInbox.js b/back/methods/imap-time-control/checkInbox.js new file mode 100644 index 000000000..ff0b0a46e --- /dev/null +++ b/back/methods/imap-time-control/checkInbox.js @@ -0,0 +1,129 @@ +const Imap = require('imap'); + +module.exports = Self => { + Self.remoteMethod('checkInbox', { + description: 'Check an email inbox and process it', + accessType: 'READ', + returns: + { + arg: 'body', + type: 'file', + root: true + }, + http: { + path: `/checkInbox`, + verb: 'GET' + } + }); + + Self.checkInbox = async() => { + let imapConfig = await Self.app.models.WorkerTimeControlParams.findOne(); + let imap = new Imap({ + user: imapConfig.mailUser, + password: imapConfig.mailPass, + host: imapConfig.mailHost, + port: 993, + tls: true + }); + let isEmailOk; + let emailText = ''; + + function openInbox(cb) { + imap.openBox('INBOX', true, cb); + } + + imap.once('ready', function() { + openInbox(function(err, box) { + if (err) throw err; + let f = imap.seq.fetch('1:3', { + bodies: ['HEADER.FIELDS (FROM SUBJECT)', '1'], + struct: true + }); + f.on('message', function(msg, seqno) { + isEmailOk = false; + msg.on('body', function(stream, info) { + let buffer = ''; + stream.on('data', function(chunk) { + buffer = chunk.toString('utf8'); + if (info.which === '1') { + emailText = buffer.split('\n')[0]; + emailText = emailText.toUpperCase(); + emailText = emailText.replace(/\s/g, ''); + if (emailText === 'OK') + isEmailOk = true; // isEmailOk + } + }); + stream.once('end', function() { + if (info.which === 'HEADER.FIELDS (FROM SUBJECT)') { + console.log('isEmailOk', isEmailOk); + if (isEmailOk) { + emailConfirm(buffer); + imap.seq.move(seqno, 'exito', function(err) { + console.log('Move correcte: ' + err); + console.log('Move error: ' + seqno); + }); + } else { + emailReply(buffer); + imap.seq.move(seqno, 'error', function(err) { + console.log('Move error: ' + err); + console.log('Move error: ' + seqno); + }); + } + } + }); + }); + }); + // msg.on('attributes', function(attrs) { + // console.log('ATRIBUTO', attrs.struct[0]); + // console.log('ATRIBUTO', attrs.struct[0].params); + // }); + }); + }); + + imap.connect(); + return 'pepinillos'; + }; + async function getUser(workerEmail) { + let firstPosition = workerEmail.search('<') + 1; + let lastPosition = workerEmail.search('@') - firstPosition; + let userName = workerEmail.substr(firstPosition, lastPosition); + let user = await Self.app.models.Account.findOne({where: {name: userName}}); + return user; + } + + async function getEmailDate(subject) { + let date = subject.match(/\d+/g); + return date; + } + + async function emailConfirm(buffer) { + let now = new Date(); + let from = JSON.stringify(Imap.parseHeader(buffer).from); + let subject = JSON.stringify(Imap.parseHeader(buffer).subject); + + let timeControlDate = await getEmailDate(subject); + let week = timeControlDate[0]; + let year = timeControlDate[1]; + let user = await getUser(from); + + let workerMail = await Self.app.models.WorkerTimeControlMail.findOne({ + where: { + week: week, + year: year, + worker: user.id + } + }); + await workerMail.updateAttributes({ + updated: now, + state: 'CONFIRMED' + }); + // MOVER A CARPETA EXITO + } + async function emailReply(subject, workerEmail) { + console.log('bbbbb'); + + // INSERT EN VN.MAIL + // UPDATE EN WORKERTIMECONTROLMAIL + // MOVER A CARPETA ERROR + } +}; diff --git a/package-lock.json b/package-lock.json index 37af78e3a..8bd4ddb07 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8795,6 +8795,11 @@ "iconv-lite": "~0.4.13" } }, + "encoding-japanese": { + "version": "1.0.30", + "resolved": "https://registry.npmjs.org/encoding-japanese/-/encoding-japanese-1.0.30.tgz", + "integrity": "sha512-bd/DFLAoJetvv7ar/KIpE3CNO8wEuyrt9Xuw6nSMiZ+Vrz/Q21BPsMHvARL2Wz6IKHKXgb+DWZqtRg1vql9cBg==" + }, "end-of-stream": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", @@ -12288,8 +12293,7 @@ "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" }, "helmet": { "version": "3.21.2", @@ -12489,6 +12493,17 @@ } } }, + "html-to-text": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-5.1.1.tgz", + "integrity": "sha512-Bci6bD/JIfZSvG4s0gW/9mMKwBRoe/1RWLxUME/d6WUSZCdY7T60bssf/jFf7EYXRyqU4P5xdClVqiYU0/ypdA==", + "requires": { + "he": "^1.2.0", + "htmlparser2": "^3.10.1", + "lodash": "^4.17.11", + "minimist": "^1.2.0" + } + }, "html-webpack-plugin": { "version": "4.0.0-beta.11", "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-4.0.0-beta.11.tgz", @@ -12724,6 +12739,38 @@ "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", "dev": true }, + "imap": { + "version": "0.8.19", + "resolved": "https://registry.npmjs.org/imap/-/imap-0.8.19.tgz", + "integrity": "sha1-NniHOTSrCc6mukh0HyhNoq9Z2NU=", + "requires": { + "readable-stream": "1.1.x", + "utf7": ">=1.0.2" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, "import-fresh": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz", @@ -13488,7 +13535,7 @@ "jasmine-spec-reporter": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-4.2.1.tgz", - "integrity": "sha512-FZBoZu7VE5nR7Nilzy+Np8KuVIOxF4oXDPDknehCYBDE080EnlPu0afdZNmpGDBRCUBv3mj5qgqCRmk6W/K8vg==", + "integrity": "sha1-HWMq7ANBZwrTJPkrqEtLMrNeniI=", "dev": true, "requires": { "colors": "1.1.2" @@ -18481,6 +18528,32 @@ "type-check": "~0.3.2" } }, + "libbase64": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-1.2.1.tgz", + "integrity": "sha512-l+nePcPbIG1fNlqMzrh68MLkX/gTxk/+vdvAb388Ssi7UuUN31MI44w4Yf33mM3Cm4xDfw48mdf3rkdHszLNew==" + }, + "libmime": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/libmime/-/libmime-5.0.0.tgz", + "integrity": "sha512-2Bm96d5ktnE217Ib1FldvUaPAaOst6GtZrsxJCwnJgi9lnsoAKIHyU0sae8rNx6DNYbjdqqh8lv5/b9poD8qOg==", + "requires": { + "encoding-japanese": "1.0.30", + "iconv-lite": "0.6.2", + "libbase64": "1.2.1", + "libqp": "1.1.0" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", + "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + } + } + }, "liboneandone": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/liboneandone/-/liboneandone-1.2.0.tgz", @@ -18490,6 +18563,11 @@ "request": "^2.74.0" } }, + "libqp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz", + "integrity": "sha1-9ebgatdLeU+1tbZpiL9yjvHe2+g=" + }, "liftoff": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", @@ -18512,6 +18590,14 @@ "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", "dev": true }, + "linkify-it": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.2.tgz", + "integrity": "sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ==", + "requires": { + "uc.micro": "^1.0.1" + } + }, "load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", @@ -19258,6 +19344,68 @@ "yallist": "^3.0.2" } }, + "mailparser": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/mailparser/-/mailparser-2.8.0.tgz", + "integrity": "sha512-Ja5H6/I1NKIFdFJF5HdZkaMGCN8F+1lu3870ZmrabkHQshhrPk4OWeEMiF0OVo82+6XJqemJPCg6pqgXaj3B6Q==", + "requires": { + "encoding-japanese": "1.0.30", + "he": "1.2.0", + "html-to-text": "5.1.1", + "iconv-lite": "0.6.2", + "libmime": "5.0.0", + "linkify-it": "3.0.2", + "mailsplit": "5.0.0", + "nodemailer": "6.4.10", + "tlds": "1.207.0" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", + "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, + "nodemailer": { + "version": "6.4.10", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.4.10.tgz", + "integrity": "sha512-j+pS9CURhPgk6r0ENr7dji+As2xZiHSvZeVnzKniLOw1eRAyM/7flP0u65tCnsapV8JFu+t0l/5VeHsCZEeh9g==" + } + } + }, + "mailsplit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mailsplit/-/mailsplit-5.0.0.tgz", + "integrity": "sha512-HeXA0eyCKBtZqbr7uoeb3Nn2L7VV8Vm27x6/YBb0ZiNzRzLoNS2PqRgGYADwh0cBzLYtqddq40bSSirqLO2LGw==", + "requires": { + "libbase64": "1.2.1", + "libmime": "4.2.1", + "libqp": "1.1.0" + }, + "dependencies": { + "iconv-lite": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.0.tgz", + "integrity": "sha512-NnEhI9hIEKHOzJ4f697DMz9IQEXr/MMJ5w64vN2/4Ai+wRnvV7SBrL0KLoRlwaKVghOc7LQ5YkPLuX146b6Ydw==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "libmime": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/libmime/-/libmime-4.2.1.tgz", + "integrity": "sha512-09y7zjSc5im1aNsq815zgo4/G3DnIzym3aDOHsGq4Ee5vrX4PdgQRybAsztz9Rv0NhO+J5C0llEUloa3sUmjmA==", + "requires": { + "encoding-japanese": "1.0.30", + "iconv-lite": "0.5.0", + "libbase64": "1.2.1", + "libqp": "1.1.0" + } + } + } + }, "make-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", @@ -24464,6 +24612,11 @@ "setimmediate": "^1.0.4" } }, + "tlds": { + "version": "1.207.0", + "resolved": "https://registry.npmjs.org/tlds/-/tlds-1.207.0.tgz", + "integrity": "sha512-k7d7Q1LqjtAvhtEOs3yN14EabsNO8ZCoY6RESSJDB9lst3bTx3as/m1UuAeCKzYxiyhR1qq72ZPhpSf+qlqiwg==" + }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -24748,6 +24901,11 @@ "is-typedarray": "^1.0.0" } }, + "uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" + }, "uglify-js": { "version": "3.4.10", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz", @@ -25088,6 +25246,21 @@ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", "dev": true }, + "utf7": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/utf7/-/utf7-1.0.2.tgz", + "integrity": "sha1-lV9JCq5lO6IguUVqCod2wZk2CZE=", + "requires": { + "semver": "~5.3.0" + }, + "dependencies": { + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" + } + } + }, "utf8-bytes": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/utf8-bytes/-/utf8-bytes-0.0.1.tgz", @@ -25877,7 +26050,7 @@ }, "globby": { "version": "6.1.0", - "resolved": "http://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", "dev": true, "requires": { @@ -25890,7 +26063,7 @@ "dependencies": { "pify": { "version": "2.3.0", - "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } diff --git a/package.json b/package.json index f9d291467..b407bdfef 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "fs-extra": "^5.0.0", "helmet": "^3.21.2", "i18n": "^0.8.4", + "imap": "^0.8.19", "loopback": "^3.26.0", "loopback-boot": "^2.27.1", "loopback-component-explorer": "^6.5.0", @@ -23,6 +24,7 @@ "loopback-connector-mysql": "^5.4.3", "loopback-connector-remote": "^3.4.1", "loopback-context": "^3.4.0", + "mailparser": "^2.8.0", "md5": "^2.2.1", "object-diff": "0.0.4", "object.pick": "^1.3.0", From ca41b93995fc9d563482aaca7011bd96a0238bbc Mon Sep 17 00:00:00 2001 From: Bernat Exposito Domenech Date: Tue, 22 Sep 2020 13:59:00 +0200 Subject: [PATCH 07/11] mail models and fix checkInbox --- back/methods/imap-time-control/checkInbox.js | 165 +++++++++++++------ back/model-config.json | 3 + back/models/mail-forward.json | 26 +++ back/models/mail.json | 3 +- db/tests/vn/workerTimeControlCheck.spec.js | 2 +- modules/worker/back/models/worker.json | 3 + 6 files changed, 145 insertions(+), 57 deletions(-) create mode 100644 back/models/mail-forward.json diff --git a/back/methods/imap-time-control/checkInbox.js b/back/methods/imap-time-control/checkInbox.js index ff0b0a46e..4f3cb06b0 100644 --- a/back/methods/imap-time-control/checkInbox.js +++ b/back/methods/imap-time-control/checkInbox.js @@ -1,5 +1,5 @@ const Imap = require('imap'); - +const {NULL} = require('node-sass'); module.exports = Self => { Self.remoteMethod('checkInbox', { description: 'Check an email inbox and process it', @@ -26,7 +26,8 @@ module.exports = Self => { tls: true }); let isEmailOk; - let emailText = ''; + let uid; + let emailBody; function openInbox(cb) { imap.openBox('INBOX', true, cb); @@ -35,7 +36,7 @@ module.exports = Self => { imap.once('ready', function() { openInbox(function(err, box) { if (err) throw err; - let f = imap.seq.fetch('1:3', { + let f = imap.seq.fetch('1:*', { bodies: ['HEADER.FIELDS (FROM SUBJECT)', '1'], struct: true }); @@ -43,87 +44,143 @@ module.exports = Self => { isEmailOk = false; msg.on('body', function(stream, info) { let buffer = ''; + let bufferCopy = ''; stream.on('data', function(chunk) { + // console.log('chunk', chunk); buffer = chunk.toString('utf8'); - if (info.which === '1') { - emailText = buffer.split('\n')[0]; - emailText = emailText.toUpperCase(); - emailText = emailText.replace(/\s/g, ''); - if (emailText === 'OK') - isEmailOk = true; // isEmailOk + // console.log('buffer', buffer); + if (info.which === '1' && bufferCopy.length == 0) + bufferCopy = buffer.replace(/\s/g, ' '); + }); + stream.on('end', function() { + if (bufferCopy.length > 0) { + emailBody = bufferCopy.toUpperCase().trim(); + + const bodyPositionOK = emailBody.match(/\bOK\b/i); + + if (bodyPositionOK != null && (bodyPositionOK.index == 0 || bodyPositionOK.index == 122)) + isEmailOk = true; + else + isEmailOk = false; } }); - stream.once('end', function() { + msg.once('attributes', function(attrs) { + uid = attrs.uid; + // let structure = attrs.struct[2][0]; + // console.log('attrs.struct', structure); + // console.log('attrs', structure.params); + // console.log('attrs.struct', structure.find(item => item.subtype === 'html')); + }); + msg.once('end', function() { if (info.which === 'HEADER.FIELDS (FROM SUBJECT)') { - console.log('isEmailOk', isEmailOk); if (isEmailOk) { + imap.move(uid, 'exito', function(err) { + }); emailConfirm(buffer); - imap.seq.move(seqno, 'exito', function(err) { - console.log('Move correcte: ' + err); - console.log('Move error: ' + seqno); - }); } else { - emailReply(buffer); - imap.seq.move(seqno, 'error', function(err) { - console.log('Move error: ' + err); - console.log('Move error: ' + seqno); + imap.move(uid, 'error', function(err) { }); + emailReply(buffer, emailBody); } } }); }); }); - // msg.on('attributes', function(attrs) { - // console.log('ATRIBUTO', attrs.struct[0]); - // console.log('ATRIBUTO', attrs.struct[0].params); - // }); + f.once('end', function() { + imap.end(); + }); }); }); imap.connect(); - return 'pepinillos'; + return 'Leer emails de gestion horaria'; }; - async function getUser(workerEmail) { - let firstPosition = workerEmail.search('<') + 1; - let lastPosition = workerEmail.search('@') - firstPosition; - let userName = workerEmail.substr(firstPosition, lastPosition); - let user = await Self.app.models.Account.findOne({where: {name: userName}}); - return user; - } - - async function getEmailDate(subject) { - let date = subject.match(/\d+/g); - return date; - } async function emailConfirm(buffer) { - let now = new Date(); - let from = JSON.stringify(Imap.parseHeader(buffer).from); - let subject = JSON.stringify(Imap.parseHeader(buffer).subject); + // try { + const now = new Date(); + const from = JSON.stringify(Imap.parseHeader(buffer).from); + const subject = JSON.stringify(Imap.parseHeader(buffer).subject); - let timeControlDate = await getEmailDate(subject); - let week = timeControlDate[0]; - let year = timeControlDate[1]; - let user = await getUser(from); + const timeControlDate = await getEmailDate(subject); + const week = timeControlDate[0]; + const year = timeControlDate[1]; + const user = await getUser(from); let workerMail = await Self.app.models.WorkerTimeControlMail.findOne({ where: { week: week, year: year, - worker: user.id + workerFk: user.id } }); - await workerMail.updateAttributes({ - updated: now, - state: 'CONFIRMED' - }); - // MOVER A CARPETA EXITO + if (workerMail != NULL) { + await workerMail.updateAttributes({ + updated: now, + state: 'CONFIRMED' + }); + } + // } catch (err) { + // throw err; + // } } - async function emailReply(subject, workerEmail) { - console.log('bbbbb'); - // INSERT EN VN.MAIL - // UPDATE EN WORKERTIMECONTROLMAIL - // MOVER A CARPETA ERROR + async function emailReply(buffer, emailBody) { + // try { + const now = new Date(); + const from = JSON.stringify(Imap.parseHeader(buffer).from); + const subject = JSON.stringify(Imap.parseHeader(buffer).subject); + + const timeControlDate = await getEmailDate(subject); + const week = timeControlDate[0]; + const year = timeControlDate[1]; + const user = await getUser(from); + + let workerMail = await Self.app.models.WorkerTimeControlMail.findOne({ + where: { + week: week, + year: year, + workerFk: user.id + } + }); + if (workerMail != NULL) { + await workerMail.updateAttributes({ + updated: now, + state: 'REVISE' + }); + } + + await sendMail(user, subject, emailBody); + // } catch (err) { + // throw err; + // } + } + + async function getUser(workerEmail) { + const userEmail = workerEmail.match(/(?<=<)(.*?)(?=>)/); + + let [user] = await Self.rawSql(`SELECT u.id,u.name FROM account.user u + LEFT JOIN account.mailForward m on m.account = u.id + WHERE forwardTo =? OR + CONCAT(u.name,'@verdnatura.es') = ?`, + [userEmail[0], userEmail[0]]); + + return user; + } + + async function getEmailDate(subject) { + const date = subject.match(/\d+/g); + return date; + } + + async function sendMail(user, subject, emailBody) { + const sendTo = 'rrhh@verdnatura.es'; + const emailSubject = subject + ' ' + user.name; + + await Self.app.models.Mail.create({ + sender: sendTo, + subject: emailSubject, + body: emailBody + }); } }; diff --git a/back/model-config.json b/back/model-config.json index 46733696f..07900448c 100644 --- a/back/model-config.json +++ b/back/model-config.json @@ -79,6 +79,9 @@ }, "Mail": { "dataSource": "vn" + }, + "MailForward": { + "dataSource": "vn" } } diff --git a/back/models/mail-forward.json b/back/models/mail-forward.json new file mode 100644 index 000000000..40b695a7a --- /dev/null +++ b/back/models/mail-forward.json @@ -0,0 +1,26 @@ +{ + "name": "MailForward", + "base": "VnModel", + "options": { + "mysql": { + "table": "account.mailForward" + } + }, + "properties": { + "account": { + "id": true, + "type": "Number" + }, + "forwardTo": { + "type": "String" + } + }, + "acls": [ + { + "accessType": "READ", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "ALLOW" + } + ] +} diff --git a/back/models/mail.json b/back/models/mail.json index cf5c11993..3861460f3 100644 --- a/back/models/mail.json +++ b/back/models/mail.json @@ -9,8 +9,7 @@ "properties": { "id": { "id": true, - "type": "Number", - "required": true + "type": "Number" }, "sender": { "type": "String" diff --git a/db/tests/vn/workerTimeControlCheck.spec.js b/db/tests/vn/workerTimeControlCheck.spec.js index 4869e38a6..f70a0b1c3 100644 --- a/db/tests/vn/workerTimeControlCheck.spec.js +++ b/db/tests/vn/workerTimeControlCheck.spec.js @@ -1,7 +1,7 @@ const app = require('vn-loopback/server/server'); const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; -// #2257 xdescribe dbtest workerTimeControl_check() +// #2261 xdescribe dbtest workerTimeControl_check() xdescribe('worker workerTimeControl_check()', () => { it(`should throw an error if the worker can't sign on that tablet`, async() => { let stmts = []; diff --git a/modules/worker/back/models/worker.json b/modules/worker/back/models/worker.json index 6af7e8608..45eee23bf 100644 --- a/modules/worker/back/models/worker.json +++ b/modules/worker/back/models/worker.json @@ -31,6 +31,9 @@ "userFk": { "type" : "Number", "required": true + }, + "bossFk": { + "type" : "Number" } }, "relations": { From 28dc557e2fe14da7f57af59c3d70b2c069b708cb Mon Sep 17 00:00:00 2001 From: Bernat Exposito Domenech Date: Wed, 23 Sep 2020 07:35:45 +0200 Subject: [PATCH 08/11] fix checkInbox --- back/methods/imap-time-control/checkInbox.js | 64 +++++++++----------- back/models/worker-time-control-mail.json | 3 + 2 files changed, 33 insertions(+), 34 deletions(-) diff --git a/back/methods/imap-time-control/checkInbox.js b/back/methods/imap-time-control/checkInbox.js index 4f3cb06b0..a79fe4418 100644 --- a/back/methods/imap-time-control/checkInbox.js +++ b/back/methods/imap-time-control/checkInbox.js @@ -46,9 +46,7 @@ module.exports = Self => { let buffer = ''; let bufferCopy = ''; stream.on('data', function(chunk) { - // console.log('chunk', chunk); buffer = chunk.toString('utf8'); - // console.log('buffer', buffer); if (info.which === '1' && bufferCopy.length == 0) bufferCopy = buffer.replace(/\s/g, ' '); }); @@ -66,10 +64,6 @@ module.exports = Self => { }); msg.once('attributes', function(attrs) { uid = attrs.uid; - // let structure = attrs.struct[2][0]; - // console.log('attrs.struct', structure); - // console.log('attrs', structure.params); - // console.log('attrs.struct', structure.find(item => item.subtype === 'html')); }); msg.once('end', function() { if (info.which === 'HEADER.FIELDS (FROM SUBJECT)') { @@ -97,7 +91,7 @@ module.exports = Self => { }; async function emailConfirm(buffer) { - // try { + console.log('buffer', buffer); const now = new Date(); const from = JSON.stringify(Imap.parseHeader(buffer).from); const subject = JSON.stringify(Imap.parseHeader(buffer).subject); @@ -106,27 +100,28 @@ module.exports = Self => { const week = timeControlDate[0]; const year = timeControlDate[1]; const user = await getUser(from); + let workerMail; - let workerMail = await Self.app.models.WorkerTimeControlMail.findOne({ - where: { - week: week, - year: year, - workerFk: user.id - } - }); + if (user.id != NULL) { + workerMail = await Self.app.models.WorkerTimeControlMail.findOne({ + where: { + week: week, + year: year, + workerFk: user.id + } + }); + } if (workerMail != NULL) { await workerMail.updateAttributes({ updated: now, state: 'CONFIRMED' }); } - // } catch (err) { - // throw err; - // } } async function emailReply(buffer, emailBody) { - // try { + console.log('buffer', buffer); + console.log('emailBody', emailBody); const now = new Date(); const from = JSON.stringify(Imap.parseHeader(buffer).from); const subject = JSON.stringify(Imap.parseHeader(buffer).subject); @@ -135,25 +130,26 @@ module.exports = Self => { const week = timeControlDate[0]; const year = timeControlDate[1]; const user = await getUser(from); + let workerMail; - let workerMail = await Self.app.models.WorkerTimeControlMail.findOne({ - where: { - week: week, - year: year, - workerFk: user.id - } - }); - if (workerMail != NULL) { - await workerMail.updateAttributes({ - updated: now, - state: 'REVISE' + if (user.id != NULL) { + workerMail = await Self.app.models.WorkerTimeControlMail.findOne({ + where: { + week: week, + year: year, + workerFk: user.id + } }); - } - await sendMail(user, subject, emailBody); - // } catch (err) { - // throw err; - // } + if (workerMail != NULL) { + await workerMail.updateAttributes({ + updated: now, + state: 'REVISE', + emailResponse: emailBody + }); + } else + await sendMail(user, subject, emailBody); + } } async function getUser(workerEmail) { diff --git a/back/models/worker-time-control-mail.json b/back/models/worker-time-control-mail.json index 4a0fd31f1..81ca235d7 100644 --- a/back/models/worker-time-control-mail.json +++ b/back/models/worker-time-control-mail.json @@ -26,6 +26,9 @@ }, "updated": { "type": "Date" + }, + "emailResponse": { + "type": "String" } }, "acls": [ From eff0641769bb4158200cf015bb990b9fe44435e3 Mon Sep 17 00:00:00 2001 From: Bernat Exposito Domenech Date: Wed, 23 Sep 2020 08:13:36 +0200 Subject: [PATCH 09/11] delete console.log --- back/methods/imap-time-control/checkInbox.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/back/methods/imap-time-control/checkInbox.js b/back/methods/imap-time-control/checkInbox.js index a79fe4418..82e3396e3 100644 --- a/back/methods/imap-time-control/checkInbox.js +++ b/back/methods/imap-time-control/checkInbox.js @@ -91,7 +91,6 @@ module.exports = Self => { }; async function emailConfirm(buffer) { - console.log('buffer', buffer); const now = new Date(); const from = JSON.stringify(Imap.parseHeader(buffer).from); const subject = JSON.stringify(Imap.parseHeader(buffer).subject); @@ -120,8 +119,6 @@ module.exports = Self => { } async function emailReply(buffer, emailBody) { - console.log('buffer', buffer); - console.log('emailBody', emailBody); const now = new Date(); const from = JSON.stringify(Imap.parseHeader(buffer).from); const subject = JSON.stringify(Imap.parseHeader(buffer).subject); From 1f23f6c53c57622041b8e8baa4b27cfc8da10ef8 Mon Sep 17 00:00:00 2001 From: Bernat Exposito Domenech Date: Wed, 23 Sep 2020 09:11:00 +0200 Subject: [PATCH 10/11] delete import --- back/methods/imap-time-control/checkInbox.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/back/methods/imap-time-control/checkInbox.js b/back/methods/imap-time-control/checkInbox.js index 82e3396e3..8cb893c76 100644 --- a/back/methods/imap-time-control/checkInbox.js +++ b/back/methods/imap-time-control/checkInbox.js @@ -1,5 +1,5 @@ const Imap = require('imap'); -const {NULL} = require('node-sass'); + module.exports = Self => { Self.remoteMethod('checkInbox', { description: 'Check an email inbox and process it', From 3f4e5a6c0cf821fda0f4d1c9a8477f255612d558 Mon Sep 17 00:00:00 2001 From: Bernat Exposito Domenech Date: Wed, 23 Sep 2020 09:31:21 +0200 Subject: [PATCH 11/11] fix checkinbox --- back/methods/imap-time-control/checkInbox.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/back/methods/imap-time-control/checkInbox.js b/back/methods/imap-time-control/checkInbox.js index 8cb893c76..6a6b697a7 100644 --- a/back/methods/imap-time-control/checkInbox.js +++ b/back/methods/imap-time-control/checkInbox.js @@ -101,7 +101,7 @@ module.exports = Self => { const user = await getUser(from); let workerMail; - if (user.id != NULL) { + if (user.id != null) { workerMail = await Self.app.models.WorkerTimeControlMail.findOne({ where: { week: week, @@ -110,7 +110,7 @@ module.exports = Self => { } }); } - if (workerMail != NULL) { + if (workerMail != null) { await workerMail.updateAttributes({ updated: now, state: 'CONFIRMED' @@ -129,7 +129,7 @@ module.exports = Self => { const user = await getUser(from); let workerMail; - if (user.id != NULL) { + if (user.id != null) { workerMail = await Self.app.models.WorkerTimeControlMail.findOne({ where: { week: week, @@ -138,7 +138,7 @@ module.exports = Self => { } }); - if (workerMail != NULL) { + if (workerMail != null) { await workerMail.updateAttributes({ updated: now, state: 'REVISE',