This repository has been archived on 2024-07-22. You can view files and clone it, but cannot push or open issues or pull requests.
Zaimki/server/routes/admin.js

185 lines
6.1 KiB
JavaScript
Raw Normal View History

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";
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();
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`
SELECT u.username, p.teamName, p.locale, u.id, u.email, u.avatarSource
FROM users u
LEFT JOIN profiles p ON p.userId = u.id
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* () {
yield [global.config.locale, []];
2021-06-17 14:29:47 -07:00
for (let [locale, , , published] of locales) {
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-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-01-12 11:06:59 -08: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
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
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-01-12 11:06:59 -08: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'});
}
2021-06-03 01:28:53 -07:00
return res.json({});
2020-10-31 13:33:59 -07:00
const users = await req.db.all(SQL`
2020-11-02 12:12:15 -08:00
SELECT u.id, u.username, u.email, u.roles, u.avatarSource, p.locale
2020-10-31 13:33:59 -07:00
FROM users u
LEFT JOIN profiles p ON p.userId = u.id
2020-12-30 15:03:30 -08:00
ORDER BY u.id DESC
2020-10-31 13:33:59 -07:00
`);
2020-11-02 12:45:45 -08:00
const authenticators = await req.db.all(SQL`
SELECT userId, type FROM authenticators
WHERE type IN (`.append(Object.keys(socialLoginConfig).map(k => `'${k}'`).join(',')).append(SQL`)
AND (validUntil IS NULL OR validUntil > ${now()})
`));
2020-10-31 13:33:59 -07:00
const groupedUsers = {};
for (let user of users) {
if (groupedUsers[user.id] === undefined) {
groupedUsers[user.id] = {
...user,
locale: undefined,
profiles: user.locale ? [user.locale] : [],
2020-11-02 12:12:15 -08:00
avatar: await avatar(req.db, user),
2020-11-02 12:45:45 -08:00
socialConnections: [],
2020-10-31 13:33:59 -07:00
}
} else {
groupedUsers[user.id].profiles.push(user.locale);
}
}
2020-11-02 12:45:45 -08:00
for (let auth of authenticators) {
groupedUsers[auth.userId].socialConnections.push(auth.type);
}
2020-10-31 13:33:59 -07:00
return res.json(groupedUsers);
}));
2020-10-31 13:33:59 -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))
: 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);
}));
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'});
}
await req.db.get(SQL`
UPDATE users
SET bannedReason = ${req.body.reason || null}
WHERE lower(trim(replace(replace(replace(replace(replace(replace(replace(replace(replace(username, 'Ą', 'ą'), 'Ć', 'ć'), 'Ę', 'ę'), 'Ł', 'ł'), 'Ń', 'ń'), 'Ó', 'ó'), 'Ś', 'ś'), 'Ż', 'ż'), 'Ź', 'ż'))) = ${normalise(req.params.username)}
`);
return res.json(true);
}));
2021-06-16 07:48:24 -07:00
router.get('/admin/suspicious', handleErrorAsync(async (req, res) => {
if (!req.isGranted('users')) {
return res.status(401).json({error: 'Unauthorised'});
}
return res.json(await req.db.all(SQL`
SELECT users.id, users.username, profiles.locale FROM profiles
LEFT JOIN users ON profiles.userId = users.id
WHERE users.suspiciousChecked != 1
AND users.bannedReason IS NULL
AND (
lower(customFlags) LIKE '%super%'
OR lower(description) LIKE '%super%'
OR lower(customFlags) LIKE '%phobe%'
OR lower(description) LIKE '%phobe%'
2021-06-23 08:24:16 -07:00
OR lower(customFlags) LIKE '%phobic%'
OR lower(description) LIKE '%phobic%'
OR lower(customFlags) LIKE '%terf%'
OR lower(description) LIKE '%terf%'
OR lower(customFlags) LIKE '%radfem%'
OR lower(description) LIKE '%radfem%'
OR lower(customFlags) LIKE '%gender critical%'
OR lower(description) LIKE '%gender critical%'
2021-06-16 07:48:24 -07:00
)
ORDER BY users.id DESC
`));
}));
router.post('/admin/suspicious/checked/:id', handleErrorAsync(async (req, res) => {
if (!req.isGranted('users')) {
return res.status(401).json({error: 'Unauthorised'});
}
await req.db.get(SQL`
UPDATE users
SET suspiciousChecked = 1
WHERE id=${req.params.id}
`);
return res.json(true);
}));
2020-10-31 13:33:59 -07:00
export default router;