2020-10-31 13:33:59 -07:00
|
|
|
import { Router } from 'express';
|
|
|
|
import SQL from 'sql-template-strings';
|
2020-11-02 12:12:15 -08:00
|
|
|
import avatar from '../avatar';
|
2020-11-02 12:45:45 -08:00
|
|
|
import {config as socialLoginConfig} from "../social";
|
2021-06-17 16:10:59 -07:00
|
|
|
import {buildDict, now, shuffle, handleErrorAsync, buildLocaleList} from "../../src/helpers";
|
2021-01-12 11:06:59 -08:00
|
|
|
import locales from '../../src/locales';
|
2021-06-09 23:45:13 -07:00
|
|
|
import {calculateStats, statsFile} from '../../src/stats';
|
|
|
|
import fs from 'fs';
|
2021-07-02 16:15:44 -07:00
|
|
|
import { caches } from "../../src/cache";
|
2020-10-31 13:33:59 -07:00
|
|
|
|
|
|
|
const router = Router();
|
|
|
|
|
2021-06-09 05:47:08 -07:00
|
|
|
router.get('/admin/list', handleErrorAsync(async (req, res) => {
|
2021-07-02 16:15:44 -07:00
|
|
|
return res.json(await caches.admins.fetch(async () => {
|
2021-06-17 14:29:47 -07:00
|
|
|
const admins = await req.db.all(SQL`
|
2021-11-23 06:05:14 -08:00
|
|
|
SELECT u.username, p.teamName, p.locale, u.id, u.email, u.avatarSource, p.credentials, p.credentialsLevel, p.credentialsName, a.payload
|
2021-06-17 14:29:47 -07:00
|
|
|
FROM users u
|
2021-11-23 06:05:14 -08:00
|
|
|
LEFT JOIN profiles p ON p.userId = u.id
|
|
|
|
LEFT JOIN authenticators a ON u.id = a.userId AND a.type = u.avatarSource AND (a.validUntil IS NULL OR a.validUntil > ${now()})
|
2021-06-17 14:29:47 -07:00
|
|
|
WHERE p.teamName IS NOT NULL
|
|
|
|
AND p.teamName != ''
|
|
|
|
ORDER BY RANDOM()
|
|
|
|
`);
|
2021-01-12 11:06:59 -08:00
|
|
|
|
2021-06-17 14:29:47 -07:00
|
|
|
const adminsGroupped = buildDict(function* () {
|
2021-06-17 16:10:59 -07:00
|
|
|
yield [global.config.locale, []];
|
2021-06-17 14:29:47 -07:00
|
|
|
for (let [locale, , , published] of locales) {
|
2021-06-17 16:10:59 -07:00
|
|
|
if (locale !== global.config.locale && published) {
|
2021-06-17 14:29:47 -07:00
|
|
|
yield [locale, []];
|
|
|
|
}
|
2021-01-12 11:06:59 -08:00
|
|
|
}
|
2021-06-17 14:29:47 -07:00
|
|
|
yield ['', []];
|
|
|
|
});
|
|
|
|
for (let admin of admins) {
|
|
|
|
admin.avatar = await avatar(req.db, admin);
|
|
|
|
delete admin.id;
|
|
|
|
delete admin.email;
|
2021-11-23 06:05:14 -08:00
|
|
|
delete admin.payload;
|
2021-08-26 05:25:59 -07:00
|
|
|
if (admin.credentials) {
|
|
|
|
admin.credentials = admin.credentials.split('|');
|
|
|
|
}
|
2021-01-12 11:06:59 -08:00
|
|
|
|
2021-06-17 14:29:47 -07:00
|
|
|
if (adminsGroupped[admin.locale] !== undefined) {
|
|
|
|
adminsGroupped[admin.locale].push(admin);
|
|
|
|
} else {
|
|
|
|
adminsGroupped[''].push(admin);
|
|
|
|
}
|
2021-01-12 11:06:59 -08:00
|
|
|
}
|
|
|
|
|
2021-06-17 14:29:47 -07:00
|
|
|
return adminsGroupped;
|
|
|
|
}));
|
2021-06-09 05:47:08 -07:00
|
|
|
}));
|
2021-01-12 11:06:59 -08:00
|
|
|
|
2021-06-09 05:47:08 -07:00
|
|
|
router.get('/admin/list/footer', handleErrorAsync(async (req, res) => {
|
2021-07-02 16:15:44 -07:00
|
|
|
return res.json(shuffle(await caches.adminsFooter.fetch(async () => {
|
2021-06-17 14:29:47 -07:00
|
|
|
const fromDb = await req.db.all(SQL`
|
|
|
|
SELECT u.username, p.footerName, p.footerAreas, p.locale
|
|
|
|
FROM users u
|
|
|
|
LEFT JOIN profiles p ON p.userId = u.id
|
2021-06-17 16:10:59 -07:00
|
|
|
WHERE p.locale = ${global.config.locale}
|
2021-06-17 14:29:47 -07:00
|
|
|
AND p.footerName IS NOT NULL AND p.footerName != ''
|
|
|
|
AND p.footerAreas IS NOT NULL AND p.footerAreas != ''
|
|
|
|
`);
|
2021-04-06 11:48:44 -07:00
|
|
|
|
2021-06-17 16:10:59 -07:00
|
|
|
const fromConfig = global.config.contact.authors || [];
|
2021-04-06 11:48:44 -07:00
|
|
|
|
2021-06-17 14:29:47 -07:00
|
|
|
return [...fromDb, ...fromConfig];
|
|
|
|
})));
|
2021-06-09 05:47:08 -07:00
|
|
|
}));
|
2021-01-12 11:06:59 -08:00
|
|
|
|
2021-06-09 05:47:08 -07:00
|
|
|
router.get('/admin/users', handleErrorAsync(async (req, res) => {
|
2020-12-30 15:03:30 -08:00
|
|
|
if (!req.isGranted('users')) {
|
2020-10-31 13:33:59 -07:00
|
|
|
return res.status(401).json({error: 'Unauthorised'});
|
|
|
|
}
|
|
|
|
|
|
|
|
const users = await req.db.all(SQL`
|
2021-11-26 08:08:10 -08:00
|
|
|
SELECT u.id, u.username, u.email, u.roles, u.avatarSource, group_concat(p.locale) AS profiles
|
2020-10-31 13:33:59 -07:00
|
|
|
FROM users u
|
|
|
|
LEFT JOIN profiles p ON p.userId = u.id
|
2021-11-26 08:08:10 -08:00
|
|
|
GROUP BY u.id
|
2020-12-30 15:03:30 -08:00
|
|
|
ORDER BY u.id DESC
|
2020-10-31 13:33:59 -07:00
|
|
|
`);
|
|
|
|
|
2021-11-26 08:08:10 -08:00
|
|
|
return res.json(users);
|
2021-06-09 05:47:08 -07:00
|
|
|
}));
|
2020-10-31 13:33:59 -07:00
|
|
|
|
2021-06-09 05:47:08 -07:00
|
|
|
router.get('/admin/stats', handleErrorAsync(async (req, res) => {
|
2020-12-30 15:03:30 -08:00
|
|
|
if (!req.isGranted('panel')) {
|
2020-11-24 15:54:02 -08:00
|
|
|
return res.status(401).json({error: 'Unauthorised'});
|
|
|
|
}
|
|
|
|
|
2021-06-09 23:45:13 -07:00
|
|
|
const stats = fs.existsSync(statsFile)
|
|
|
|
? JSON.parse(fs.readFileSync(statsFile))
|
2021-06-17 16:10:59 -07:00
|
|
|
: await calculateStats(req.db, buildLocaleList(global.config.locale));
|
2020-11-27 11:30:21 -08:00
|
|
|
|
2021-06-09 23:45:13 -07:00
|
|
|
for (let locale in stats.locales) {
|
|
|
|
if (stats.locales.hasOwnProperty(locale) && !req.isGranted('panel', locale)) {
|
|
|
|
delete stats.locales[locale];
|
2020-11-24 15:54:02 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-09 23:45:13 -07:00
|
|
|
return res.json(stats);
|
2021-06-09 05:47:08 -07:00
|
|
|
}));
|
2020-11-24 15:54:02 -08:00
|
|
|
|
2021-06-16 07:08:38 -07:00
|
|
|
const normalise = s => s.trim().toLowerCase();
|
|
|
|
|
|
|
|
router.post('/admin/ban/:username', handleErrorAsync(async (req, res) => {
|
|
|
|
if (!req.isGranted('users')) {
|
|
|
|
return res.status(401).json({error: 'Unauthorised'});
|
|
|
|
}
|
|
|
|
|
2021-07-24 10:43:17 -07:00
|
|
|
const user = await req.db.get(SQL`SELECT id FROM users WHERE usernameNorm = ${normalise(req.params.username)}`);
|
|
|
|
if (!user) {
|
|
|
|
return res.status(400).json({error: 'No such user'});
|
|
|
|
}
|
|
|
|
|
2021-08-12 03:14:34 -07:00
|
|
|
if (req.body.reason) {
|
|
|
|
if (!req.body.terms.length) {
|
|
|
|
return res.status(400).json({error: 'Terms are required'});
|
|
|
|
}
|
|
|
|
await req.db.get(SQL`
|
|
|
|
UPDATE users
|
|
|
|
SET bannedReason = ${req.body.reason},
|
|
|
|
bannedTerms = ${req.body.terms.join(',')},
|
|
|
|
bannedBy = ${req.user.id}
|
|
|
|
WHERE id = ${user.id}
|
|
|
|
`);
|
|
|
|
} else {
|
|
|
|
await req.db.get(SQL`
|
|
|
|
UPDATE users
|
|
|
|
SET bannedReason = null
|
|
|
|
WHERE id = ${user.id}
|
|
|
|
`);
|
|
|
|
}
|
2021-07-24 10:43:17 -07:00
|
|
|
|
|
|
|
await req.db.get(SQL`
|
|
|
|
UPDATE reports
|
|
|
|
SET isHandled = 1
|
|
|
|
WHERE userId = ${user.id}
|
2021-06-16 07:08:38 -07:00
|
|
|
`);
|
|
|
|
|
|
|
|
return res.json(true);
|
|
|
|
}));
|
|
|
|
|
2021-07-24 10:18:39 -07:00
|
|
|
router.get('/admin/reports', handleErrorAsync(async (req, res) => {
|
2021-06-16 07:48:24 -07:00
|
|
|
if (!req.isGranted('users')) {
|
|
|
|
return res.status(401).json({error: 'Unauthorised'});
|
|
|
|
}
|
|
|
|
|
|
|
|
return res.json(await req.db.all(SQL`
|
2021-07-24 10:18:39 -07:00
|
|
|
SELECT reports.id, sus.username AS susUsername, reporter.username AS reporterUsername, reports.comment, reports.isAutomatic, reports.isHandled
|
|
|
|
FROM reports
|
|
|
|
LEFT JOIN users sus ON reports.userId = sus.id
|
|
|
|
LEFT JOIN users reporter ON reports.reporterId = reporter.id
|
2021-08-24 23:56:36 -07:00
|
|
|
ORDER BY reports.isHandled ASC, reports.id DESC
|
2021-06-16 07:48:24 -07:00
|
|
|
`));
|
|
|
|
}));
|
|
|
|
|
2021-07-24 10:18:39 -07:00
|
|
|
router.post('/admin/reports/handle/:id', handleErrorAsync(async (req, res) => {
|
2021-06-16 07:48:24 -07:00
|
|
|
if (!req.isGranted('users')) {
|
|
|
|
return res.status(401).json({error: 'Unauthorised'});
|
|
|
|
}
|
|
|
|
|
|
|
|
await req.db.get(SQL`
|
2021-07-24 10:18:39 -07:00
|
|
|
UPDATE reports
|
|
|
|
SET isHandled = 1
|
2021-06-16 07:48:24 -07:00
|
|
|
WHERE id=${req.params.id}
|
|
|
|
`);
|
|
|
|
|
|
|
|
return res.json(true);
|
|
|
|
}));
|
|
|
|
|
2020-10-31 13:33:59 -07:00
|
|
|
export default router;
|