| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723 | 
							- import moment from 'moment';
 
- import Users from '../../models/users';
 
- import Boards from '../../models/boards';
 
- import Lists from '../../models/lists';
 
- import Swimlanes from '../../models/swimlanes';
 
- import Cards from '../../models/cards';
 
- import CardComments from '../../models/cardComments';
 
- import Attachments from '../../models/attachments';
 
- import Checklists from '../../models/checklists';
 
- import ChecklistItems from '../../models/checklistItems';
 
- import SessionData from '../../models/usersessiondata';
 
- import CustomFields from '../../models/customFields';
 
- import {
 
-   DEFAULT_LIMIT,
 
-   OPERATOR_ASSIGNEE,
 
-   OPERATOR_BOARD,
 
-   OPERATOR_COMMENT,
 
-   OPERATOR_CREATED_AT,
 
-   OPERATOR_CREATOR,
 
-   OPERATOR_DUE,
 
-   OPERATOR_HAS,
 
-   OPERATOR_LABEL,
 
-   OPERATOR_LIMIT,
 
-   OPERATOR_LIST,
 
-   OPERATOR_MEMBER,
 
-   OPERATOR_MODIFIED_AT,
 
-   OPERATOR_SORT,
 
-   OPERATOR_STATUS,
 
-   OPERATOR_SWIMLANE,
 
-   OPERATOR_USER,
 
-   ORDER_ASCENDING,
 
-   PREDICATE_ALL,
 
-   PREDICATE_ARCHIVED,
 
-   PREDICATE_ASSIGNEES,
 
-   PREDICATE_ATTACHMENT,
 
-   PREDICATE_CHECKLIST,
 
-   PREDICATE_CREATED_AT,
 
-   PREDICATE_DESCRIPTION,
 
-   PREDICATE_DUE_AT,
 
-   PREDICATE_END_AT,
 
-   PREDICATE_ENDED,
 
-   PREDICATE_MEMBERS,
 
-   PREDICATE_MODIFIED_AT,
 
-   PREDICATE_PRIVATE,
 
-   PREDICATE_PUBLIC,
 
-   PREDICATE_START_AT,
 
-   PREDICATE_SYSTEM,
 
- } from '/config/search-const';
 
- import { QueryErrors, QueryParams, Query } from '/config/query-classes';
 
- const escapeForRegex = require('escape-string-regexp');
 
- Meteor.publish('card', cardId => {
 
-   check(cardId, String);
 
-   return Cards.find({ _id: cardId });
 
- });
 
- Meteor.publish('myCards', function(sessionId) {
 
-   check(sessionId, String);
 
-   const queryParams = new QueryParams();
 
-   queryParams.addPredicate(OPERATOR_USER, Meteor.user().username);
 
-   queryParams.setPredicate(OPERATOR_LIMIT, 200);
 
-   const query = buildQuery(queryParams);
 
-   query.projection.sort = {
 
-     boardId: 1,
 
-     swimlaneId: 1,
 
-     listId: 1,
 
-   };
 
-   return findCards(sessionId, query);
 
- });
 
- // Meteor.publish('dueCards', function(sessionId, allUsers = false) {
 
- //   check(sessionId, String);
 
- //   check(allUsers, Boolean);
 
- //
 
- //   // eslint-disable-next-line no-console
 
- //   // console.log('all users:', allUsers);
 
- //
 
- //   const queryParams = {
 
- //     has: [{ field: 'dueAt', exists: true }],
 
- //     limit: 25,
 
- //     skip: 0,
 
- //     sort: { name: 'dueAt', order: 'des' },
 
- //   };
 
- //
 
- //   if (!allUsers) {
 
- //     queryParams.users = [Meteor.user().username];
 
- //   }
 
- //
 
- //   return buildQuery(sessionId, queryParams);
 
- // });
 
- Meteor.publish('globalSearch', function(sessionId, params, text) {
 
-   check(sessionId, String);
 
-   check(params, Object);
 
-   check(text, String);
 
-   // eslint-disable-next-line no-console
 
-   // console.log('queryParams:', params);
 
-   return findCards(sessionId, buildQuery(new QueryParams(params, text)));
 
- });
 
