getAll: function(req, res) { var pUserId = req.query.userId; var pTaskId = req.query.taskId; var query = new mongoose.Query; if (pUserId && pUserId !== "" ) { query.where('userId', pUserId); } if (pTaskId && pTaskId !== "" ) { query.where('taskId', pTaskId); } Note.find(query, function (err, entries) { if (err) { res.status(500); res.json({ "message": err }); } else { res.json(entries); } }).sort({'created': -1}); },
/** * Show a list of content - admin */ function listContent(req,res,template,block,next) { // Re-retrieve our object var Content = calipso.db.model('Content'); var cPerm = calipso.permission.Helper.hasPermission("content:manage:create"), vPerm = calipso.permission.Helper.hasPermission("content:manage:view"); res.menu.adminToolbar.addMenuItem(req, {name:'Create',weight:1,path:'new',url:'/content/new',description:'Create content ...',permit:cPerm}); var tag = req.moduleParams.tag ? req.moduleParams.tag : ''; var format = req.moduleParams.format ? req.moduleParams.format : 'html'; var sortBy = req.moduleParams.sortBy; // TODO : Make this more flexible ... var t1 = req.moduleParams.t1 ? req.moduleParams.t1 : ''; var t2 = req.moduleParams.t2 ? req.moduleParams.t2 : ''; var t3 = req.moduleParams.t3 ? req.moduleParams.t3 : ''; var t4 = req.moduleParams.t4 ? req.moduleParams.t4 : ''; var query = new Query(); if(req.session && req.session.user && vPerm(req.session.user)) { // Show all } else { // Published only if not admin query.where('status','published'); } if(tag) { res.layout = "tagLanding" // Enable landing page layout to be created for a tag view query.where('tags',tag); } // Taxonomy tags var taxonomy = ""; if(t1) { res.layout = t1 + "Landing" // Enable landing page layout to be created for a t1 level; taxonomy += t1; if(t2) { taxonomy += "/" + t2; if(t3) { taxonomy += "/" + t3; if(t4) { taxonomy += "/" + t4; } } } } if(taxonomy) { query.where('taxonomy',new RegExp(taxonomy)); } // Get the content list getContentList(query,{req:req,res:res,template:template,block:block,format:format,sortBy:sortBy},next); };
/** * Show a list of content - admin */ function listContent(req,res,template,block,next) { // Re-retrieve our object var Content = calipso.lib.mongoose.model('Content'); res.menu.adminToolbar.addMenuItem({name:'New Content',path:'new',url:'/content/new',description:'Create content ...',security:[]}); var tag = req.moduleParams.tag ? req.moduleParams.tag : ''; var format = req.moduleParams.format ? req.moduleParams.format : 'html'; // TODO : Make this more flexible ... var t1 = req.moduleParams.t1 ? req.moduleParams.t1 : ''; var t2 = req.moduleParams.t2 ? req.moduleParams.t2 : ''; var t3 = req.moduleParams.t3 ? req.moduleParams.t3 : ''; var t4 = req.moduleParams.t4 ? req.moduleParams.t4 : ''; var query = new Query(); if(req.session.user && req.session.user.isAdmin) { // Show all } else { // Published only if not admin query.where('status','published'); } if(tag) { query.where('tags',tag); } // Taxonomy tags var taxonomy = ""; if(t1) { res.layout = t1 + "Landing" // Enable landing page layout to be created for this t1 level; taxonomy += t1; if(t2) { taxonomy += "/" + t2; if(t3) { taxonomy += "/" + t3; if(t4) { taxonomy += "/" + t4; } } } } if(taxonomy) { query.where('taxonomy',new RegExp(taxonomy)); } // Get the content list getContentList(query,{req:req,res:res,template:template,block:block,format:format},next); };
it('should not return users without any points', function() { // Remove some users first (leave only 000001 and 000002) var q = new Query(); q.nor([{ fbUserId: '000001' }, { fbUserId: '000002' }, { fbUserId: '111111' }, { fbUserId: '123456' }]); var removed = false; Mongo.User.remove(q, function() { removed = true; }); waitsFor(function() { return removed; }); var usersFound = false; var usersLength = 0; runs(function() { // Guard assertion: Make sure the remove was successful Mongo.User.find({}, function(error, users) { usersLength = users.length; usersFound = true; }); }); waitsFor(function() { return usersFound; }); runs(function() { expect(usersLength).toEqual(4); }); // Now, the actual test testDB(Mongo.findUsersWithMostPoints(), function(users) { expect(users.length).toEqual(2); expect(users[0].fbUserId).toEqual('000001'); expect(users[1].fbUserId).toEqual('000002'); }); });
getAll: function(req, res) { var pUserId = req.query.userId; var query = new mongoose.Query; if (pUserId && pUserId !== "" ) { query.where('userId', pUserId); } query.sort({ 'userId': 1, 'position': 1, 'urgency': 1 }); Goal.find(query, function (err, entries) { if (err) { res.status(500); res.json({ "message": err }); } else { res.json(entries); } }); },
includePaths.forEach((pathParts) => { // first, check that the include path is valid. if(!arrayContains(refPaths, pathParts[0])) { let title = "Invalid include path."; let detail = `Resources of type "${type}" don't have a(n) "${pathParts[0]}" relationship.`; throw new APIError(400, undefined, title, detail); } if(pathParts.length > 1) { throw new APIError(501, undefined, "Multi-level include paths aren't yet supported."); } // Finally, do the population populatedPaths.push(pathParts[0]); queryBuilder.populate(pathParts[0]); });
/** * Returns a Promise for an array of two items: the primary resources (either * a single Resource or a Collection) and the included resources, as an array. * * Note: The correct behavior if idOrIds is an empty array is to return no * documents, as happens below. If it's undefined, though, we're not filtering * by id and should return all documents. */ find(type, idOrIds, fields, sorts, filters, includePaths, limit) { const model = this.getModel(this.constructor.getModelName(type)); const queryBuilder = new mongoose.Query(null, null, model, model.collection); const [mode, idQuery] = this.constructor.getIdQueryType(idOrIds); const pluralizer = this.inflector.plural; let primaryDocumentsPromise, includedResourcesPromise = Q(null); queryBuilder[mode](idQuery); // do sorting if(Array.isArray(sorts)) { queryBuilder.sort(sorts.join(" ")); } // filter out invalid records with simple fields equality. // note that there's a non-trivial risk of sql-like injection here. // we're mostly protected by the fact that we're treating the filter's // value as a single string, though, and not parsing as JSON. if(typeof filters === "object" && !Array.isArray(filters)) { queryBuilder.where(filters); } // limit the number of documents if (typeof limit === "number" && !isNaN(limit)) { queryBuilder.limit(limit); } // in an ideal world, we'd use mongoose here to filter the fields before // querying. But, because the fields to filter can be scoped by type and // we don't always know about a document's type until after query (becuase // of discriminator keys), and because filtering out fields can really // complicate population for includes, we don't yet filter at query time but // instead just hide filtered fields in @docToResource. There is a more- // efficient way to do this down the road, though--something like taking the // provided fields and expanding them just enough (by looking at the type // heirarachy and the relationship paths) to make sure that we're not going // to run into any of the problems outlined above, while still querying for // less data than we would without any fields restriction. For reference, the // code for safely using the user's `fields` input, by putting them into a // mongoose `.select()` object so that the user can't prefix a field with a // minus on input to affect the query, is below. // Reference: http://mongoosejs.com/docs/api.html#query_Query-select. // let arrToSelectObject = (prev, curr) => { prev[curr] = 1; return prev; }; // for(let type in fields) { // fields[type] = fields[type].reduce(arrToSelectObject, {}); // } // support includes, but only a level deep for now (recursive includes, // especially if done in an efficient way query wise, are a pain in the ass). if(includePaths) { const populatedPaths = []; const refPaths = util.getReferencePaths(model); includePaths = includePaths.map((it) => it.split(".")); includePaths.forEach((pathParts) => { // first, check that the include path is valid. if(!arrayContains(refPaths, pathParts[0])) { let title = "Invalid include path."; let detail = `Resources of type "${type}" don't have a(n) "${pathParts[0]}" relationship.`; throw new APIError(400, undefined, title, detail); } if(pathParts.length > 1) { throw new APIError(501, undefined, "Multi-level include paths aren't yet supported."); } // Finally, do the population populatedPaths.push(pathParts[0]); queryBuilder.populate(pathParts[0]); }); let includedResources = []; primaryDocumentsPromise = Q(queryBuilder.exec()).then((docs) => { forEachArrayOrVal(docs, (doc) => { // There's no gaurantee that the doc (or every doc) was found // and we can't populate paths on a non-existent doc. if(!doc) return; populatedPaths.forEach((path) => { // if it's a toOne relationship, doc[path] will be a doc or undefined; // if it's a toMany relationship, we have an array (or undefined). let refDocs = Array.isArray(doc[path]) ? doc[path] : [doc[path]]; refDocs.forEach((it) => { // only include if it's not undefined. if(it) { includedResources.push( this.constructor.docToResource(it, pluralizer, fields) ); } }); }); }); return docs; }); includedResourcesPromise = primaryDocumentsPromise.then(() => new Collection(includedResources) ); } else { primaryDocumentsPromise = Q(queryBuilder.exec()); } return Q.all([primaryDocumentsPromise.then((it) => { const makeCollection = !idOrIds || Array.isArray(idOrIds) ? true : false; return this.constructor.docsToResourceOrCollection(it, makeCollection, pluralizer, fields); }), includedResourcesPromise]).catch(util.errorHandler); }