Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring code in src/controllers/mods.js #68

Open
wants to merge 3 commits into
base: f24
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 65 additions & 46 deletions src/controllers/mods.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,74 +18,106 @@ const helpers = require('./helpers');
const modsController = module.exports;
modsController.flags = {};

// The following function has been broken down with helper functions to reduce cognitive complexity
modsController.flags.list = async function (req, res) {
console.log('mods.js has been loaded and is executing. The listing function for the flags is functional with refactored code.');
const [isAdminOrGlobalMod, moderatedCids,, { sorts }] = await initialize(req);
let [,, { filters }] = await initialize(req);

if (!checkAccess(isAdminOrGlobalMod, moderatedCids, req, res)) {
return;
}

filters = parseFilters(req, filters);
filters = adjustFiltersForMod(filters, res);
let hasFilter = determineHasFilter(filters);
const sort = parseSort(req, sorts);
hasFilter = hasFilter || !!sort;

const [flagsData, analyticsData, selectData] = await fetchData(req, filters, sort);
const selected = await getSelectedUsers(filters);

res.render('flags/list', {
flags: flagsData.flags,
count: flagsData.count,
analytics: analyticsData,
selectedCategory: selectData.selectedCategory,
selected,
hasFilter: hasFilter,
filters: filters,
expanded: !!(filters.assignee || filters.reporterId || filters.targetUid),
sort: sort || 'newest',
title: '[[pages:flags]]',
pagination: pagination.create(flagsData.page, flagsData.pageCount, req.query),
breadcrumbs: helpers.buildBreadcrumbs([{ text: '[[pages:flags]]' }]),
});
};

function initialize(req) {
const validFilters = ['assignee', 'state', 'reporterId', 'type', 'targetUid', 'cid', 'quick', 'page', 'perPage'];
const validSorts = ['newest', 'oldest', 'reports', 'upvotes', 'downvotes', 'replies'];

const results = await Promise.all([
return Promise.all([
user.isAdminOrGlobalMod(req.uid),
user.getModeratedCids(req.uid),
plugins.hooks.fire('filter:flags.validateFilters', { filters: validFilters }),
plugins.hooks.fire('filter:flags.validateSort', { sorts: validSorts }),
]);
const [isAdminOrGlobalMod, moderatedCids,, { sorts }] = results;
let [,, { filters }] = results;
}

function checkAccess(isAdminOrGlobalMod, moderatedCids, req, res) {
if (!(isAdminOrGlobalMod || !!moderatedCids.length)) {
return helpers.notAllowed(req, res);
helpers.notAllowed(req, res);
return false;
}

if (!isAdminOrGlobalMod && moderatedCids.length) {
res.locals.cids = moderatedCids.map(cid => String(cid));
}
return true;
}

// Parse query string params for filters, eliminate non-valid filters
filters = filters.reduce((memo, cur) => {
function parseFilters(req, filters) {
return filters.reduce((memo, cur) => {
if (req.query.hasOwnProperty(cur)) {
if (typeof req.query[cur] === 'string' && req.query[cur].trim() !== '') {
memo[cur] = req.query[cur].trim();
} else if (Array.isArray(req.query[cur]) && req.query[cur].length) {
memo[cur] = req.query[cur];
}
}

return memo;
}, {});
}

let hasFilter = !!Object.keys(filters).length;

function adjustFiltersForMod(filters, res) {
if (res.locals.cids) {
if (!filters.cid) {
// If mod and no cid filter, add filter for their modded categories
filters.cid = res.locals.cids;
} else if (Array.isArray(filters.cid)) {
// Remove cids they do not moderate
filters.cid = filters.cid.filter(cid => res.locals.cids.includes(String(cid)));
} else if (!res.locals.cids.includes(String(filters.cid))) {
filters.cid = res.locals.cids;
hasFilter = false;
}
}
return filters;
}

// Pagination doesn't count as a filter
if (
(Object.keys(filters).length === 1 && filters.hasOwnProperty('page')) ||
(Object.keys(filters).length === 2 && filters.hasOwnProperty('page') && filters.hasOwnProperty('perPage'))
) {
hasFilter = false;
}
function determineHasFilter(filters) {
return !!Object.keys(filters).length &&
!(Object.keys(filters).length === 1 && filters.hasOwnProperty('page')) &&
!(Object.keys(filters).length === 2 && filters.hasOwnProperty('page') && filters.hasOwnProperty('perPage'));
}

// Parse sort from query string
let sort;
if (req.query.sort) {
sort = sorts.includes(req.query.sort) ? req.query.sort : null;
}
if (sort === 'newest') {
sort = undefined;
function parseSort(req, sorts) {
let sort = null;
if (req.query.sort && sorts.includes(req.query.sort)) {
sort = req.query.sort;
}
hasFilter = hasFilter || !!sort;
return sort === 'newest' ? undefined : sort;
}

const [flagsData, analyticsData, selectData] = await Promise.all([
async function fetchData(req, filters, sort) {
return Promise.all([
flags.list({
filters: filters,
sort: sort,
Expand All @@ -95,8 +127,9 @@ modsController.flags.list = async function (req, res) {
analytics.getDailyStatsForSet('analytics:flags', Date.now(), 30),
helpers.getSelectedCategory(filters.cid),
]);
}

// Send back information for userFilter module
async function getSelectedUsers(filters) {
const selected = {};
await Promise.all(['assignee', 'reporterId', 'targetUid'].map(async (filter) => {
let uids = filters[filter];
Expand All @@ -110,22 +143,8 @@ modsController.flags.list = async function (req, res) {

selected[filter] = await user.getUsersFields(uids, ['username', 'userslug', 'picture']);
}));

res.render('flags/list', {
flags: flagsData.flags,
count: flagsData.count,
analytics: analyticsData,
selectedCategory: selectData.selectedCategory,
selected,
hasFilter: hasFilter,
filters: filters,
expanded: !!(filters.assignee || filters.reporterId || filters.targetUid),
sort: sort || 'newest',
title: '[[pages:flags]]',
pagination: pagination.create(flagsData.page, flagsData.pageCount, req.query),
breadcrumbs: helpers.buildBreadcrumbs([{ text: '[[pages:flags]]' }]),
});
};
return selected;
}

modsController.flags.detail = async function (req, res, next) {
const results = await utils.promiseParallel({
Expand Down