- function buildSelector(queryParams) {
 
-   const userId = Meteor.userId();
 
-   const errors = new QueryErrors();
 
-   let selector = {};
 
-   // eslint-disable-next-line no-console
 
-   console.log('queryParams:', queryParams);
 
-   if (queryParams.selector) {
 
-     selector = queryParams.selector;
 
-   } else {
 
-     const boardsSelector = {};
 
-     let archived = false;
 
-     let endAt = null;
 
-     if (queryParams.hasOperator(OPERATOR_STATUS)) {
 
-       queryParams.getPredicates(OPERATOR_STATUS).forEach(status => {
 
-         if (status === PREDICATE_ARCHIVED) {
 
-           archived = true;
 
-         } else if (status === PREDICATE_ALL) {
 
-           archived = null;
 
-         } else if (status === PREDICATE_ENDED) {
 
-           endAt = { $nin: [null, ''] };
 
-         } else if ([PREDICATE_PRIVATE, PREDICATE_PUBLIC].includes(status)) {
 
-           boardsSelector.permission = status;
 
-         }
 
-       });
 
-     }
 
-     selector = {
 
-       type: 'cardType-card',
 
-       // boardId: { $in: Boards.userBoardIds(userId) },
 
-       $and: [],
 
-     };
 
-     if (archived !== null) {
 
-       if (archived) {
 
-         selector.boardId = {
 
-           $in: Boards.userBoardIds(userId, null, boardsSelector),
 
-         };
 
-         selector.$and.push({
 
-           $or: [
 
-             {
 
-               boardId: {
 
-                 $in: Boards.userBoardIds(userId, archived, boardsSelector),
 
-               },
 
-             },
 
-             { swimlaneId: { $in: Swimlanes.archivedSwimlaneIds() } },
 
-             { listId: { $in: Lists.archivedListIds() } },
 
-             { archived: true },
 
-           ],
 
-         });
 
-       } else {
 
-         selector.boardId = {
 
-           $in: Boards.userBoardIds(userId, false, boardsSelector),
 
-         };
 
-         selector.swimlaneId = { $nin: Swimlanes.archivedSwimlaneIds() };
 
-         selector.listId = { $nin: Lists.archivedListIds() };
 
-         selector.archived = false;
 
-       }
 
-     } else {
 
-       selector.boardId = {
 
-         $in: Boards.userBoardIds(userId, null, boardsSelector),
 
-       };
 
-     }
 
-     if (endAt !== null) {
 
-       selector.endAt = endAt;
 
-     }
 
-     if (queryParams.hasOperator(OPERATOR_BOARD)) {
 
-       const queryBoards = [];
 
-       queryParams.getPredicates(OPERATOR_BOARD).forEach(query => {
 
-         const boards = Boards.userSearch(userId, {
 
-           title: new RegExp(escapeForRegex(query), 'i'),
 
-         });
 
-         if (boards.count()) {
 
-           boards.forEach(board => {
 
-             queryBoards.push(board._id);
 
-           });
 
-         } else {
 
-           errors.addNotFound(OPERATOR_BOARD, query);
 
-         }
 
-       });
 
-       selector.boardId.$in = queryBoards;
 
-     }
 
-     if (queryParams.hasOperator(OPERATOR_SWIMLANE)) {
 
-       const querySwimlanes = [];
 
-       queryParams.getPredicates(OPERATOR_SWIMLANE).forEach(query => {
 
-         const swimlanes = Swimlanes.find({
 
-           title: new RegExp(escapeForRegex(query), 'i'),
 
-         });
 
-         if (swimlanes.count()) {
 
-           swimlanes.forEach(swim => {
 
-             querySwimlanes.push(swim._id);
 
-           });
 
-         } else {
 
-           errors.addNotFound(OPERATOR_SWIMLANE, query);
 
-         }
 
-       });
 
-       // eslint-disable-next-line no-prototype-builtins
 
-       if (!selector.swimlaneId.hasOwnProperty('swimlaneId')) {
 
-         selector.swimlaneId = { $in: [] };
 
-       }
 
-       selector.swimlaneId.$in = querySwimlanes;
 
-     }
 
-     if (queryParams.hasOperator(OPERATOR_LIST)) {
 
-       const queryLists = [];
 
-       queryParams.getPredicates(OPERATOR_LIST).forEach(query => {
 
-         const lists = Lists.find({
 
-           title: new RegExp(escapeForRegex(query), 'i'),
 
-         });
 
-         if (lists.count()) {
 
-           lists.forEach(list => {
 
-             queryLists.push(list._id);
 
-           });
 
-         } else {
 
-           errors.addNotFound(OPERATOR_LIST, query);
 
-         }
 
-       });
 
-       // eslint-disable-next-line no-prototype-builtins
 
-       if (!selector.hasOwnProperty('listId')) {
 
-         selector.listId = { $in: [] };
 
-       }
 
-       selector.listId.$in = queryLists;
 
-     }
 
-     if (queryParams.hasOperator(OPERATOR_COMMENT)) {
 
-       const cardIds = CardComments.textSearch(
 
-         userId,
 
-         queryParams.getPredicates(OPERATOR_COMMENT),
 
-         com => {
 
-           return com.cardId;
 
-         },
 
-       );
 
-       if (cardIds.length) {
 
-         selector._id = { $in: cardIds };
 
-       } else {
 
-         queryParams.getPredicates(OPERATOR_COMMENT).forEach(comment => {
 
-           errors.addNotFound(OPERATOR_COMMENT, comment);
 
-         });
 
-       }
 
-     }
 
-     [OPERATOR_DUE, OPERATOR_CREATED_AT, OPERATOR_MODIFIED_AT].forEach(field => {
 
-       if (queryParams.hasOperator(field)) {
 
-         selector[field] = {};
 
-         const predicate = queryParams.getPredicate(field);
 
-         selector[field][predicate.operator] = new Date(predicate.value);
 
-       }
 
-     });
 
-     const queryUsers = {};
 
-     queryUsers[OPERATOR_ASSIGNEE] = [];
 
-     queryUsers[OPERATOR_MEMBER] = [];
 
-     queryUsers[OPERATOR_CREATOR] = [];
 
-     if (queryParams.hasOperator(OPERATOR_USER)) {
 
-       const users = [];
 
-       queryParams.getPredicates(OPERATOR_USER).forEach(username => {
 
-         const user = Users.findOne({ username });
 
-         if (user) {
 
-           users.push(user._id);
 
-         } else {
 
-           errors.addNotFound(OPERATOR_USER, username);
 
-         }
 
-       });
 
-       if (users.length) {
 
-         selector.$and.push({
 
-           $or: [{ members: { $in: users } }, { assignees: { $in: users } }],
 
-         });
 
-       }
 
-     }
 
-     [OPERATOR_MEMBER, OPERATOR_ASSIGNEE, OPERATOR_CREATOR].forEach(key => {
 
-       if (queryParams.hasOperator(key)) {
 
-         const users = [];
 
-         queryParams.getPredicates(key).forEach(username => {
 
-           const user = Users.findOne({ username });
 
-           if (user) {
 
-             users.push(user._id);
 
-           } else {
 
-             errors.addNotFound(key, username);
 
-           }
 
-         });
 
-         if (users.length) {
 
-           selector[key] = { $in: users };
 
-         }
 
-       }
 
-     });
 
-     if (queryParams.hasOperator(OPERATOR_LABEL)) {
 
-       const queryLabels = [];
 
-       queryParams.getPredicates(OPERATOR_LABEL).forEach(label => {
 
-         let boards = Boards.userBoards(userId, null, {
 
-           labels: { $elemMatch: { color: label.toLowerCase() } },
 
-         });
 
-         if (boards.count()) {
 
-           boards.forEach(board => {
 
-             // eslint-disable-next-line no-console
 
-             // console.log('board:', board);
 
-             // eslint-disable-next-line no-console
 
-             // console.log('board.labels:', board.labels);
 
-             board.labels
 
-               .filter(boardLabel => {
 
-                 return boardLabel.color === label.toLowerCase();
 
-               })
 
-               .forEach(boardLabel => {
 
-                 queryLabels.push(boardLabel._id);
 
-               });
 
-           });
 
-         } else {
 
-           // eslint-disable-next-line no-console
 
-           // console.log('label:', label);
 
-           const reLabel = new RegExp(escapeForRegex(label), 'i');
 
-           // eslint-disable-next-line no-console
 
-           // console.log('reLabel:', reLabel);
 
-           boards = Boards.userBoards(userId, null, {
 
-             labels: { $elemMatch: { name: reLabel } },
 
-           });
 
-           if (boards.count()) {
 
-             boards.forEach(board => {
 
-               board.labels
 
-                 .filter(boardLabel => {
 
-                   if (!boardLabel.name) {
 
-                     return false;
 
-                   }
 
-                   return boardLabel.name.match(reLabel);
 
-                 })
 
-                 .forEach(boardLabel => {
 
-                   queryLabels.push(boardLabel._id);
 
-                 });
 
-             });
 
-           } else {
 
-             errors.addNotFound(OPERATOR_LABEL, label);
 
-           }
 
-         }
 
-       });
 
-       if (queryLabels.length) {
 
-         // eslint-disable-next-line no-console
 
-         // console.log('queryLabels:', queryLabels);
 
-         selector.labelIds = { $in: _.uniq(queryLabels) };
 
-       }
 
-     }
 
-     if (queryParams.hasOperator(OPERATOR_HAS)) {
 
-       queryParams.getPredicates(OPERATOR_HAS).forEach(has => {
 
-         switch (has.field) {
 
-           case PREDICATE_ATTACHMENT:
 
-             selector.$and.push({
 
-               _id: {
 
-                 $in: Attachments.find({}, { fields: { cardId: 1 } }).map(
 
-                   a => a.cardId,
 
-                 ),
 
-               },
 
-             });
 
-             break;
 
-           case PREDICATE_CHECKLIST:
 
-             selector.$and.push({
 
-               _id: {
 
-                 $in: Checklists.find({}, { fields: { cardId: 1 } }).map(
 
-                   a => a.cardId,
 
-                 ),
 
-               },
 
-             });
 
-             break;
 
-           case PREDICATE_DESCRIPTION:
 
-           case PREDICATE_START_AT:
 
-           case PREDICATE_DUE_AT:
 
-           case PREDICATE_END_AT:
 
-             if (has.exists) {
 
-               selector[has.field] = { $exists: true, $nin: [null, ''] };
 
-             } else {
 
-               selector[has.field] = { $in: [null, ''] };
 
-             }
 
-             break;
 
-           case PREDICATE_ASSIGNEES:
 
-           case PREDICATE_MEMBERS:
 
-             if (has.exists) {
 
-               selector[has.field] = { $exists: true, $nin: [null, []] };
 
-             } else {
 
-               selector[has.field] = { $in: [null, []] };
 
-             }
 
-             break;
 
-         }
 
-       });
 
-     }
 
-     if (queryParams.text) {
 
-       const regex = new RegExp(escapeForRegex(queryParams.text), 'i');
 
-       const items = ChecklistItems.find(
 
-         { title: regex },
 
-         { fields: { cardId: 1 } },
 
-       );
 
-       const checklists = Checklists.find(
 
-         {
 
-           $or: [
 
-             { title: regex },
 
-             { _id: { $in: items.map(item => item.checklistId) } },
 
-           ],
 
-         },
 
-         { fields: { cardId: 1 } },
 
-       );
 
-       const attachments = Attachments.find({ 'original.name': regex });
 
-       const comments = CardComments.find(
 
-         { text: regex },
 
-         { fields: { cardId: 1 } },
 
-       );
 
-       selector.$and.push({
 
-         $or: [
 
-           { title: regex },
 
-           { description: regex },
 
-           { customFields: { $elemMatch: { value: regex } } },
 
-           // {
 
-           //   _id: {
 
-           //     $in: CardComments.textSearch(userId, [queryParams.text]).map(
 
-           //       com => com.cardId,
 
-           //     ),
 
-           //   },
 
-           // },
 
-           { _id: { $in: checklists.map(list => list.cardId) } },
 
-           { _id: { $in: attachments.map(attach => attach.cardId) } },
 
-           { _id: { $in: comments.map(com => com.cardId) } },
 
-         ],
 
-       });
 
-     }
 
-     if (selector.$and.length === 0) {
 
-       delete selector.$and;
 
-     }
 
-   }
 
-   // eslint-disable-next-line no-console
 
-   console.log('selector:', selector);
 
-   // eslint-disable-next-line no-console
 
-   console.log('selector.$and:', selector.$and);
 
-   const query = new Query();
 
-   query.selector = selector;
 
-   query.setQueryParams(queryParams);
 
-   query._errors = errors;
 
-   return query;
 
- }
 
