Compare commits

...

3 Commits

Author SHA1 Message Date
Phillip Thelen e890223a02 cleanup 2026-02-05 11:28:20 +01:00
Phillip Thelen 9a767a9eeb allow task history to be omitted from task list calls 2026-02-05 11:17:19 +01:00
Phillip Thelen 0982c80376 allow negative userFields to be passed 2026-02-05 11:16:57 +01:00
3 changed files with 35 additions and 22 deletions
+3 -2
View File
@@ -395,14 +395,15 @@ api.getUserTasks = {
const types = Tasks.tasksTypes.map(type => `${type}s`);
types.push('completedTodos', '_allCompletedTodos'); // _allCompletedTodos is currently in BETA and is likely to be removed in future
req.checkQuery('type', res.t('invalidTasksTypeExtra')).optional().isIn(types);
req.checkQuery('history', res.t('invalidHistoryBoolean')).optional().isBoolean();
const validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
const { user } = res.locals;
const { dueDate } = req.query;
const { dueDate, history } = req.query;
const tasks = await getTasks(req, res, { user, dueDate });
const tasks = await getTasks(req, res, { user, dueDate, history: history !== 'false' });
return res.respond(200, tasks);
},
};
+6 -1
View File
@@ -151,6 +151,7 @@ async function getTasks (req, res, options = {}) {
challenge,
group,
dueDate,
history = true,
} = options;
let query;
@@ -243,7 +244,11 @@ async function getTasks (req, res, options = {}) {
}];
}
const mQuery = Tasks.Task.find(query);
const projection = {};
if (!history) {
projection.history = 0;
}
const mQuery = Tasks.Task.find(query, projection);
if (limit) mQuery.limit(limit);
if (sort) mQuery.sort(sort);
+26 -19
View File
@@ -20,32 +20,37 @@ const COMMUNITY_MANAGER_EMAIL = nconf.get('EMAILS_COMMUNITY_MANAGER_EMAIL');
const USER_FIELDS_ALWAYS_LOADED = ['_id', '_v', 'notifications', 'preferences', 'auth', 'flags', 'permissions'];
function getUserFields (options, req) {
const excluded = options.userFieldsToExclude || [];
const included = options.userFieldsToInclude || [];
const urlPath = url.parse(req.url || '').pathname;
if (urlPath === '/user') {
const { userFields } = req.query;
if (userFields || urlPath !== '/user') {
const userFieldOptions = userFields.split(',')
.filter(field => USER_FIELDS_ALWAYS_LOADED.indexOf(field.split('.')[0]) === -1);
for (const field of userFieldOptions) {
if (field[0] === '-') {
excluded.push(field.slice(1));
} else {
included.push(field);
}
}
}
}
// A list of user fields that aren't needed for the route and are not loaded from the db.
// Must be an array
if (options.userFieldsToExclude) {
return options.userFieldsToExclude
if (excluded.length > 0) {
return excluded
.filter(field => !USER_FIELDS_ALWAYS_LOADED
.find(fieldToInclude => field.startsWith(fieldToInclude)))
.map(field => `-${field}`) // -${field} means exclude ${field} in mongodb
.join(' ');
}
if (options.userFieldsToInclude) {
return options.userFieldsToInclude.concat(USER_FIELDS_ALWAYS_LOADED).join(' ');
if (included.length > 0) {
return included.concat(USER_FIELDS_ALWAYS_LOADED).join(' ');
}
// Allows GET requests to /user to specify a list
// of user fields to return instead of the entire doc
const urlPath = url.parse(req.url).pathname;
const { userFields } = req.query;
if (!userFields || urlPath !== '/user') return '';
let userFieldOptions = userFields.split(',');
if (userFieldOptions.length === 0) return '';
userFieldOptions = userFieldOptions.filter(field => USER_FIELDS_ALWAYS_LOADED.indexOf(field.split('.')[0]) === -1);
return userFieldOptions.concat(USER_FIELDS_ALWAYS_LOADED).join(' ');
return '';
}
// Make sure stackdriver traces are storing the user id
@@ -83,8 +88,10 @@ export function authWithHeaders (options = {}) {
if (fields && fields.indexOf('apiToken') === -1 && fields.indexOf('-') === -1) {
fields = `${fields} apiToken`;
}
let findPromise = fields ? User.findOne(userQuery).select(fields) : User.findOne(userQuery);
let findPromise = User.findOne(userQuery);
if (fields && fields.length > 0) {
findPromise = findPromise.select(fields);
}
if (leanUser) {
findPromise = findPromise.lean();