From 70c46f822567b423bfca0a42e0b680d777a5c7e7 Mon Sep 17 00:00:00 2001 From: Aisha Al Attiyah Date: Sun, 20 Oct 2024 00:09:22 +0300 Subject: [PATCH] fixed lint errors --- public/src/admin/dashboard/bug-logs.js | 118 ++-- src/controllers/admin/dashboard.js | 712 ++++++++++++------------- src/routes/admin.js | 128 ++--- src/routes/api.js | 1 - 4 files changed, 479 insertions(+), 480 deletions(-) diff --git a/public/src/admin/dashboard/bug-logs.js b/public/src/admin/dashboard/bug-logs.js index 749d40665e..7fcbd48901 100644 --- a/public/src/admin/dashboard/bug-logs.js +++ b/public/src/admin/dashboard/bug-logs.js @@ -1,62 +1,62 @@ 'use strict'; define('admin/dashboard/bug-logs', ['jquery', 'api'], ($, api) => { - const BugLogs = {}; - - BugLogs.init = () => { - // Fetch and display bug logs - fetchBugLogs(); - - // Handle bug report submission - $('#submit').on('click', submitBugReport); - }; - - function fetchBugLogs() { - api.get('/api/admin/get-bug-log') - .then((data) => { - const bugLogsContainer = $('#bug-logs-container'); - console.log(bugLogsContainer); - bugLogsContainer.empty(); - - if (data.bugLogs && data.bugLogs.length > 0) { - console.log(data.bugLogs); - data.bugLogs.forEach((log) => { - const logElement = $('
').addClass('bug-log'); - logElement.append($('

').text(`Name: ${log.name}`)); - logElement.append($('

').text(`Email: ${log.email}`)); - logElement.append($('

').text(`Description: ${log.bug-description}`)); - logElement.append($('

').text(`Timestamp: ${log.timestamp}`)); - bugLogsContainer.append(logElement); - }); - } else { - bugLogsContainer.append($('

').text('No bug logs found.')); - } - }) - .catch((err) => { - console.error('Error fetching bug logs:', err); - $('#bug-logs-container').append($('

').text('Error fetching bug logs.')); - }); - } - - function submitBugReport() { - const description = $('#bug-report-description').val().trim(); - - if (!description) { - alert('Description is required'); - return; - } - - api.post('/api/admin/submit-bug-report', { description }) - .then(() => { - alert('Bug report submitted successfully'); - $('#bug-report-description').val(''); - fetchBugLogs(); - }) - .catch((err) => { - console.error('Error submitting bug report:', err); - alert('Error submitting bug report'); - }); - } - - return BugLogs; -}); \ No newline at end of file + const BugLogs = {}; + + BugLogs.init = () => { + // Fetch and display bug logs + fetchBugLogs(); + + // Handle bug report submission + $('#submit').on('click', submitBugReport); + }; + + function fetchBugLogs() { + api.get('/api/admin/get-bug-log') + .then((data) => { + const bugLogsContainer = $('#bug-logs-container'); + console.log(bugLogsContainer); + bugLogsContainer.empty(); + + if (data.bugLogs && data.bugLogs.length > 0) { + console.log(data.bugLogs); + data.bugLogs.forEach((log) => { + const logElement = $('

').addClass('bug-log'); + logElement.append($('

').text(`Name: ${log.name}`)); + logElement.append($('

').text(`Email: ${log.email}`)); + logElement.append($('

').text(`Description: ${log.bugDescription}`)); + logElement.append($('

').text(`Timestamp: ${log.timestamp}`)); + bugLogsContainer.append(logElement); + }); + } else { + bugLogsContainer.append($('

').text('No bug logs found.')); + } + }) + .catch((err) => { + console.error('Error fetching bug logs:', err); + $('#bug-logs-container').append($('

').text('Error fetching bug logs.')); + }); + } + + function submitBugReport() { + const description = $('#bug-report-description').val().trim(); + + if (!description) { + alert('Description is required'); + return; + } + + api.post('/api/admin/submit-bug-report', { description }) + .then(() => { + alert('Bug report submitted successfully'); + $('#bug-report-description').val(''); + fetchBugLogs(); + }) + .catch((err) => { + console.error('Error submitting bug report:', err); + alert('Error submitting bug report'); + }); + } + + return BugLogs; +}); diff --git a/src/controllers/admin/dashboard.js b/src/controllers/admin/dashboard.js index 1843c32e59..28395fd08e 100644 --- a/src/controllers/admin/dashboard.js +++ b/src/controllers/admin/dashboard.js @@ -19,417 +19,417 @@ const emailer = require('../../emailer'); const dashboardController = module.exports; dashboardController.get = async function (req, res) { - const [stats, notices, latestVersion, lastrestart, isAdmin, popularSearches] = await Promise.all([ - getStats(), - getNotices(), - getLatestVersion(), - getLastRestart(), - user.isAdministrator(req.uid), - getPopularSearches(), - ]); - const version = nconf.get('version'); - - res.render('admin/dashboard', { - version: version, - lookupFailed: latestVersion === null, - latestVersion: latestVersion, - upgradeAvailable: latestVersion && semver.gt(latestVersion, version), - currentPrerelease: versions.isPrerelease.test(version), - notices: notices, - stats: stats, - canRestart: !!process.send, - lastrestart: lastrestart, - showSystemControls: isAdmin, - popularSearches: popularSearches, - }); + const [stats, notices, latestVersion, lastrestart, isAdmin, popularSearches] = await Promise.all([ + getStats(), + getNotices(), + getLatestVersion(), + getLastRestart(), + user.isAdministrator(req.uid), + getPopularSearches(), + ]); + const version = nconf.get('version'); + + res.render('admin/dashboard', { + version: version, + lookupFailed: latestVersion === null, + latestVersion: latestVersion, + upgradeAvailable: latestVersion && semver.gt(latestVersion, version), + currentPrerelease: versions.isPrerelease.test(version), + notices: notices, + stats: stats, + canRestart: !!process.send, + lastrestart: lastrestart, + showSystemControls: isAdmin, + popularSearches: popularSearches, + }); }; async function getNotices() { - const notices = [ - { - done: !meta.reloadRequired, - doneText: '[[admin/dashboard:restart-not-required]]', - notDoneText: '[[admin/dashboard:restart-required]]', - }, - { - done: plugins.hooks.hasListeners('filter:search.query'), - doneText: '[[admin/dashboard:search-plugin-installed]]', - notDoneText: '[[admin/dashboard:search-plugin-not-installed]]', - tooltip: '[[admin/dashboard:search-plugin-tooltip]]', - link: '/admin/extend/plugins', - }, - ]; - - if (emailer.fallbackNotFound) { - notices.push({ - done: false, - notDoneText: '[[admin/dashboard:fallback-emailer-not-found]]', - }); - } - - if (global.env !== 'production') { - notices.push({ - done: false, - notDoneText: '[[admin/dashboard:running-in-development]]', - }); - } - - return await plugins.hooks.fire('filter:admin.notices', notices); + const notices = [ + { + done: !meta.reloadRequired, + doneText: '[[admin/dashboard:restart-not-required]]', + notDoneText: '[[admin/dashboard:restart-required]]', + }, + { + done: plugins.hooks.hasListeners('filter:search.query'), + doneText: '[[admin/dashboard:search-plugin-installed]]', + notDoneText: '[[admin/dashboard:search-plugin-not-installed]]', + tooltip: '[[admin/dashboard:search-plugin-tooltip]]', + link: '/admin/extend/plugins', + }, + ]; + + if (emailer.fallbackNotFound) { + notices.push({ + done: false, + notDoneText: '[[admin/dashboard:fallback-emailer-not-found]]', + }); + } + + if (global.env !== 'production') { + notices.push({ + done: false, + notDoneText: '[[admin/dashboard:running-in-development]]', + }); + } + + return await plugins.hooks.fire('filter:admin.notices', notices); } async function getLatestVersion() { - try { - return await versions.getLatestVersion(); - } catch (err) { - winston.error(`[acp] Failed to fetch latest version\n${err.stack}`); - } - return null; + try { + return await versions.getLatestVersion(); + } catch (err) { + winston.error(`[acp] Failed to fetch latest version\n${err.stack}`); + } + return null; } dashboardController.getAnalytics = async (req, res, next) => { - // Basic validation - const validUnits = ['days', 'hours']; - const validSets = ['uniquevisitors', 'pageviews', 'pageviews:registered', 'pageviews:bot', 'pageviews:guest']; - const until = req.query.until ? new Date(parseInt(req.query.until, 10)) : Date.now(); - const count = req.query.count || (req.query.units === 'hours' ? 24 : 30); - if (isNaN(until) || !validUnits.includes(req.query.units)) { - return next(new Error('[[error:invalid-data]]')); - } - - // Filter out invalid sets, if no sets, assume all sets - let sets; - if (req.query.sets) { - sets = Array.isArray(req.query.sets) ? req.query.sets : [req.query.sets]; - sets = sets.filter(set => validSets.includes(set)); - } else { - sets = validSets; - } - - const method = req.query.units === 'days' ? analytics.getDailyStatsForSet : analytics.getHourlyStatsForSet; - let payload = await Promise.all(sets.map(set => method(`analytics:${set}`, until, count))); - payload = _.zipObject(sets, payload); - - res.json({ - query: { - set: req.query.set, - units: req.query.units, - until: until, - count: count, - }, - result: payload, - }); + // Basic validation + const validUnits = ['days', 'hours']; + const validSets = ['uniquevisitors', 'pageviews', 'pageviews:registered', 'pageviews:bot', 'pageviews:guest']; + const until = req.query.until ? new Date(parseInt(req.query.until, 10)) : Date.now(); + const count = req.query.count || (req.query.units === 'hours' ? 24 : 30); + if (isNaN(until) || !validUnits.includes(req.query.units)) { + return next(new Error('[[error:invalid-data]]')); + } + + // Filter out invalid sets, if no sets, assume all sets + let sets; + if (req.query.sets) { + sets = Array.isArray(req.query.sets) ? req.query.sets : [req.query.sets]; + sets = sets.filter(set => validSets.includes(set)); + } else { + sets = validSets; + } + + const method = req.query.units === 'days' ? analytics.getDailyStatsForSet : analytics.getHourlyStatsForSet; + let payload = await Promise.all(sets.map(set => method(`analytics:${set}`, until, count))); + payload = _.zipObject(sets, payload); + + res.json({ + query: { + set: req.query.set, + units: req.query.units, + until: until, + count: count, + }, + result: payload, + }); }; async function getStats() { - const cache = require('../../cache'); - const cachedStats = cache.get('admin:stats'); - if (cachedStats !== undefined) { - return cachedStats; - } + const cache = require('../../cache'); + const cachedStats = cache.get('admin:stats'); + if (cachedStats !== undefined) { + return cachedStats; + } - let results = await Promise.all([ - getStatsFromAnalytics('uniquevisitors', 'uniqueIPCount'), - getStatsFromAnalytics('logins', 'loginCount'), - getStatsForSet('users:joindate', 'userCount'), - getStatsForSet('posts:pid', 'postCount'), - getStatsForSet('topics:tid', 'topicCount'), - ]); + let results = await Promise.all([ + getStatsFromAnalytics('uniquevisitors', 'uniqueIPCount'), + getStatsFromAnalytics('logins', 'loginCount'), + getStatsForSet('users:joindate', 'userCount'), + getStatsForSet('posts:pid', 'postCount'), + getStatsForSet('topics:tid', 'topicCount'), + ]); - results[0].name = '[[admin/dashboard:unique-visitors]]'; + results[0].name = '[[admin/dashboard:unique-visitors]]'; - results[1].name = '[[admin/dashboard:logins]]'; - results[1].href = `${nconf.get('relative_path')}/admin/dashboard/logins`; + results[1].name = '[[admin/dashboard:logins]]'; + results[1].href = `${nconf.get('relative_path')}/admin/dashboard/logins`; - results[2].name = '[[admin/dashboard:new-users]]'; - results[2].href = `${nconf.get('relative_path')}/admin/dashboard/users`; + results[2].name = '[[admin/dashboard:new-users]]'; + results[2].href = `${nconf.get('relative_path')}/admin/dashboard/users`; - results[3].name = '[[admin/dashboard:posts]]'; + results[3].name = '[[admin/dashboard:posts]]'; - results[4].name = '[[admin/dashboard:topics]]'; - results[4].href = `${nconf.get('relative_path')}/admin/dashboard/topics`; + results[4].name = '[[admin/dashboard:topics]]'; + results[4].href = `${nconf.get('relative_path')}/admin/dashboard/topics`; - ({ results } = await plugins.hooks.fire('filter:admin.getStats', { - results, - helpers: { getStatsForSet, getStatsFromAnalytics }, - })); + ({ results } = await plugins.hooks.fire('filter:admin.getStats', { + results, + helpers: { getStatsForSet, getStatsFromAnalytics }, + })); - cache.set('admin:stats', results, 600000); - return results; + cache.set('admin:stats', results, 600000); + return results; } async function getStatsForSet(set, field) { - const terms = { - day: 86400000, - week: 604800000, - month: 2592000000, - }; - - const now = Date.now(); - const results = await utils.promiseParallel({ - yesterday: db.sortedSetCount(set, now - (terms.day * 2), '+inf'), - today: db.sortedSetCount(set, now - terms.day, '+inf'), - lastweek: db.sortedSetCount(set, now - (terms.week * 2), '+inf'), - thisweek: db.sortedSetCount(set, now - terms.week, '+inf'), - lastmonth: db.sortedSetCount(set, now - (terms.month * 2), '+inf'), - thismonth: db.sortedSetCount(set, now - terms.month, '+inf'), - alltime: getGlobalField(field), - }); - - return calculateDeltas(results); + const terms = { + day: 86400000, + week: 604800000, + month: 2592000000, + }; + + const now = Date.now(); + const results = await utils.promiseParallel({ + yesterday: db.sortedSetCount(set, now - (terms.day * 2), '+inf'), + today: db.sortedSetCount(set, now - terms.day, '+inf'), + lastweek: db.sortedSetCount(set, now - (terms.week * 2), '+inf'), + thisweek: db.sortedSetCount(set, now - terms.week, '+inf'), + lastmonth: db.sortedSetCount(set, now - (terms.month * 2), '+inf'), + thismonth: db.sortedSetCount(set, now - terms.month, '+inf'), + alltime: getGlobalField(field), + }); + + return calculateDeltas(results); } async function getStatsFromAnalytics(set, field) { - const today = new Date(); - today.setHours(0, 0, 0, 0); - - const data = await analytics.getDailyStatsForSet(`analytics:${set}`, today, 60); - const sum = arr => arr.reduce((memo, cur) => memo + cur, 0); - const results = { - yesterday: sum(data.slice(-2)), - today: data.slice(-1)[0], - lastweek: sum(data.slice(-14)), - thisweek: sum(data.slice(-7)), - lastmonth: sum(data.slice(0)), // entire set - thismonth: sum(data.slice(-30)), - alltime: await getGlobalField(field), - }; - - return calculateDeltas(results); + const today = new Date(); + today.setHours(0, 0, 0, 0); + + const data = await analytics.getDailyStatsForSet(`analytics:${set}`, today, 60); + const sum = arr => arr.reduce((memo, cur) => memo + cur, 0); + const results = { + yesterday: sum(data.slice(-2)), + today: data.slice(-1)[0], + lastweek: sum(data.slice(-14)), + thisweek: sum(data.slice(-7)), + lastmonth: sum(data.slice(0)), // entire set + thismonth: sum(data.slice(-30)), + alltime: await getGlobalField(field), + }; + + return calculateDeltas(results); } function calculateDeltas(results) { - function textClass(num) { - if (num > 0) { - return 'text-success'; - } else if (num < 0) { - return 'text-danger'; - } - return 'text-warning'; - } - - function increasePercent(last, now) { - const percent = last ? (now - last) / last * 100 : 0; - return percent.toFixed(1); - } - results.yesterday -= results.today; - results.dayIncrease = increasePercent(results.yesterday, results.today); - results.dayTextClass = textClass(results.dayIncrease); - - results.lastweek -= results.thisweek; - results.weekIncrease = increasePercent(results.lastweek, results.thisweek); - results.weekTextClass = textClass(results.weekIncrease); - - results.lastmonth -= results.thismonth; - results.monthIncrease = increasePercent(results.lastmonth, results.thismonth); - results.monthTextClass = textClass(results.monthIncrease); - - return results; + function textClass(num) { + if (num > 0) { + return 'text-success'; + } else if (num < 0) { + return 'text-danger'; + } + return 'text-warning'; + } + + function increasePercent(last, now) { + const percent = last ? (now - last) / last * 100 : 0; + return percent.toFixed(1); + } + results.yesterday -= results.today; + results.dayIncrease = increasePercent(results.yesterday, results.today); + results.dayTextClass = textClass(results.dayIncrease); + + results.lastweek -= results.thisweek; + results.weekIncrease = increasePercent(results.lastweek, results.thisweek); + results.weekTextClass = textClass(results.weekIncrease); + + results.lastmonth -= results.thismonth; + results.monthIncrease = increasePercent(results.lastmonth, results.thismonth); + results.monthTextClass = textClass(results.monthIncrease); + + return results; } async function getGlobalField(field) { - const count = await db.getObjectField('global', field); - return parseInt(count, 10) || 0; + const count = await db.getObjectField('global', field); + return parseInt(count, 10) || 0; } async function getLastRestart() { - const lastrestart = await db.getObject('lastrestart'); - if (!lastrestart) { - return null; - } - const userData = await user.getUserData(lastrestart.uid); - lastrestart.user = userData; - lastrestart.timestampISO = utils.toISOString(lastrestart.timestamp); - return lastrestart; + const lastrestart = await db.getObject('lastrestart'); + if (!lastrestart) { + return null; + } + const userData = await user.getUserData(lastrestart.uid); + lastrestart.user = userData; + lastrestart.timestampISO = utils.toISOString(lastrestart.timestamp); + return lastrestart; } async function getPopularSearches() { - const searches = await db.getSortedSetRevRangeWithScores('searches:all', 0, 9); - return searches.map(s => ({ value: validator.escape(String(s.value)), score: s.score })); + const searches = await db.getSortedSetRevRangeWithScores('searches:all', 0, 9); + return searches.map(s => ({ value: validator.escape(String(s.value)), score: s.score })); } dashboardController.getLogins = async (req, res) => { - let stats = await getStats(); - stats = stats.filter(stat => stat.name === '[[admin/dashboard:logins]]').map(({ ...stat }) => { - delete stat.href; - return stat; - }); - const summary = { - day: stats[0].today, - week: stats[0].thisweek, - month: stats[0].thismonth, - }; - - // List recent sessions - const start = Date.now() - (1000 * 60 * 60 * 24 * meta.config.loginDays); - const uids = await db.getSortedSetRangeByScore('users:online', 0, 500, start, Date.now()); - const usersData = await user.getUsersData(uids); - let sessions = await Promise.all(uids.map(async (uid) => { - const sessions = await user.auth.getSessions(uid); - sessions.forEach((session) => { - session.user = usersData[uids.indexOf(uid)]; - }); - - return sessions; - })); - sessions = _.flatten(sessions).sort((a, b) => b.datetime - a.datetime); - - res.render('admin/dashboard/logins', { - set: 'logins', - query: req.query, - stats, - summary, - sessions, - loginDays: meta.config.loginDays, - }); + let stats = await getStats(); + stats = stats.filter(stat => stat.name === '[[admin/dashboard:logins]]').map(({ ...stat }) => { + delete stat.href; + return stat; + }); + const summary = { + day: stats[0].today, + week: stats[0].thisweek, + month: stats[0].thismonth, + }; + + // List recent sessions + const start = Date.now() - (1000 * 60 * 60 * 24 * meta.config.loginDays); + const uids = await db.getSortedSetRangeByScore('users:online', 0, 500, start, Date.now()); + const usersData = await user.getUsersData(uids); + let sessions = await Promise.all(uids.map(async (uid) => { + const sessions = await user.auth.getSessions(uid); + sessions.forEach((session) => { + session.user = usersData[uids.indexOf(uid)]; + }); + + return sessions; + })); + sessions = _.flatten(sessions).sort((a, b) => b.datetime - a.datetime); + + res.render('admin/dashboard/logins', { + set: 'logins', + query: req.query, + stats, + summary, + sessions, + loginDays: meta.config.loginDays, + }); }; dashboardController.getUsers = async (req, res) => { - let stats = await getStats(); - stats = stats.filter(stat => stat.name === '[[admin/dashboard:new-users]]').map(({ ...stat }) => { - delete stat.href; - return stat; - }); - const summary = { - day: stats[0].today, - week: stats[0].thisweek, - month: stats[0].thismonth, - }; - - // List of users registered within time frame - const end = parseInt(req.query.until, 10) || Date.now(); - const start = end - (1000 * 60 * 60 * (req.query.units === 'days' ? 24 : 1) * (req.query.count || (req.query.units === 'days' ? 30 : 24))); - const uids = await db.getSortedSetRangeByScore('users:joindate', 0, 500, start, end); - const users = await user.getUsersData(uids); - - res.render('admin/dashboard/users', { - set: 'registrations', - query: req.query, - stats, - summary, - users, - }); + let stats = await getStats(); + stats = stats.filter(stat => stat.name === '[[admin/dashboard:new-users]]').map(({ ...stat }) => { + delete stat.href; + return stat; + }); + const summary = { + day: stats[0].today, + week: stats[0].thisweek, + month: stats[0].thismonth, + }; + + // List of users registered within time frame + const end = parseInt(req.query.until, 10) || Date.now(); + const start = end - (1000 * 60 * 60 * (req.query.units === 'days' ? 24 : 1) * (req.query.count || (req.query.units === 'days' ? 30 : 24))); + const uids = await db.getSortedSetRangeByScore('users:joindate', 0, 500, start, end); + const users = await user.getUsersData(uids); + + res.render('admin/dashboard/users', { + set: 'registrations', + query: req.query, + stats, + summary, + users, + }); }; dashboardController.getTopics = async (req, res) => { - let stats = await getStats(); - stats = stats.filter(stat => stat.name === '[[admin/dashboard:topics]]').map(({ ...stat }) => { - delete stat.href; - return stat; - }); - const summary = { - day: stats[0].today, - week: stats[0].thisweek, - month: stats[0].thismonth, - }; - - // List of topics created within time frame - const end = parseInt(req.query.until, 10) || Date.now(); - const start = end - (1000 * 60 * 60 * (req.query.units === 'days' ? 24 : 1) * (req.query.count || (req.query.units === 'days' ? 30 : 24))); - const tids = await db.getSortedSetRangeByScore('topics:tid', 0, 500, start, end); - const topicData = await topics.getTopicsByTids(tids); - - res.render('admin/dashboard/topics', { - set: 'topics', - query: req.query, - stats, - summary, - topics: topicData, - }); + let stats = await getStats(); + stats = stats.filter(stat => stat.name === '[[admin/dashboard:topics]]').map(({ ...stat }) => { + delete stat.href; + return stat; + }); + const summary = { + day: stats[0].today, + week: stats[0].thisweek, + month: stats[0].thismonth, + }; + + // List of topics created within time frame + const end = parseInt(req.query.until, 10) || Date.now(); + const start = end - (1000 * 60 * 60 * (req.query.units === 'days' ? 24 : 1) * (req.query.count || (req.query.units === 'days' ? 30 : 24))); + const tids = await db.getSortedSetRangeByScore('topics:tid', 0, 500, start, end); + const topicData = await topics.getTopicsByTids(tids); + + res.render('admin/dashboard/topics', { + set: 'topics', + query: req.query, + stats, + summary, + topics: topicData, + }); }; dashboardController.getSearches = async (req, res) => { - let start = 0; - let end = 0; - if (req.query.start) { - start = new Date(req.query.start); - start.setHours(24, 0, 0, 0); - end = new Date(); - end.setHours(24, 0, 0, 0); - } - if (req.query.end) { - end = new Date(req.query.end); - end.setHours(24, 0, 0, 0); - } - - let searches; - if (start && end && start <= end) { - const daysArr = [start]; - const nextDay = new Date(start.getTime()); - while (nextDay < end) { - nextDay.setDate(nextDay.getDate() + 1); - nextDay.setHours(0, 0, 0, 0); - daysArr.push(new Date(nextDay.getTime())); - } - - const daysData = await Promise.all( - daysArr.map(async d => db.getSortedSetRevRangeWithScores(`searches:${d.getTime()}`, 0, -1)) - ); - - const map = {}; - daysData.forEach((d) => { - d.forEach((search) => { - if (!map[search.value]) { - map[search.value] = search.score; - } else { - map[search.value] += search.score; - } - }); - }); - - searches = Object.keys(map) - .map(key => ({ value: key, score: map[key] })) - .sort((a, b) => b.score - a.score); - } else { - searches = await db.getSortedSetRevRangeWithScores('searches:all', 0, 99); - } - - res.render('admin/dashboard/searches', { - searches: searches.map(s => ({ value: validator.escape(String(s.value)), score: s.score })), - startDate: req.query.start ? validator.escape(String(req.query.start)) : null, - endDate: req.query.end ? validator.escape(String(req.query.end)) : null, - }); + let start = 0; + let end = 0; + if (req.query.start) { + start = new Date(req.query.start); + start.setHours(24, 0, 0, 0); + end = new Date(); + end.setHours(24, 0, 0, 0); + } + if (req.query.end) { + end = new Date(req.query.end); + end.setHours(24, 0, 0, 0); + } + + let searches; + if (start && end && start <= end) { + const daysArr = [start]; + const nextDay = new Date(start.getTime()); + while (nextDay < end) { + nextDay.setDate(nextDay.getDate() + 1); + nextDay.setHours(0, 0, 0, 0); + daysArr.push(new Date(nextDay.getTime())); + } + + const daysData = await Promise.all( + daysArr.map(async d => db.getSortedSetRevRangeWithScores(`searches:${d.getTime()}`, 0, -1)) + ); + + const map = {}; + daysData.forEach((d) => { + d.forEach((search) => { + if (!map[search.value]) { + map[search.value] = search.score; + } else { + map[search.value] += search.score; + } + }); + }); + + searches = Object.keys(map) + .map(key => ({ value: key, score: map[key] })) + .sort((a, b) => b.score - a.score); + } else { + searches = await db.getSortedSetRevRangeWithScores('searches:all', 0, 99); + } + + res.render('admin/dashboard/searches', { + searches: searches.map(s => ({ value: validator.escape(String(s.value)), score: s.score })), + startDate: req.query.start ? validator.escape(String(req.query.start)) : null, + endDate: req.query.end ? validator.escape(String(req.query.end)) : null, + }); }; const bugLogs = []; dashboardController.getBugLogs = async function (req, res) { - console.log('getbuglogs'); // Add logging - try { - // Sanitize and format bug logs before rendering - console.log('bugLogs:', bugLogs); - const sanitizedBugLogs = bugLogs.map(log => ({ - user: validator.escape(String(log.user)), - description: validator.escape(String(log.description)), - timestamp: new Date(log.timestamp).toISOString(), - })); - - // Pass the sanitized bug logs to the view for rendering - res.render('admin/dashboard/bug-logs', { bugLogs: sanitizedBugLogs }); - } catch (error) { - console.error('Error fetching bug logs:', error); // Log the error for debugging - res.status(500).json({ message: 'Internal server error' }); - } + console.log('getbuglogs'); // Add logging + try { + // Sanitize and format bug logs before rendering + console.log('bugLogs:', bugLogs); + const sanitizedBugLogs = bugLogs.map(log => ({ + user: validator.escape(String(log.user)), + description: validator.escape(String(log.description)), + timestamp: new Date(log.timestamp).toISOString(), + })); + + // Pass the sanitized bug logs to the view for rendering + res.render('admin/dashboard/bug-logs', { bugLogs: sanitizedBugLogs }); + } catch (error) { + console.error('Error fetching bug logs:', error); // Log the error for debugging + res.status(500).json({ message: 'Internal server error' }); + } }; dashboardController.submitBugReport = async function (req, res) { - console.log('submitBugReport'); // Add logging - console.log('req.body:', req.body); // Add logging - try { - const { description } = req.body; - if (!description) { - return res.status(400).json({ message: 'Description is required' }); - } - - const sanitizedDescription = validator.escape(description); - const timestamp = Date.now(); - const user = req.user ? req.user.username : 'Anonymous'; // Assuming req.user contains the user information - - // Add the bug report to the in-memory array - bugLogs.push({ user, description: sanitizedDescription, timestamp }); - console.log('Bug report submitted:', { user, description: sanitizedDescription, timestamp }); - res.status(201).json({ message: 'Bug report submitted successfully' }); - } catch (error) { - console.error('Error submitting bug report:', error); // Log the error for debugging - res.status(500).json({ message: 'Internal server error' }); - } -}; \ No newline at end of file + console.log('submitBugReport'); // Add logging + console.log('req.body:', req.body); // Add logging + try { + const { description } = req.body; + if (!description) { + return res.status(400).json({ message: 'Description is required' }); + } + + const sanitizedDescription = validator.escape(description); + const timestamp = Date.now(); + const user = req.user ? req.user.username : 'Anonymous'; // Assuming req.user contains the user information + + // Add the bug report to the in-memory array + bugLogs.push({ user, description: sanitizedDescription, timestamp }); + console.log('Bug report submitted:', { user, description: sanitizedDescription, timestamp }); + res.status(201).json({ message: 'Bug report submitted successfully' }); + } catch (error) { + console.error('Error submitting bug report:', error); // Log the error for debugging + res.status(500).json({ message: 'Internal server error' }); + } +}; diff --git a/src/routes/admin.js b/src/routes/admin.js index 3a5978f928..7baff43dc5 100644 --- a/src/routes/admin.js +++ b/src/routes/admin.js @@ -3,84 +3,84 @@ const helpers = require('./helpers'); module.exports = function (app, name, middleware, controllers) { - const middlewares = [middleware.pluginHooks]; + const middlewares = [middleware.pluginHooks]; - helpers.setupAdminPageRoute(app, `/${name}`, middlewares, controllers.admin.routeIndex); + helpers.setupAdminPageRoute(app, `/${name}`, middlewares, controllers.admin.routeIndex); - helpers.setupAdminPageRoute(app, `/${name}/dashboard`, middlewares, controllers.admin.dashboard.get); - helpers.setupAdminPageRoute(app, `/${name}/dashboard/logins`, middlewares, controllers.admin.dashboard.getLogins); - helpers.setupAdminPageRoute(app, `/${name}/dashboard/users`, middlewares, controllers.admin.dashboard.getUsers); - helpers.setupAdminPageRoute(app, `/${name}/dashboard/topics`, middlewares, controllers.admin.dashboard.getTopics); - helpers.setupAdminPageRoute(app, `/${name}/dashboard/searches`, middlewares, controllers.admin.dashboard.getSearches); - helpers.setupAdminPageRoute(app, `/${name}/dashboard/bug-logs`, middlewares, controllers.admin.dashboard.getBugLogs); + helpers.setupAdminPageRoute(app, `/${name}/dashboard`, middlewares, controllers.admin.dashboard.get); + helpers.setupAdminPageRoute(app, `/${name}/dashboard/logins`, middlewares, controllers.admin.dashboard.getLogins); + helpers.setupAdminPageRoute(app, `/${name}/dashboard/users`, middlewares, controllers.admin.dashboard.getUsers); + helpers.setupAdminPageRoute(app, `/${name}/dashboard/topics`, middlewares, controllers.admin.dashboard.getTopics); + helpers.setupAdminPageRoute(app, `/${name}/dashboard/searches`, middlewares, controllers.admin.dashboard.getSearches); + helpers.setupAdminPageRoute(app, `/${name}/dashboard/bug-logs`, middlewares, controllers.admin.dashboard.getBugLogs); - helpers.setupAdminPageRoute(app, `/${name}/manage/categories`, middlewares, controllers.admin.categories.getAll); - helpers.setupAdminPageRoute(app, `/${name}/manage/categories/:category_id`, middlewares, controllers.admin.categories.get); - helpers.setupAdminPageRoute(app, `/${name}/manage/categories/:category_id/analytics`, middlewares, controllers.admin.categories.getAnalytics); + helpers.setupAdminPageRoute(app, `/${name}/manage/categories`, middlewares, controllers.admin.categories.getAll); + helpers.setupAdminPageRoute(app, `/${name}/manage/categories/:category_id`, middlewares, controllers.admin.categories.get); + helpers.setupAdminPageRoute(app, `/${name}/manage/categories/:category_id/analytics`, middlewares, controllers.admin.categories.getAnalytics); - helpers.setupAdminPageRoute(app, `/${name}/manage/privileges/:cid?`, middlewares, controllers.admin.privileges.get); - helpers.setupAdminPageRoute(app, `/${name}/manage/tags`, middlewares, controllers.admin.tags.get); + helpers.setupAdminPageRoute(app, `/${name}/manage/privileges/:cid?`, middlewares, controllers.admin.privileges.get); + helpers.setupAdminPageRoute(app, `/${name}/manage/tags`, middlewares, controllers.admin.tags.get); - helpers.setupAdminPageRoute(app, `/${name}/manage/users`, middlewares, controllers.admin.users.index); - helpers.setupAdminPageRoute(app, `/${name}/manage/registration`, middlewares, controllers.admin.users.registrationQueue); + helpers.setupAdminPageRoute(app, `/${name}/manage/users`, middlewares, controllers.admin.users.index); + helpers.setupAdminPageRoute(app, `/${name}/manage/registration`, middlewares, controllers.admin.users.registrationQueue); - helpers.setupAdminPageRoute(app, `/${name}/manage/admins-mods`, middlewares, controllers.admin.adminsMods.get); + helpers.setupAdminPageRoute(app, `/${name}/manage/admins-mods`, middlewares, controllers.admin.adminsMods.get); - helpers.setupAdminPageRoute(app, `/${name}/manage/groups`, middlewares, controllers.admin.groups.list); - helpers.setupAdminPageRoute(app, `/${name}/manage/groups/:name`, middlewares, controllers.admin.groups.get); + helpers.setupAdminPageRoute(app, `/${name}/manage/groups`, middlewares, controllers.admin.groups.list); + helpers.setupAdminPageRoute(app, `/${name}/manage/groups/:name`, middlewares, controllers.admin.groups.get); - helpers.setupAdminPageRoute(app, `/${name}/manage/uploads`, middlewares, controllers.admin.uploads.get); - helpers.setupAdminPageRoute(app, `/${name}/manage/digest`, middlewares, controllers.admin.digest.get); + helpers.setupAdminPageRoute(app, `/${name}/manage/uploads`, middlewares, controllers.admin.uploads.get); + helpers.setupAdminPageRoute(app, `/${name}/manage/digest`, middlewares, controllers.admin.digest.get); - helpers.setupAdminPageRoute(app, `/${name}/settings/email`, middlewares, controllers.admin.settings.email); - helpers.setupAdminPageRoute(app, `/${name}/settings/user`, middlewares, controllers.admin.settings.user); - helpers.setupAdminPageRoute(app, `/${name}/settings/post`, middlewares, controllers.admin.settings.post); - helpers.setupAdminPageRoute(app, `/${name}/settings/advanced`, middlewares, controllers.admin.settings.advanced); - helpers.setupAdminPageRoute(app, `/${name}/settings/navigation`, middlewares, controllers.admin.settings.navigation); - helpers.setupAdminPageRoute(app, `/${name}/settings/api`, middlewares, controllers.admin.settings.api); - helpers.setupAdminPageRoute(app, `/${name}/settings/:term?`, middlewares, controllers.admin.settings.get); + helpers.setupAdminPageRoute(app, `/${name}/settings/email`, middlewares, controllers.admin.settings.email); + helpers.setupAdminPageRoute(app, `/${name}/settings/user`, middlewares, controllers.admin.settings.user); + helpers.setupAdminPageRoute(app, `/${name}/settings/post`, middlewares, controllers.admin.settings.post); + helpers.setupAdminPageRoute(app, `/${name}/settings/advanced`, middlewares, controllers.admin.settings.advanced); + helpers.setupAdminPageRoute(app, `/${name}/settings/navigation`, middlewares, controllers.admin.settings.navigation); + helpers.setupAdminPageRoute(app, `/${name}/settings/api`, middlewares, controllers.admin.settings.api); + helpers.setupAdminPageRoute(app, `/${name}/settings/:term?`, middlewares, controllers.admin.settings.get); - helpers.setupAdminPageRoute(app, `/${name}/appearance/:term?`, middlewares, controllers.admin.appearance.get); + helpers.setupAdminPageRoute(app, `/${name}/appearance/:term?`, middlewares, controllers.admin.appearance.get); - helpers.setupAdminPageRoute(app, `/${name}/extend/plugins`, middlewares, controllers.admin.plugins.get); - helpers.setupAdminPageRoute(app, `/${name}/extend/widgets`, middlewares, controllers.admin.extend.widgets.get); - helpers.setupAdminPageRoute(app, `/${name}/extend/rewards`, middlewares, controllers.admin.extend.rewards.get); + helpers.setupAdminPageRoute(app, `/${name}/extend/plugins`, middlewares, controllers.admin.plugins.get); + helpers.setupAdminPageRoute(app, `/${name}/extend/widgets`, middlewares, controllers.admin.extend.widgets.get); + helpers.setupAdminPageRoute(app, `/${name}/extend/rewards`, middlewares, controllers.admin.extend.rewards.get); - helpers.setupAdminPageRoute(app, `/${name}/advanced/database`, middlewares, controllers.admin.database.get); - helpers.setupAdminPageRoute(app, `/${name}/advanced/events`, middlewares, controllers.admin.events.get); - helpers.setupAdminPageRoute(app, `/${name}/advanced/hooks`, middlewares, controllers.admin.hooks.get); - helpers.setupAdminPageRoute(app, `/${name}/advanced/logs`, middlewares, controllers.admin.logs.get); - helpers.setupAdminPageRoute(app, `/${name}/advanced/errors`, middlewares, controllers.admin.errors.get); - helpers.setupAdminPageRoute(app, `/${name}/advanced/errors/export`, middlewares, controllers.admin.errors.export); - helpers.setupAdminPageRoute(app, `/${name}/advanced/cache`, middlewares, controllers.admin.cache.get); + helpers.setupAdminPageRoute(app, `/${name}/advanced/database`, middlewares, controllers.admin.database.get); + helpers.setupAdminPageRoute(app, `/${name}/advanced/events`, middlewares, controllers.admin.events.get); + helpers.setupAdminPageRoute(app, `/${name}/advanced/hooks`, middlewares, controllers.admin.hooks.get); + helpers.setupAdminPageRoute(app, `/${name}/advanced/logs`, middlewares, controllers.admin.logs.get); + helpers.setupAdminPageRoute(app, `/${name}/advanced/errors`, middlewares, controllers.admin.errors.get); + helpers.setupAdminPageRoute(app, `/${name}/advanced/errors/export`, middlewares, controllers.admin.errors.export); + helpers.setupAdminPageRoute(app, `/${name}/advanced/cache`, middlewares, controllers.admin.cache.get); - helpers.setupAdminPageRoute(app, `/${name}/development/logger`, middlewares, controllers.admin.logger.get); - helpers.setupAdminPageRoute(app, `/${name}/development/info`, middlewares, controllers.admin.info.get); + helpers.setupAdminPageRoute(app, `/${name}/development/logger`, middlewares, controllers.admin.logger.get); + helpers.setupAdminPageRoute(app, `/${name}/development/info`, middlewares, controllers.admin.info.get); - apiRoutes(app, name, middleware, controllers); + apiRoutes(app, name, middleware, controllers); }; function apiRoutes(router, name, middleware, controllers) { - router.get(`/api/${name}/config`, middleware.ensureLoggedIn, helpers.tryRoute(controllers.admin.getConfig)); - router.get(`/api/${name}/users/csv`, middleware.ensureLoggedIn, helpers.tryRoute(controllers.admin.users.getCSV)); - router.get(`/api/${name}/groups/:groupname/csv`, middleware.ensureLoggedIn, helpers.tryRoute(controllers.admin.groups.getCSV)); - router.get(`/api/${name}/analytics`, middleware.ensureLoggedIn, helpers.tryRoute(controllers.admin.dashboard.getAnalytics)); - router.get(`/api/${name}/advanced/cache/dump`, middleware.ensureLoggedIn, helpers.tryRoute(controllers.admin.cache.dump)); - - router.get(`/api/${name}/get-bug-log`, middleware.ensureLoggedIn, helpers.tryRoute(controllers.admin.dashboard.getBugLogs)); - router.post(`/api/${name}/submit-bug-report`, middleware.ensureLoggedIn, helpers.tryRoute(controllers.admin.dashboard.submitBugReport)); - - const multipart = require('connect-multiparty'); - const multipartMiddleware = multipart(); - - const middlewares = [multipartMiddleware, middleware.validateFiles, middleware.applyCSRF, middleware.ensureLoggedIn]; - - router.post(`/api/${name}/category/uploadpicture`, middlewares, helpers.tryRoute(controllers.admin.uploads.uploadCategoryPicture)); - router.post(`/api/${name}/uploadfavicon`, middlewares, helpers.tryRoute(controllers.admin.uploads.uploadFavicon)); - router.post(`/api/${name}/uploadTouchIcon`, middlewares, helpers.tryRoute(controllers.admin.uploads.uploadTouchIcon)); - router.post(`/api/${name}/uploadMaskableIcon`, middlewares, helpers.tryRoute(controllers.admin.uploads.uploadMaskableIcon)); - router.post(`/api/${name}/uploadlogo`, middlewares, helpers.tryRoute(controllers.admin.uploads.uploadLogo)); - router.post(`/api/${name}/uploadOgImage`, middlewares, helpers.tryRoute(controllers.admin.uploads.uploadOgImage)); - router.post(`/api/${name}/upload/file`, middlewares, helpers.tryRoute(controllers.admin.uploads.uploadFile)); - router.post(`/api/${name}/uploadDefaultAvatar`, middlewares, helpers.tryRoute(controllers.admin.uploads.uploadDefaultAvatar)); -} \ No newline at end of file + router.get(`/api/${name}/config`, middleware.ensureLoggedIn, helpers.tryRoute(controllers.admin.getConfig)); + router.get(`/api/${name}/users/csv`, middleware.ensureLoggedIn, helpers.tryRoute(controllers.admin.users.getCSV)); + router.get(`/api/${name}/groups/:groupname/csv`, middleware.ensureLoggedIn, helpers.tryRoute(controllers.admin.groups.getCSV)); + router.get(`/api/${name}/analytics`, middleware.ensureLoggedIn, helpers.tryRoute(controllers.admin.dashboard.getAnalytics)); + router.get(`/api/${name}/advanced/cache/dump`, middleware.ensureLoggedIn, helpers.tryRoute(controllers.admin.cache.dump)); + + router.get(`/api/${name}/get-bug-log`, middleware.ensureLoggedIn, helpers.tryRoute(controllers.admin.dashboard.getBugLogs)); + router.post(`/api/${name}/submit-bug-report`, middleware.ensureLoggedIn, helpers.tryRoute(controllers.admin.dashboard.submitBugReport)); + + const multipart = require('connect-multiparty'); + const multipartMiddleware = multipart(); + + const middlewares = [multipartMiddleware, middleware.validateFiles, middleware.applyCSRF, middleware.ensureLoggedIn]; + + router.post(`/api/${name}/category/uploadpicture`, middlewares, helpers.tryRoute(controllers.admin.uploads.uploadCategoryPicture)); + router.post(`/api/${name}/uploadfavicon`, middlewares, helpers.tryRoute(controllers.admin.uploads.uploadFavicon)); + router.post(`/api/${name}/uploadTouchIcon`, middlewares, helpers.tryRoute(controllers.admin.uploads.uploadTouchIcon)); + router.post(`/api/${name}/uploadMaskableIcon`, middlewares, helpers.tryRoute(controllers.admin.uploads.uploadMaskableIcon)); + router.post(`/api/${name}/uploadlogo`, middlewares, helpers.tryRoute(controllers.admin.uploads.uploadLogo)); + router.post(`/api/${name}/uploadOgImage`, middlewares, helpers.tryRoute(controllers.admin.uploads.uploadOgImage)); + router.post(`/api/${name}/upload/file`, middlewares, helpers.tryRoute(controllers.admin.uploads.uploadFile)); + router.post(`/api/${name}/uploadDefaultAvatar`, middlewares, helpers.tryRoute(controllers.admin.uploads.uploadDefaultAvatar)); +} diff --git a/src/routes/api.js b/src/routes/api.js index b155c2f907..0fe575a326 100644 --- a/src/routes/api.js +++ b/src/routes/api.js @@ -42,5 +42,4 @@ module.exports = function (app, middleware, controllers) { middleware.canViewUsers, middleware.checkAccountPermissions, ], helpers.tryRoute(controllers.accounts.edit.uploadPicture)); - };