- function buildProjection(query) {
 
-   // eslint-disable-next-line no-console
 
-   // console.log('query:', query);
 
-   let skip = 0;
 
-   if (query.getQueryParams().skip) {
 
-     skip = query.getQueryParams().skip;
 
-   }
 
-   let limit = DEFAULT_LIMIT;
 
-   const configLimit = parseInt(process.env.RESULTS_PER_PAGE, 10);
 
-   if (!isNaN(configLimit) && configLimit > 0) {
 
-     limit = configLimit;
 
-   }
 
-   if (query.getQueryParams().hasOperator(OPERATOR_LIMIT)) {
 
-     limit = query.getQueryParams().getPredicate(OPERATOR_LIMIT);
 
-   }
 
-   const projection = {
 
-     fields: {
 
-       _id: 1,
 
-       archived: 1,
 
-       boardId: 1,
 
-       swimlaneId: 1,
 
-       listId: 1,
 
-       title: 1,
 
-       type: 1,
 
-       sort: 1,
 
-       members: 1,
 
-       assignees: 1,
 
-       colors: 1,
 
-       dueAt: 1,
 
-       createdAt: 1,
 
-       modifiedAt: 1,
 
-       labelIds: 1,
 
-       customFields: 1,
 
-       userId: 1,
 
-     },
 
-     sort: {
 
-       boardId: 1,
 
-       swimlaneId: 1,
 
-       listId: 1,
 
-       sort: 1,
 
-     },
 
-     skip,
 
-     limit,
 
-   };
 
-   if (query.getQueryParams().hasOperator(OPERATOR_SORT)) {
 
-     const order =
 
-       query.getQueryParams().getPredicate(OPERATOR_SORT).order ===
 
-       ORDER_ASCENDING
 
-         ? 1
 
-         : -1;
 
-     switch (query.getQueryParams().getPredicate(OPERATOR_SORT).name) {
 
-       case PREDICATE_DUE_AT:
 
-         projection.sort = {
 
-           dueAt: order,
 
-           boardId: 1,
 
-           swimlaneId: 1,
 
-           listId: 1,
 
-           sort: 1,
 
-         };
 
-         break;
 
-       case PREDICATE_MODIFIED_AT:
 
-         projection.sort = {
 
-           modifiedAt: order,
 
-           boardId: 1,
 
-           swimlaneId: 1,
 
-           listId: 1,
 
-           sort: 1,
 
-         };
 
-         break;
 
-       case PREDICATE_CREATED_AT:
 
-         projection.sort = {
 
-           createdAt: order,
 
-           boardId: 1,
 
-           swimlaneId: 1,
 
-           listId: 1,
 
-           sort: 1,
 
-         };
 
-         break;
 
-       case PREDICATE_SYSTEM:
 
-         projection.sort = {
 
-           boardId: order,
 
-           swimlaneId: order,
 
-           listId: order,
 
-           modifiedAt: order,
 
-           sort: order,
 
-         };
 
-         break;
 
-     }
 
-   }
 
-   // eslint-disable-next-line no-console
 
-   // console.log('projection:', projection);
 
-   query.projection = projection;
 
-   return query;
 
- }
 
