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

183 lines
6.0 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";
2021-04-06 11:48:44 -07:00
import {buildDict, now, shuffle, sortByValue} from "../../src/helpers";
2021-01-12 11:06:59 -08:00
import locales from '../../src/locales';
2021-04-08 15:43:57 -07:00
import {decodeTime} from "ulid";
2020-10-31 13:33:59 -07:00
const router = Router();
2021-01-12 11:06:59 -08:00
router.get('/admin/list', async (req, res) => {
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()
`);
const adminsGroupped = buildDict(function*() {
yield [req.config.locale, []];
for (let [locale, , , published] of locales) {
if (locale !== req.config.locale && published) {
yield [locale, []];
}
}
yield ['', []];
});
for (let admin of admins) {
admin.avatar = await avatar(req.db, admin);
delete admin.id;
delete admin.email;
if (adminsGroupped[admin.locale] !== undefined) {
adminsGroupped[admin.locale].push(admin);
} else {
adminsGroupped[''].push(admin);
}
}
return res.json(adminsGroupped);
});
router.get('/admin/list/footer', async (req, res) => {
2021-04-06 11:48:44 -07:00
const fromDb = await req.db.all(SQL`
2021-01-12 11:06:59 -08:00
SELECT u.username, p.footerName, p.footerAreas, p.locale
FROM users u
LEFT JOIN profiles p ON p.userId = u.id
WHERE p.locale = ${req.config.locale}
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 = req.config.contact.authors || [];
return res.json(shuffle([...fromDb, ...fromConfig]));
2021-01-12 11:06:59 -08:00
});
2020-10-31 13:33:59 -07:00
router.get('/admin/users', 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);
});
2021-04-08 15:43:57 -07:00
const formatMonth = d => `${d.getFullYear()}-${(d.getMonth() + 1).toString().padStart(2, '0')}-${d.getDate().toString().padStart(2, '0')}`;
const buildChart = (rows) => {
const dates = rows.map(row => new Date(decodeTime(row.id)));
const chart = {};
let loop = dates[0];
const end = dates[dates.length - 1];
while(loop <= end){
chart[formatMonth(loop)] = 0;
loop = new Date(loop.setDate(loop.getDate() + 1));
}
chart[formatMonth(loop)] = 0;
for (let date of dates) {
chart[formatMonth(date)]++;
}
return chart;
}
2020-11-24 15:54:02 -08:00
router.get('/admin/stats', 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'});
}
const users = {
overall: (await req.db.get(SQL`SELECT count(*) AS c FROM users`)).c,
2020-12-30 15:03:30 -08:00
admins: (await req.db.get(SQL`SELECT count(*) AS c FROM users WHERE roles!=''`)).c,
2021-04-08 15:43:57 -07:00
chart: buildChart(await req.db.all(SQL`SELECT id FROM users ORDER BY id`)),
2020-11-24 15:54:02 -08:00
};
const locales = {};
for (let locale in req.locales) {
if (!req.locales.hasOwnProperty(locale)) { continue; }
2020-12-30 15:03:30 -08:00
if (!req.isGranted('panel', locale)) { continue; }
2020-11-27 11:30:21 -08:00
const profiles = await req.db.all(SQL`SELECT pronouns, flags FROM profiles WHERE locale=${locale}`);
2020-11-24 15:54:02 -08:00
const pronouns = {}
2020-11-27 11:30:21 -08:00
const flags = {}
2020-11-24 15:54:02 -08:00
for (let profile of profiles) {
const pr = JSON.parse(profile.pronouns);
for (let pronoun in pr) {
if (!pr.hasOwnProperty(pronoun)) { continue; }
if (pronoun.includes(',') || pr[pronoun] < 0) {
continue;
}
const p = pronoun.replace(/^.*:\/\//, '').replace(/^\//, '').toLowerCase().replace(/^[a-z]+\.[^/]+\//, '');
if (pronouns[p] === undefined) {
pronouns[p] = 0;
}
pronouns[p] += pr[pronoun] === 1 ? 1 : 0.5;
2020-11-24 15:54:02 -08:00
}
2020-11-27 11:30:21 -08:00
const fl = JSON.parse(profile.flags);
for (let flag of fl) {
if (flags[flag] === undefined) {
flags[flag] = 0;
}
flags[flag] += 1;
}
2020-11-24 15:54:02 -08:00
}
locales[locale] = {
name: req.locales[locale].name,
url: req.locales[locale].url,
profiles: profiles.length,
pronouns: sortByValue(pronouns, true),
2020-11-27 11:30:21 -08:00
flags: sortByValue(flags, true),
2020-11-24 15:54:02 -08:00
nouns: {
approved: (await req.db.get(SQL`SELECT count(*) AS c FROM nouns WHERE locale=${locale} AND approved=1 AND deleted=0`)).c,
awaiting: (await req.db.get(SQL`SELECT count(*) AS c FROM nouns WHERE locale=${locale} AND approved=0 AND deleted=0`)).c,
2021-04-08 15:43:57 -07:00
},
chart: buildChart(await req.db.all(SQL`SELECT id FROM profiles WHERE locale=${locale} ORDER BY id`)),
2020-11-24 15:54:02 -08:00
};
}
return res.json({ users, locales });
});
2020-10-31 13:33:59 -07:00
export default router;