| 
									
										
										
										
											2015-09-17 16:25:15 -04:00
										 |  |  | 'use strict'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 11:53:51 -04:00
										 |  |  | const nconf = require('nconf'); | 
					
						
							|  |  |  | const semver = require('semver'); | 
					
						
							|  |  |  | const winston = require('winston'); | 
					
						
							| 
									
										
										
										
											2019-06-28 14:59:55 -04:00
										 |  |  | const _ = require('lodash'); | 
					
						
							| 
									
										
										
										
											2015-09-17 16:25:15 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 11:53:51 -04:00
										 |  |  | const versions = require('../../admin/versions'); | 
					
						
							|  |  |  | const db = require('../../database'); | 
					
						
							|  |  |  | const meta = require('../../meta'); | 
					
						
							| 
									
										
										
										
											2020-01-04 10:34:20 -05:00
										 |  |  | const analytics = require('../../analytics'); | 
					
						
							| 
									
										
										
										
											2019-08-14 11:53:51 -04:00
										 |  |  | const plugins = require('../../plugins'); | 
					
						
							|  |  |  | const user = require('../../user'); | 
					
						
							| 
									
										
										
										
											2021-02-24 10:01:54 -05:00
										 |  |  | const topics = require('../../topics'); | 
					
						
							| 
									
										
										
										
											2019-08-14 11:53:51 -04:00
										 |  |  | const utils = require('../../utils'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const dashboardController = module.exports; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | dashboardController.get = async function (req, res) { | 
					
						
							| 
									
										
										
										
											2020-06-05 15:26:51 -04:00
										 |  |  | 	const [stats, notices, latestVersion, lastrestart, isAdmin] = await Promise.all([ | 
					
						
							| 
									
										
										
										
											2019-08-14 11:53:51 -04:00
										 |  |  | 		getStats(), | 
					
						
							|  |  |  | 		getNotices(), | 
					
						
							|  |  |  | 		getLatestVersion(), | 
					
						
							|  |  |  | 		getLastRestart(), | 
					
						
							| 
									
										
										
										
											2020-06-25 17:08:09 -04:00
										 |  |  | 		user.isAdministrator(req.uid), | 
					
						
							| 
									
										
										
										
											2019-08-14 11:53:51 -04:00
										 |  |  | 	]); | 
					
						
							|  |  |  | 	const version = nconf.get('version'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-29 09:59:22 -04:00
										 |  |  | 	res.render('admin/dashboard', { | 
					
						
							| 
									
										
										
										
											2019-08-14 11:53:51 -04:00
										 |  |  | 		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, | 
					
						
							| 
									
										
										
										
											2020-06-05 15:26:51 -04:00
										 |  |  | 		showSystemControls: isAdmin, | 
					
						
							| 
									
										
										
										
											2019-08-14 11:53:51 -04:00
										 |  |  | 	}); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | async function getNotices() { | 
					
						
							|  |  |  | 	const notices = [ | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			done: !meta.reloadRequired, | 
					
						
							| 
									
										
										
										
											2020-05-29 09:59:22 -04:00
										 |  |  | 			doneText: '[[admin/dashboard:restart-not-required]]', | 
					
						
							|  |  |  | 			notDoneText: '[[admin/dashboard:restart-required]]', | 
					
						
							| 
									
										
										
										
											2017-02-17 19:31:21 -07:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2019-08-14 11:53:51 -04:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2020-11-20 16:06:26 -05:00
										 |  |  | 			done: plugins.hooks.hasListeners('filter:search.query'), | 
					
						
							| 
									
										
										
										
											2020-05-29 09:59:22 -04:00
										 |  |  | 			doneText: '[[admin/dashboard:search-plugin-installed]]', | 
					
						
							|  |  |  | 			notDoneText: '[[admin/dashboard:search-plugin-not-installed]]', | 
					
						
							|  |  |  | 			tooltip: '[[admin/dashboard:search-plugin-tooltip]]', | 
					
						
							| 
									
										
										
										
											2019-08-14 11:53:51 -04:00
										 |  |  | 			link: '/admin/extend/plugins', | 
					
						
							| 
									
										
										
										
											2017-06-22 19:03:49 -04:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2019-08-14 11:53:51 -04:00
										 |  |  | 	]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (global.env !== 'production') { | 
					
						
							|  |  |  | 		notices.push({ | 
					
						
							|  |  |  | 			done: false, | 
					
						
							| 
									
										
										
										
											2020-05-29 09:59:22 -04:00
										 |  |  | 			notDoneText: '[[admin/dashboard:running-in-development]]', | 
					
						
							| 
									
										
										
										
											2019-08-14 11:53:51 -04:00
										 |  |  | 		}); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-20 16:06:26 -05:00
										 |  |  | 	return await plugins.hooks.fire('filter:admin.notices', notices); | 
					
						
							| 
									
										
										
										
											2019-08-14 11:53:51 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | async function getLatestVersion() { | 
					
						
							|  |  |  | 	try { | 
					
						
							| 
									
										
										
										
											2020-06-20 23:32:12 -04:00
										 |  |  | 		return await versions.getLatestVersion(); | 
					
						
							| 
									
										
										
										
											2019-08-14 11:53:51 -04:00
										 |  |  | 	} catch (err) { | 
					
						
							| 
									
										
										
										
											2021-02-03 23:59:08 -07:00
										 |  |  | 		winston.error(`[acp] Failed to fetch latest version\n${err.stack}`); | 
					
						
							| 
									
										
										
										
											2019-08-14 11:53:51 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return null; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-09-17 16:25:15 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-28 14:59:55 -04:00
										 |  |  | 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; | 
					
						
							| 
									
										
										
										
											2021-02-03 23:59:08 -07:00
										 |  |  | 	let payload = await Promise.all(sets.map(set => method(`analytics:${set}`, until, count))); | 
					
						
							| 
									
										
										
										
											2019-06-28 14:59:55 -04:00
										 |  |  | 	payload = _.zipObject(sets, payload); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	res.json({ | 
					
						
							|  |  |  | 		query: { | 
					
						
							|  |  |  | 			set: req.query.set, | 
					
						
							|  |  |  | 			units: req.query.units, | 
					
						
							|  |  |  | 			until: until, | 
					
						
							|  |  |  | 			count: count, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		result: payload, | 
					
						
							|  |  |  | 	}); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 11:53:51 -04:00
										 |  |  | async function getStats() { | 
					
						
							| 
									
										
										
										
											2019-08-21 01:20:02 -04:00
										 |  |  | 	const cache = require('../../cache'); | 
					
						
							|  |  |  | 	const cachedStats = cache.get('admin:stats'); | 
					
						
							|  |  |  | 	if (cachedStats !== undefined) { | 
					
						
							|  |  |  | 		return cachedStats; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-22 13:23:20 -05:00
										 |  |  | 	let results = await Promise.all([ | 
					
						
							| 
									
										
										
										
											2019-08-14 11:53:51 -04:00
										 |  |  | 		getStatsForSet('ip:recent', 'uniqueIPCount'), | 
					
						
							| 
									
										
										
										
											2021-02-22 13:23:20 -05:00
										 |  |  | 		getStatsFromAnalytics('logins', 'loginCount'), | 
					
						
							| 
									
										
										
										
											2019-08-14 11:53:51 -04:00
										 |  |  | 		getStatsForSet('users:joindate', 'userCount'), | 
					
						
							|  |  |  | 		getStatsForSet('posts:pid', 'postCount'), | 
					
						
							|  |  |  | 		getStatsForSet('topics:tid', 'topicCount'), | 
					
						
							|  |  |  | 	]); | 
					
						
							| 
									
										
										
										
											2020-05-29 09:59:22 -04:00
										 |  |  | 	results[0].name = '[[admin/dashboard:unique-visitors]]'; | 
					
						
							| 
									
										
										
										
											2021-02-22 16:37:17 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-22 11:38:26 -05:00
										 |  |  | 	results[1].name = '[[admin/dashboard:logins]]'; | 
					
						
							| 
									
										
										
										
											2021-02-22 16:37:17 -05:00
										 |  |  | 	results[1].href = `${nconf.get('relative_path')}/admin/dashboard/logins`; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-22 11:38:26 -05:00
										 |  |  | 	results[2].name = '[[admin/dashboard:new-users]]'; | 
					
						
							| 
									
										
										
										
											2021-02-22 16:37:17 -05:00
										 |  |  | 	results[2].href = `${nconf.get('relative_path')}/admin/dashboard/users`; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-22 11:38:26 -05:00
										 |  |  | 	results[3].name = '[[admin/dashboard:posts]]'; | 
					
						
							| 
									
										
										
										
											2021-02-22 16:37:17 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-22 11:38:26 -05:00
										 |  |  | 	results[4].name = '[[admin/dashboard:topics]]'; | 
					
						
							| 
									
										
										
										
											2021-02-22 16:37:17 -05:00
										 |  |  | 	results[4].href = `${nconf.get('relative_path')}/admin/dashboard/topics`; | 
					
						
							| 
									
										
										
										
											2021-02-22 13:23:20 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	({ results } = await plugins.hooks.fire('filter:admin.getStats', { | 
					
						
							|  |  |  | 		results, | 
					
						
							|  |  |  | 		helpers: { getStatsForSet, getStatsFromAnalytics }, | 
					
						
							|  |  |  | 	})); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-21 01:20:02 -04:00
										 |  |  | 	cache.set('admin:stats', results, 600000); | 
					
						
							| 
									
										
										
										
											2019-08-14 11:53:51 -04:00
										 |  |  | 	return results; | 
					
						
							| 
									
										
										
										
											2015-09-17 16:25:15 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 11:53:51 -04:00
										 |  |  | async function getStatsForSet(set, field) { | 
					
						
							|  |  |  | 	const terms = { | 
					
						
							| 
									
										
										
										
											2015-09-17 16:25:15 -04:00
										 |  |  | 		day: 86400000, | 
					
						
							|  |  |  | 		week: 604800000, | 
					
						
							| 
									
										
										
										
											2017-02-17 19:31:21 -07:00
										 |  |  | 		month: 2592000000, | 
					
						
							| 
									
										
										
										
											2015-09-17 16:25:15 -04:00
										 |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 11:53:51 -04:00
										 |  |  | 	const now = Date.now(); | 
					
						
							| 
									
										
										
										
											2019-08-21 00:25:38 -04:00
										 |  |  | 	const results = await utils.promiseParallel({ | 
					
						
							| 
									
										
										
										
											2019-08-21 01:30:00 -04:00
										 |  |  | 		yesterday: db.sortedSetCount(set, now - (terms.day * 2), '+inf'), | 
					
						
							| 
									
										
										
										
											2019-08-21 00:25:38 -04:00
										 |  |  | 		today: db.sortedSetCount(set, now - terms.day, '+inf'), | 
					
						
							| 
									
										
										
										
											2019-08-21 01:30:00 -04:00
										 |  |  | 		lastweek: db.sortedSetCount(set, now - (terms.week * 2), '+inf'), | 
					
						
							| 
									
										
										
										
											2019-08-21 00:25:38 -04:00
										 |  |  | 		thisweek: db.sortedSetCount(set, now - terms.week, '+inf'), | 
					
						
							| 
									
										
										
										
											2019-08-21 01:30:00 -04:00
										 |  |  | 		lastmonth: db.sortedSetCount(set, now - (terms.month * 2), '+inf'), | 
					
						
							| 
									
										
										
										
											2019-08-21 00:25:38 -04:00
										 |  |  | 		thismonth: db.sortedSetCount(set, now - terms.month, '+inf'), | 
					
						
							| 
									
										
										
										
											2019-08-14 11:53:51 -04:00
										 |  |  | 		alltime: getGlobalField(field), | 
					
						
							|  |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2019-08-21 01:20:02 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-22 13:23:20 -05:00
										 |  |  | 	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)), | 
					
						
							| 
									
										
										
										
											2021-02-24 12:28:08 -05:00
										 |  |  | 		today: data.slice(-1)[0], | 
					
						
							| 
									
										
										
										
											2021-02-22 13:23:20 -05:00
										 |  |  | 		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) { | 
					
						
							| 
									
										
										
										
											2019-08-21 00:25:38 -04:00
										 |  |  | 	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); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-08-21 01:30:00 -04:00
										 |  |  | 	results.yesterday -= results.today; | 
					
						
							| 
									
										
										
										
											2019-08-21 00:25:38 -04:00
										 |  |  | 	results.dayIncrease = increasePercent(results.yesterday, results.today); | 
					
						
							|  |  |  | 	results.dayTextClass = textClass(results.dayIncrease); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-21 01:30:00 -04:00
										 |  |  | 	results.lastweek -= results.thisweek; | 
					
						
							| 
									
										
										
										
											2019-08-21 00:25:38 -04:00
										 |  |  | 	results.weekIncrease = increasePercent(results.lastweek, results.thisweek); | 
					
						
							|  |  |  | 	results.weekTextClass = textClass(results.weekIncrease); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-21 01:30:00 -04:00
										 |  |  | 	results.lastmonth -= results.thismonth; | 
					
						
							| 
									
										
										
										
											2019-08-21 00:25:38 -04:00
										 |  |  | 	results.monthIncrease = increasePercent(results.lastmonth, results.thismonth); | 
					
						
							|  |  |  | 	results.monthTextClass = textClass(results.monthIncrease); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return results; | 
					
						
							| 
									
										
										
										
											2015-09-17 16:25:15 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 11:53:51 -04:00
										 |  |  | async function getGlobalField(field) { | 
					
						
							|  |  |  | 	const count = await db.getObjectField('global', field); | 
					
						
							|  |  |  | 	return parseInt(count, 10) || 0; | 
					
						
							| 
									
										
										
										
											2015-09-17 16:25:15 -04:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-05-02 13:38:15 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 11:53:51 -04:00
										 |  |  | 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; | 
					
						
							| 
									
										
										
										
											2018-05-02 13:38:15 -04:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2021-02-22 16:37:17 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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, | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-24 11:22:44 -05:00
										 |  |  | 	// 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); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-22 16:37:17 -05:00
										 |  |  | 	res.render('admin/dashboard/logins', { | 
					
						
							|  |  |  | 		set: 'logins', | 
					
						
							| 
									
										
										
										
											2021-02-22 17:06:28 -05:00
										 |  |  | 		query: req.query, | 
					
						
							| 
									
										
										
										
											2021-02-22 16:37:17 -05:00
										 |  |  | 		stats, | 
					
						
							|  |  |  | 		summary, | 
					
						
							| 
									
										
										
										
											2021-02-24 11:22:44 -05:00
										 |  |  | 		sessions, | 
					
						
							|  |  |  | 		loginDays: meta.config.loginDays, | 
					
						
							| 
									
										
										
										
											2021-02-22 16:37:17 -05:00
										 |  |  | 	}); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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, | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-24 10:01:54 -05:00
										 |  |  | 	// List of users registered within time frame
 | 
					
						
							| 
									
										
										
										
											2021-02-22 20:49:52 -05:00
										 |  |  | 	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); | 
					
						
							| 
									
										
										
										
											2021-02-24 12:28:08 -05:00
										 |  |  | 	const users = await user.getUsersData(uids); | 
					
						
							| 
									
										
										
										
											2021-02-22 17:06:28 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-22 16:37:17 -05:00
										 |  |  | 	res.render('admin/dashboard/users', { | 
					
						
							|  |  |  | 		set: 'registrations', | 
					
						
							| 
									
										
										
										
											2021-02-22 17:06:28 -05:00
										 |  |  | 		query: req.query, | 
					
						
							| 
									
										
										
										
											2021-02-22 16:37:17 -05:00
										 |  |  | 		stats, | 
					
						
							|  |  |  | 		summary, | 
					
						
							| 
									
										
										
										
											2021-02-22 20:49:52 -05:00
										 |  |  | 		users, | 
					
						
							| 
									
										
										
										
											2021-02-22 16:37:17 -05:00
										 |  |  | 	}); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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, | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-24 10:01:54 -05:00
										 |  |  | 	// 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); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-22 16:37:17 -05:00
										 |  |  | 	res.render('admin/dashboard/topics', { | 
					
						
							|  |  |  | 		set: 'topics', | 
					
						
							| 
									
										
										
										
											2021-02-22 17:06:28 -05:00
										 |  |  | 		query: req.query, | 
					
						
							| 
									
										
										
										
											2021-02-22 16:37:17 -05:00
										 |  |  | 		stats, | 
					
						
							|  |  |  | 		summary, | 
					
						
							| 
									
										
										
										
											2021-02-24 10:01:54 -05:00
										 |  |  | 		topics: topicData, | 
					
						
							| 
									
										
										
										
											2021-02-22 16:37:17 -05:00
										 |  |  | 	}); | 
					
						
							|  |  |  | }; |