- function buildQuery(queryParams) {
 
-   const query = buildSelector(queryParams);
 
-   return buildProjection(query);
 
- }
 
- Meteor.publish('brokenCards', function(sessionId) {
 
-   check(sessionId, String);
 
-   const params = new QueryParams();
 
-   params.addPredicate(OPERATOR_STATUS, PREDICATE_ALL);
 
-   const query = buildQuery(params);
 
-   query.selector.$or = [
 
-     { boardId: { $in: [null, ''] } },
 
-     { swimlaneId: { $in: [null, ''] } },
 
-     { listId: { $in: [null, ''] } },
 
-   ];
 
-   // console.log('brokenCards selector:', query.selector);
 
-   return findCards(sessionId, query);
 
- });
 
- Meteor.publish('nextPage', function(sessionId) {
 
-   check(sessionId, String);
 
-   const session = SessionData.findOne({ sessionId });
 
-   const projection = session.getProjection();
 
-   projection.skip = session.lastHit;
 
-   return findCards(sessionId, new Query(session.getSelector(), projection));
 
- });
 
- Meteor.publish('previousPage', function(sessionId) {
 
-   check(sessionId, String);
 
-   const session = SessionData.findOne({ sessionId });
 
-   const projection = session.getProjection();
 
-   projection.skip = session.lastHit - session.resultsCount - projection.limit;
 
-   return findCards(sessionId, new Query(session.getSelector(), projection));
 
- });
 
