rulesHelper.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. var nodemailer = require('nodemailer');
  2. RulesHelper = {
  3. executeRules(activity) {
  4. const matchingRules = this.findMatchingRules(activity);
  5. for (let i = 0; i < matchingRules.length; i++) {
  6. const action = matchingRules[i].getAction();
  7. if (action !== undefined) {
  8. this.performAction(activity, action);
  9. }
  10. }
  11. },
  12. findMatchingRules(activity) {
  13. const activityType = activity.activityType;
  14. if (TriggersDef[activityType] === undefined) {
  15. return [];
  16. }
  17. const matchingFields = TriggersDef[activityType].matchingFields;
  18. const matchingMap = this.buildMatchingFieldsMap(activity, matchingFields);
  19. const matchingTriggers = Triggers.find(matchingMap);
  20. const matchingRules = [];
  21. matchingTriggers.forEach(function(trigger) {
  22. const rule = trigger.getRule();
  23. // Check that for some unknown reason there are some leftover triggers
  24. // not connected to any rules
  25. if (rule !== undefined) {
  26. matchingRules.push(trigger.getRule());
  27. }
  28. });
  29. return matchingRules;
  30. },
  31. buildMatchingFieldsMap(activity, matchingFields) {
  32. const matchingMap = { activityType: activity.activityType };
  33. matchingFields.forEach(field => {
  34. // Creating a matching map with the actual field of the activity
  35. // and with the wildcard (for example: trigger when a card is added
  36. // in any [*] board
  37. let value = activity[field];
  38. if (field === 'oldListName') {
  39. const oldList = Lists.findOne({ _id: activity.oldListId });
  40. if (oldList) {
  41. value = oldList.title;
  42. }
  43. } else if (field === 'oldSwimlaneName') {
  44. const oldSwimlane = Swimlanes.findOne({ _id: activity.oldSwimlaneId });
  45. if (oldSwimlane) {
  46. value = oldSwimlane.title;
  47. }
  48. }
  49. let matchesList = [value, '*'];
  50. if (field === 'cardTitle') {
  51. matchesList = value.split(/\W/).concat(matchesList);
  52. }
  53. matchingMap[field] = {
  54. $in: matchesList,
  55. };
  56. });
  57. return matchingMap;
  58. },
  59. performAction(activity, action) {
  60. const card = Cards.findOne({ _id: activity.cardId });
  61. const boardId = activity.boardId;
  62. if (
  63. action.actionType === 'moveCardToTop' ||
  64. action.actionType === 'moveCardToBottom'
  65. ) {
  66. let list;
  67. let listId;
  68. if (action.listName === '*') {
  69. list = card.list();
  70. if (boardId !== action.boardId) {
  71. list = Lists.findOne({ title: list.title, boardId: action.boardId });
  72. }
  73. } else {
  74. list = Lists.findOne({
  75. title: action.listName,
  76. boardId: action.boardId,
  77. });
  78. }
  79. if (list === undefined) {
  80. listId = '';
  81. } else {
  82. listId = list._id;
  83. }
  84. let swimlane;
  85. let swimlaneId;
  86. if (action.swimlaneName === '*') {
  87. swimlane = Swimlanes.findOne(card.swimlaneId);
  88. if (boardId !== action.boardId) {
  89. swimlane = Swimlanes.findOne({
  90. title: swimlane.title,
  91. boardId: action.boardId,
  92. });
  93. }
  94. } else {
  95. swimlane = Swimlanes.findOne({
  96. title: action.swimlaneName,
  97. boardId: action.boardId,
  98. });
  99. }
  100. if (swimlane === undefined) {
  101. swimlaneId = Swimlanes.findOne({
  102. title: 'Default',
  103. boardId: action.boardId,
  104. })._id;
  105. } else {
  106. swimlaneId = swimlane._id;
  107. }
  108. if (action.actionType === 'moveCardToTop') {
  109. const minOrder = _.min(
  110. list.cardsUnfiltered(swimlaneId).map(c => c.sort),
  111. );
  112. card.move(action.boardId, swimlaneId, listId, minOrder - 1);
  113. } else {
  114. const maxOrder = _.max(
  115. list.cardsUnfiltered(swimlaneId).map(c => c.sort),
  116. );
  117. card.move(action.boardId, swimlaneId, listId, maxOrder + 1);
  118. }
  119. }
  120. if (action.actionType === 'sendEmail') {
  121. const to = action.emailTo;
  122. const text = action.emailMsg || '';
  123. const subject = action.emailSubject || '';
  124. try {
  125. if (process.env.MAIL_SERVICE !== '') {
  126. let transporter = nodemailer.createTransport({
  127. service: process.env.MAIL_SERVICE,
  128. auth: {
  129. user: process.env.MAIL_SERVICE_USER,
  130. pass: process.env.MAIL_SERVICE_PASSWORD
  131. },
  132. })
  133. let info = transporter.sendMail({
  134. to,
  135. from: Accounts.emailTemplates.from,
  136. subject,
  137. text,
  138. })
  139. } else {
  140. Email.send({
  141. to,
  142. from: Accounts.emailTemplates.from,
  143. subject,
  144. text,
  145. });
  146. }
  147. } catch (e) {
  148. // eslint-disable-next-line no-console
  149. console.error(e);
  150. return;
  151. }
  152. }
  153. if (action.actionType === 'setDate') {
  154. try {
  155. const currentDateTime = new Date();
  156. switch (action.dateField) {
  157. case 'startAt': {
  158. const resStart = card.getStart();
  159. if (typeof resStart === 'undefined') {
  160. card.setStart(currentDateTime);
  161. }
  162. break;
  163. }
  164. case 'endAt': {
  165. const resEnd = card.getEnd();
  166. if (typeof resEnd === 'undefined') {
  167. card.setEnd(currentDateTime);
  168. }
  169. break;
  170. }
  171. case 'dueAt': {
  172. const resDue = card.getDue();
  173. if (typeof resDue === 'undefined') {
  174. card.setDue(currentDateTime);
  175. }
  176. break;
  177. }
  178. case 'receivedAt': {
  179. const resReceived = card.getReceived();
  180. if (typeof resReceived === 'undefined') {
  181. card.setReceived(currentDateTime);
  182. }
  183. break;
  184. }
  185. }
  186. } catch (e) {
  187. // eslint-disable-next-line no-console
  188. console.error(e);
  189. return;
  190. }
  191. }
  192. if (action.actionType === 'updateDate') {
  193. const currentDateTimeUpdate = new Date();
  194. switch (action.dateField) {
  195. case 'startAt': {
  196. card.setStart(currentDateTimeUpdate);
  197. break;
  198. }
  199. case 'endAt': {
  200. card.setEnd(currentDateTimeUpdate);
  201. break;
  202. }
  203. case 'dueAt': {
  204. card.setDue(currentDateTimeUpdate);
  205. break;
  206. }
  207. case 'receivedAt': {
  208. card.setReceived(currentDateTimeUpdate);
  209. break;
  210. }
  211. }
  212. }
  213. if (action.actionType === 'removeDate') {
  214. switch (action.dateField) {
  215. case 'startAt': {
  216. card.unsetStart();
  217. break;
  218. }
  219. case 'endAt': {
  220. card.unsetEnd();
  221. break;
  222. }
  223. case 'dueAt': {
  224. card.unsetDue();
  225. break;
  226. }
  227. case 'receivedAt': {
  228. card.unsetReceived();
  229. break;
  230. }
  231. }
  232. }
  233. if (action.actionType === 'archive') {
  234. card.archive();
  235. }
  236. if (action.actionType === 'unarchive') {
  237. card.restore();
  238. }
  239. if (action.actionType === 'setColor') {
  240. card.setColor(action.selectedColor);
  241. }
  242. if (action.actionType === 'addLabel') {
  243. card.addLabel(action.labelId);
  244. }
  245. if (action.actionType === 'removeLabel') {
  246. card.removeLabel(action.labelId);
  247. }
  248. if (action.actionType === 'addMember') {
  249. const memberId = Users.findOne({ username: action.username })._id;
  250. card.assignMember(memberId);
  251. }
  252. if (action.actionType === 'removeMember') {
  253. if (action.username === '*') {
  254. const members = card.members;
  255. for (let i = 0; i < members.length; i++) {
  256. card.unassignMember(members[i]);
  257. }
  258. } else {
  259. const memberId = Users.findOne({ username: action.username })._id;
  260. card.unassignMember(memberId);
  261. }
  262. }
  263. if (action.actionType === 'checkAll') {
  264. const checkList = Checklists.findOne({
  265. title: action.checklistName,
  266. cardId: card._id,
  267. });
  268. checkList.checkAllItems();
  269. }
  270. if (action.actionType === 'uncheckAll') {
  271. const checkList = Checklists.findOne({
  272. title: action.checklistName,
  273. cardId: card._id,
  274. });
  275. checkList.uncheckAllItems();
  276. }
  277. if (action.actionType === 'checkItem') {
  278. const checkList = Checklists.findOne({
  279. title: action.checklistName,
  280. cardId: card._id,
  281. });
  282. const checkItem = ChecklistItems.findOne({
  283. title: action.checkItemName,
  284. checkListId: checkList._id,
  285. });
  286. checkItem.check();
  287. }
  288. if (action.actionType === 'uncheckItem') {
  289. const checkList = Checklists.findOne({
  290. title: action.checklistName,
  291. cardId: card._id,
  292. });
  293. const checkItem = ChecklistItems.findOne({
  294. title: action.checkItemName,
  295. checkListId: checkList._id,
  296. });
  297. checkItem.uncheck();
  298. }
  299. if (action.actionType === 'addChecklist') {
  300. Checklists.insert({
  301. title: action.checklistName,
  302. cardId: card._id,
  303. sort: 0,
  304. });
  305. }
  306. if (action.actionType === 'removeChecklist') {
  307. Checklists.remove({
  308. title: action.checklistName,
  309. cardId: card._id,
  310. sort: 0,
  311. });
  312. }
  313. if (action.actionType === 'addSwimlane') {
  314. Swimlanes.insert({
  315. title: action.swimlaneName,
  316. boardId,
  317. sort: 0,
  318. });
  319. }
  320. if (action.actionType === 'addChecklistWithItems') {
  321. const checkListId = Checklists.insert({
  322. title: action.checklistName,
  323. cardId: card._id,
  324. sort: 0,
  325. });
  326. const itemsArray = action.checklistItems.split(',');
  327. const checkList = Checklists.findOne({ _id: checkListId });
  328. for (let i = 0; i < itemsArray.length; i++) {
  329. ChecklistItems.insert({
  330. title: itemsArray[i],
  331. checklistId: checkListId,
  332. cardId: card._id,
  333. sort: checkList.itemCount(),
  334. });
  335. }
  336. }
  337. if (action.actionType === 'createCard') {
  338. const list = Lists.findOne({ title: action.listName, boardId });
  339. let listId = '';
  340. let swimlaneId = '';
  341. const swimlane = Swimlanes.findOne({
  342. title: action.swimlaneName,
  343. boardId,
  344. });
  345. if (list === undefined) {
  346. listId = '';
  347. } else {
  348. listId = list._id;
  349. }
  350. if (swimlane === undefined) {
  351. swimlaneId = Swimlanes.findOne({ title: 'Default', boardId })._id;
  352. } else {
  353. swimlaneId = swimlane._id;
  354. }
  355. Cards.insert({
  356. title: action.cardName,
  357. listId,
  358. swimlaneId,
  359. sort: 0,
  360. boardId,
  361. });
  362. }
  363. },
  364. };