- function findCards(sessionId, query) {
 
-   const userId = Meteor.userId();
 
-   // eslint-disable-next-line no-console
 
-   // console.log('selector:', query.selector);
 
-   // console.log('selector.$and:', query.selector.$and);
 
-   // eslint-disable-next-line no-console
 
-   // console.log('projection:', projection);
 
-   const cards = Cards.find(query.selector, query.projection);
 
-   // eslint-disable-next-line no-console
 
-   // console.log('count:', cards.count());
 
-   const update = {
 
-     $set: {
 
-       totalHits: 0,
 
-       lastHit: 0,
 
-       resultsCount: 0,
 
-       cards: [],
 
-       selector: SessionData.pickle(query.selector),
 
-       projection: SessionData.pickle(query.projection),
 
-       errors: query.errors(),
 
-     },
 
-   };
 
-   if (cards) {
 
-     update.$set.totalHits = cards.count();
 
-     update.$set.lastHit =
 
-       query.projection.skip + query.projection.limit < cards.count()
 
-         ? query.projection.skip + query.projection.limit
 
-         : cards.count();
 
-     update.$set.cards = cards.map(card => {
 
-       return card._id;
 
-     });
 
-     update.$set.resultsCount = update.$set.cards.length;
 
-   }
 
-   // eslint-disable-next-line no-console
 
-   // console.log('sessionId:', sessionId);
 
-   // eslint-disable-next-line no-console
 
-   // console.log('userId:', userId);
 
-   // eslint-disable-next-line no-console
 
-   // console.log('update:', update);
 
-   SessionData.upsert({ userId, sessionId }, update);
 
-   // remove old session data
 
-   SessionData.remove({
 
-     userId,
 
-     modifiedAt: {
 
-       $lt: new Date(
 
-         moment()
 
-           .subtract(1, 'day')
 
-           .format(),
 
-       ),
 
-     },
 
-   });
 
-   if (cards) {
 
-     const boards = [];
 
-     const swimlanes = [];
 
-     const lists = [];
 
-     const customFieldIds = [];
 
-     const users = [this.userId];
 
-     cards.forEach(card => {
 
-       if (card.boardId) boards.push(card.boardId);
 
-       if (card.swimlaneId) swimlanes.push(card.swimlaneId);
 
-       if (card.listId) lists.push(card.listId);
 
-       if (card.userId) {
 
-         users.push(card.userId);
 
-       }
 
-       if (card.members) {
 
-         card.members.forEach(userId => {
 
-           users.push(userId);
 
-         });
 
-       }
 
-       if (card.assignees) {
 
-         card.assignees.forEach(userId => {
 
-           users.push(userId);
 
-         });
 
-       }
 
-       if (card.customFields) {
 
-         card.customFields.forEach(field => {
 
-           customFieldIds.push(field._id);
 
-         });
 
-       }
 
-     });
 
-     const fields = {
 
-       _id: 1,
 
-       title: 1,
 
-       archived: 1,
 
-       sort: 1,
 
-       type: 1,
 
-     };
 
-     return [
 
-       cards,
 
-       Boards.find(
 
-         { _id: { $in: boards } },
 
-         { fields: { ...fields, labels: 1, color: 1 } },
 
-       ),
 
-       Swimlanes.find(
 
-         { _id: { $in: swimlanes } },
 
-         { fields: { ...fields, color: 1 } },
 
-       ),
 
-       Lists.find({ _id: { $in: lists } }, { fields }),
 
-       CustomFields.find({ _id: { $in: customFieldIds } }),
 
-       Users.find({ _id: { $in: users } }, { fields: Users.safeFields }),
 
-       Checklists.find({ cardId: { $in: cards.map(c => c._id) } }),
 
-       Attachments.find({ cardId: { $in: cards.map(c => c._id) } }),
 
-       CardComments.find({ cardId: { $in: cards.map(c => c._id) } }),
 
-       SessionData.find({ userId, sessionId }),
 
-     ];
 
-   }
 
-   return [SessionData.find({ userId, sessionId })];
 
- }
 
 
  |