#215 better server error handling - server

This commit is contained in:
Andrea Vos 2021-06-09 17:47:08 +02:00
parent 17be34029d
commit 53b2cc68a2
14 changed files with 123 additions and 108 deletions

View File

@ -54,6 +54,11 @@ app.use(require('./routes/census').default);
app.use(require('./routes/images').default);
app.use(function (err, req, res, next) {
console.error(err.stack);
res.status(500).send('Unexpected server error');
});
export default {
path: '/api',
handler: app,

View File

@ -2,13 +2,13 @@ import { Router } from 'express';
import SQL from 'sql-template-strings';
import avatar from '../avatar';
import {config as socialLoginConfig} from "../social";
import {buildDict, now, shuffle, sortByValue} from "../../src/helpers";
import {buildDict, now, shuffle, sortByValue, handleErrorAsync} from "../../src/helpers";
import locales from '../../src/locales';
import {decodeTime} from "ulid";
const router = Router();
router.get('/admin/list', async (req, res) => {
router.get('/admin/list', handleErrorAsync(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
@ -39,9 +39,9 @@ router.get('/admin/list', async (req, res) => {
}
return res.json(adminsGroupped);
});
}));
router.get('/admin/list/footer', async (req, res) => {
router.get('/admin/list/footer', handleErrorAsync(async (req, res) => {
const fromDb = await req.db.all(SQL`
SELECT u.username, p.footerName, p.footerAreas, p.locale
FROM users u
@ -54,9 +54,9 @@ router.get('/admin/list/footer', async (req, res) => {
const fromConfig = req.config.contact.authors || [];
return res.json(shuffle([...fromDb, ...fromConfig]));
});
}));
router.get('/admin/users', async (req, res) => {
router.get('/admin/users', handleErrorAsync(async (req, res) => {
if (!req.isGranted('users')) {
return res.status(401).json({error: 'Unauthorised'});
}
@ -96,7 +96,7 @@ router.get('/admin/users', async (req, res) => {
}
return res.json(groupedUsers);
});
}));
const formatMonth = d => `${d.getFullYear()}-${(d.getMonth() + 1).toString().padStart(2, '0')}-${d.getDate().toString().padStart(2, '0')}`;
@ -120,7 +120,7 @@ const buildChart = (rows) => {
return chart;
}
router.get('/admin/stats', async (req, res) => {
router.get('/admin/stats', handleErrorAsync(async (req, res) => {
if (!req.isGranted('panel')) {
return res.status(401).json({error: 'Unauthorised'});
}
@ -177,6 +177,6 @@ router.get('/admin/stats', async (req, res) => {
}
return res.json({ users, locales });
});
}));
export default router;

View File

@ -5,6 +5,7 @@ import { loadSuml } from '../loader';
import avatar from '../avatar';
import {buildPronoun, parsePronouns} from "../../src/buildPronoun";
import {loadTsv} from "../../src/tsv";
import {handleErrorAsync} from "../../src/helpers";
const translations = loadSuml('translations');
@ -26,7 +27,7 @@ const drawCircle = (context, image, x, y, size) => {
const router = Router();
router.get('/banner/:pronounName*.png', async (req, res) => {
router.get('/banner/:pronounName*.png', handleErrorAsync(async (req, res) => {
const pronounName = req.params.pronounName + req.params[0];
const width = 1200
const height = 600
@ -97,6 +98,6 @@ router.get('/banner/:pronounName*.png', async (req, res) => {
context.fillText(pronounNameOptions.join('\n'), width / leftRatio + imageSize / 1.5, height / 2 + (pronounNameOptions.length <= 2 ? 72 : 24))
return res.set('content-type', mime).send(canvas.toBuffer(mime));
});
}));
export default router;

View File

@ -3,6 +3,7 @@ import SQL from 'sql-template-strings';
import sha1 from 'sha1';
import {ulid} from "ulid";
import Papa from 'papaparse';
import {handleErrorAsync} from "../../src/helpers";
const getIp = req => {
try {
@ -42,11 +43,11 @@ const hasFinished = async req => {
const router = Router();
router.get('/census/finished', async (req, res) => {
router.get('/census/finished', handleErrorAsync(async (req, res) => {
return res.json(await hasFinished(req));
});
}));
router.post('/census/submit', async (req, res) => {
router.post('/census/submit', handleErrorAsync(async (req, res) => {
const suspicious = await hasFinished(req);
const id = ulid();
@ -65,17 +66,17 @@ router.post('/census/submit', async (req, res) => {
)`);
return res.json(id);
});
}));
router.get('/census/count', async (req, res) => {
router.get('/census/count', handleErrorAsync(async (req, res) => {
return res.json((await req.db.get(SQL`
SELECT COUNT(*) as c FROM census
WHERE locale = ${req.config.locale}
AND edition = ${req.config.census.edition}
`)).c);
});
}));
router.get('/census/export', async (req, res) => {
router.get('/census/export', handleErrorAsync(async (req, res) => {
if (!req.isGranted('census')) {
res.status(401).json({error: 'Unauthorised'});
}
@ -110,6 +111,6 @@ router.get('/census/export', async (req, res) => {
}
return res.set('content-type', 'text/csv').send(Papa.unparse(report));
});
}));
export default router;

View File

@ -2,6 +2,7 @@ import { Router } from 'express';
import {ulid} from "ulid";
import multer from 'multer';
import {loadImage, createCanvas} from 'canvas';
import {handleErrorAsync} from "../../src/helpers";
import awsConfig from '../aws';
import S3 from 'aws-sdk/clients/s3';
@ -43,7 +44,7 @@ const scaleDownTo = (image, size) => {
const router = Router();
router.post('/images/upload', multer({limits: {fileSize: 10 * 1024 * 1024}}).any('images[]', 12), async (req, res) => {
router.post('/images/upload', multer({limits: {fileSize: 10 * 1024 * 1024}}).any('images[]', 12), handleErrorAsync(async (req, res) => {
const s3 = new S3(awsConfig);
const ids = [];
@ -75,6 +76,6 @@ router.post('/images/upload', multer({limits: {fileSize: 10 * 1024 * 1024}}).any
ids.push(id);
}
return res.json(ids);
});
}));
export default router;

View File

@ -1,7 +1,7 @@
import { Router } from 'express';
import SQL from 'sql-template-strings';
import {ulid} from "ulid";
import {isTroll} from "../../src/helpers";
import {isTroll, handleErrorAsync} from "../../src/helpers";
const approve = async (db, id) => {
const { base_id } = await db.get(SQL`SELECT base_id FROM inclusive WHERE id=${id}`);
@ -21,7 +21,7 @@ const approve = async (db, id) => {
const router = Router();
router.get('/inclusive', async (req, res) => {
router.get('/inclusive', handleErrorAsync(async (req, res) => {
return res.json(await req.db.all(SQL`
SELECT i.*, u.username AS author FROM inclusive i
LEFT JOIN users u ON i.author_id = u.id
@ -30,9 +30,9 @@ router.get('/inclusive', async (req, res) => {
AND i.deleted = 0
ORDER BY i.approved, i.insteadOf
`));
});
}));
router.get('/inclusive/search/:term', async (req, res) => {
router.get('/inclusive/search/:term', handleErrorAsync(async (req, res) => {
const term = '%' + req.params.term + '%';
return res.json(await req.db.all(SQL`
SELECT i.*, u.username AS author FROM inclusive i
@ -43,9 +43,9 @@ router.get('/inclusive/search/:term', async (req, res) => {
AND (i.insteadOf like ${term} OR i.say like ${term})
ORDER BY i.approved, i.insteadOf
`));
});
}));
router.post('/inclusive/submit', async (req, res) => {
router.post('/inclusive/submit', handleErrorAsync(async (req, res) => {
if (!(req.user && req.user.admin) && isTroll(JSON.stringify(req.body))) {
return res.json('ok');
}
@ -66,9 +66,9 @@ router.post('/inclusive/submit', async (req, res) => {
}
return res.json('ok');
});
}));
router.post('/inclusive/hide/:id', async (req, res) => {
router.post('/inclusive/hide/:id', handleErrorAsync(async (req, res) => {
if (!req.isGranted('inclusive')) {
res.status(401).json({error: 'Unauthorised'});
}
@ -80,9 +80,9 @@ router.post('/inclusive/hide/:id', async (req, res) => {
`);
return res.json('ok');
});
}));
router.post('/inclusive/approve/:id', async (req, res) => {
router.post('/inclusive/approve/:id', handleErrorAsync(async (req, res) => {
if (!req.isGranted('inclusive')) {
res.status(401).json({error: 'Unauthorised'});
}
@ -90,9 +90,9 @@ router.post('/inclusive/approve/:id', async (req, res) => {
await approve(req.db, req.params.id);
return res.json('ok');
});
}));
router.post('/inclusive/remove/:id', async (req, res) => {
router.post('/inclusive/remove/:id', handleErrorAsync(async (req, res) => {
if (!req.isGranted('inclusive')) {
res.status(401).json({error: 'Unauthorised'});
}
@ -104,6 +104,6 @@ router.post('/inclusive/remove/:id', async (req, res) => {
`);
return res.json('ok');
});
}));
export default router;

View File

@ -3,7 +3,7 @@ import SQL from 'sql-template-strings';
import {ulid} from "ulid";
import {createCanvas, loadImage, registerFont} from "canvas";
import {loadSuml} from "../loader";
import {buildDict, isTroll} from "../../src/helpers";
import {handleErrorAsync, isTroll} from "../../src/helpers";
const translations = loadSuml('translations');
@ -68,7 +68,7 @@ const selectFragment = (sourcesMap, keyAndFragment) => {
const router = Router();
router.get('/nouns', async (req, res) => {
router.get('/nouns', handleErrorAsync(async (req, res) => {
return res.json(await addVersions(req, await req.db.all(SQL`
SELECT n.*, u.username AS author FROM nouns n
LEFT JOIN users u ON n.author_id = u.id
@ -77,9 +77,9 @@ router.get('/nouns', async (req, res) => {
AND n.approved >= ${req.isGranted('nouns') ? 0 : 1}
ORDER BY n.approved, n.masc
`)));
});
}));
router.get('/nouns/search/:term', async (req, res) => {
router.get('/nouns/search/:term', handleErrorAsync(async (req, res) => {
const term = '%' + req.params.term + '%';
return res.json(await addVersions(req, await req.db.all(SQL`
SELECT n.*, u.username AS author FROM nouns n
@ -90,9 +90,9 @@ router.get('/nouns/search/:term', async (req, res) => {
AND (n.masc like ${term} OR n.fem like ${term} OR n.neutr like ${term} OR n.mascPl like ${term} OR n.femPl like ${term} OR n.neutrPl like ${term})
ORDER BY n.approved, n.masc
`)));
});
}));
router.post('/nouns/submit', async (req, res) => {
router.post('/nouns/submit', handleErrorAsync(async (req, res) => {
if (!(req.user && req.user.admin) && isTroll(JSON.stringify(req.body))) {
return res.json('ok');
}
@ -114,9 +114,9 @@ router.post('/nouns/submit', async (req, res) => {
}
return res.json('ok');
});
}));
router.post('/nouns/hide/:id', async (req, res) => {
router.post('/nouns/hide/:id', handleErrorAsync(async (req, res) => {
if (!req.isGranted('nouns')) {
res.status(401).json({error: 'Unauthorised'});
}
@ -128,9 +128,9 @@ router.post('/nouns/hide/:id', async (req, res) => {
`);
return res.json('ok');
});
}));
router.post('/nouns/approve/:id', async (req, res) => {
router.post('/nouns/approve/:id', handleErrorAsync(async (req, res) => {
if (!req.isGranted('nouns')) {
res.status(401).json({error: 'Unauthorised'});
}
@ -138,9 +138,9 @@ router.post('/nouns/approve/:id', async (req, res) => {
await approve(req.db, req.params.id);
return res.json('ok');
});
}));
router.post('/nouns/remove/:id', async (req, res) => {
router.post('/nouns/remove/:id', handleErrorAsync(async (req, res) => {
if (!req.isGranted('nouns')) {
res.status(401).json({error: 'Unauthorised'});
}
@ -152,7 +152,7 @@ router.post('/nouns/remove/:id', async (req, res) => {
`);
return res.json('ok');
});
}));
const findBaseForm = (noun, query) => {
for (let form of ['masc', 'fem', 'neutr', 'mascPl', 'femPl', 'neutrPl']) {
@ -166,7 +166,7 @@ const findBaseForm = (noun, query) => {
return null;
}
router.get('/nouns/:word.png', async (req, res) => {
router.get('/nouns/:word.png', handleErrorAsync(async (req, res) => {
const query = req.params.word.toLowerCase();
const term = '%' + query + '%';
const noun = (await req.db.all(SQL`
@ -233,6 +233,6 @@ router.get('/nouns/:word.png', async (req, res) => {
context.fillText(translations.title, padding + 48, height - padding - 4);
return res.set('content-type', mime).send(canvas.toBuffer(mime));
});
}));
export default router;

View File

@ -3,6 +3,7 @@ import SQL from 'sql-template-strings';
import md5 from "js-md5";
import {ulid} from "ulid";
import avatar from "../avatar";
import {handleErrorAsync} from "../../src/helpers";
const normalise = s => s.trim().toLowerCase();
@ -58,11 +59,11 @@ const fetchProfiles = async (db, username, self) => {
const router = Router();
router.get('/profile/get/:username', async (req, res) => {
router.get('/profile/get/:username', handleErrorAsync(async (req, res) => {
return res.json(await fetchProfiles(req.db, req.params.username, req.user && req.user.username === req.params.username))
});
}));
router.post('/profile/save', async (req, res) => {
router.post('/profile/save', handleErrorAsync(async (req, res) => {
if (!req.user) {
return res.status(401).json({error: 'Unauthorised'});
}
@ -97,12 +98,12 @@ router.post('/profile/save', async (req, res) => {
}
return res.json(await fetchProfiles(req.db, req.user.username, true));
});
}));
router.post('/profile/delete/:locale', async (req, res) => {
router.post('/profile/delete/:locale', handleErrorAsync(async (req, res) => {
await req.db.get(SQL`DELETE FROM profiles WHERE userId = ${req.user.id} AND locale = ${req.params.locale}`);
return res.json(await fetchProfiles(req.db, req.user.username, true));
});
}));
export default router;

View File

@ -3,6 +3,7 @@ import { loadTsv } from '../loader';
import {buildPronoun, parsePronouns} from "../../src/buildPronoun";
import {Example} from "../../src/classes";
import sha1 from 'sha1';
import {handleErrorAsync} from "../../src/helpers";
import awsConfig from '../aws';
import Polly from 'aws-sdk/clients/polly';
@ -10,7 +11,7 @@ import S3 from 'aws-sdk/clients/s3';
const router = Router();
router.get('/pronounce/:voice/:pronoun*', async (req, res) => {
router.get('/pronounce/:voice/:pronoun*', handleErrorAsync(async (req, res) => {
const pronounString = req.params.pronoun + req.params[0];
const pronoun = buildPronoun(
parsePronouns(loadTsv('pronouns/pronouns')),
@ -65,6 +66,6 @@ router.get('/pronounce/:voice/:pronoun*', async (req, res) => {
return res.set('content-type', pollyResponse.ContentType).send(pollyResponse.AudioStream);
}
});
}));
export default router;

View File

@ -1,7 +1,7 @@
import { Router } from 'express';
import { loadTsv } from '../loader';
import {buildPronoun, parsePronouns} from "../../src/buildPronoun";
import {buildList} from "../../src/helpers";
import {buildList, handleErrorAsync} from "../../src/helpers";
import {Example} from "../../src/classes";
const buildExample = e => new Example(
@ -33,16 +33,16 @@ const addExamples = (pronoun, examples) => {
const router = Router();
router.get('/pronouns', async (req, res) => {
router.get('/pronouns', handleErrorAsync(async (req, res) => {
const pronouns = parsePronouns(loadTsv('pronouns/pronouns'));
for (let pronoun in pronouns) {
if (!pronouns.hasOwnProperty(pronoun)) { continue; }
pronouns[pronoun].examples = addExamples(pronouns[pronoun], requestExamples(req.query.examples))
}
return res.json(pronouns);
});
}));
router.get('/pronouns/:pronoun*', async (req, res) => {
router.get('/pronouns/:pronoun*', handleErrorAsync(async (req, res) => {
const pronoun = buildPronoun(
parsePronouns(loadTsv('pronouns/pronouns')),
req.params.pronoun + req.params[0],
@ -51,6 +51,6 @@ router.get('/pronouns/:pronoun*', async (req, res) => {
pronoun.examples = addExamples(pronoun, requestExamples(req.query.examples))
}
return res.json(pronoun);
});
}));
export default router;

View File

@ -1,6 +1,7 @@
import { Router } from 'express';
import SQL from "sql-template-strings";
import {ulid} from "ulid";
import {handleErrorAsync} from "../../src/helpers";
const approve = async (db, id) => {
const { base_id } = await db.get(SQL`SELECT base_id FROM sources WHERE id=${id}`);
@ -46,7 +47,7 @@ const linkOtherVersions = async (req, sources) => {
const router = Router();
router.get('/sources', async (req, res) => {
router.get('/sources', handleErrorAsync(async (req, res) => {
let sql = SQL`
SELECT s.*, u.username AS submitter FROM sources s
LEFT JOIN users u ON s.submitter_id = u.id
@ -58,9 +59,9 @@ router.get('/sources', async (req, res) => {
sql.append(SQL`AND s.pronouns LIKE ${'%' + req.query.pronoun + '%'}`)
}
return res.json(await linkOtherVersions(req, await req.db.all(sql)));
});
}));
router.get('/sources/:id', async (req, res) => {
router.get('/sources/:id', handleErrorAsync(async (req, res) => {
return res.json(await linkOtherVersions(req, await req.db.all(SQL`
SELECT s.*, u.username AS submitter FROM sources s
LEFT JOIN users u ON s.submitter_id = u.id
@ -69,9 +70,9 @@ router.get('/sources/:id', async (req, res) => {
AND s.approved >= ${req.isGranted('sources') ? 0 : 1}
AND s.id = ${req.params.id}
`)));
});
}));
router.post('/sources/submit', async (req, res) => {
router.post('/sources/submit', handleErrorAsync(async (req, res) => {
const id = ulid();
await req.db.get(SQL`
INSERT INTO sources (id, locale, pronouns, type, author, title, extra, year, fragments, comment, link, key, images, submitter_id, base_id)
@ -89,9 +90,9 @@ router.post('/sources/submit', async (req, res) => {
}
return res.json('ok');
});
}));
router.post('/sources/hide/:id', async (req, res) => {
router.post('/sources/hide/:id', handleErrorAsync(async (req, res) => {
if (!req.isGranted('sources')) {
res.status(401).json({error: 'Unauthorised'});
}
@ -103,9 +104,9 @@ router.post('/sources/hide/:id', async (req, res) => {
`);
return res.json('ok');
});
}));
router.post('/sources/approve/:id', async (req, res) => {
router.post('/sources/approve/:id', handleErrorAsync(async (req, res) => {
if (!req.isGranted('sources')) {
res.status(401).json({error: 'Unauthorised'});
}
@ -113,9 +114,9 @@ router.post('/sources/approve/:id', async (req, res) => {
await approve(req.db, req.params.id);
return res.json('ok');
});
}));
router.post('/sources/remove/:id', async (req, res) => {
router.post('/sources/remove/:id', handleErrorAsync(async (req, res) => {
if (!req.isGranted('sources')) {
res.status(401).json({error: 'Unauthorised'});
}
@ -127,6 +128,6 @@ router.post('/sources/remove/:id', async (req, res) => {
`);
return res.json('ok');
});
}));
export default router;

View File

@ -1,7 +1,7 @@
import { Router } from 'express';
import SQL from 'sql-template-strings';
import {ulid} from "ulid";
import {isTroll} from "../../src/helpers";
import {isTroll, handleErrorAsync} from "../../src/helpers";
const approve = async (db, id) => {
const { base_id } = await db.get(SQL`SELECT base_id FROM terms WHERE id=${id}`);
@ -21,7 +21,7 @@ const approve = async (db, id) => {
const router = Router();
router.get('/terms', async (req, res) => {
router.get('/terms', handleErrorAsync(async (req, res) => {
return res.json(await req.db.all(SQL`
SELECT i.*, u.username AS author FROM terms i
LEFT JOIN users u ON i.author_id = u.id
@ -30,9 +30,9 @@ router.get('/terms', async (req, res) => {
AND i.deleted = 0
ORDER BY i.term
`));
});
}));
router.get('/terms/search/:term', async (req, res) => {
router.get('/terms/search/:term', handleErrorAsync(async (req, res) => {
const term = '%' + req.params.term + '%';
return res.json(await req.db.all(SQL`
SELECT i.*, u.username AS author FROM terms i
@ -43,9 +43,9 @@ router.get('/terms/search/:term', async (req, res) => {
AND (i.term like ${term} OR i.original like ${term})
ORDER BY i.term
`));
});
}));
router.post('/terms/submit', async (req, res) => {
router.post('/terms/submit', handleErrorAsync(async (req, res) => {
if (!(req.user && req.user.admin) && isTroll(JSON.stringify(req.body))) {
return res.json('ok');
}
@ -66,9 +66,9 @@ router.post('/terms/submit', async (req, res) => {
}
return res.json('ok');
});
}));
router.post('/terms/hide/:id', async (req, res) => {
router.post('/terms/hide/:id', handleErrorAsync(async (req, res) => {
if (!req.isGranted('terms')) {
res.status(401).json({error: 'Unauthorised'});
}
@ -80,9 +80,9 @@ router.post('/terms/hide/:id', async (req, res) => {
`);
return res.json('ok');
});
}));
router.post('/terms/approve/:id', async (req, res) => {
router.post('/terms/approve/:id', handleErrorAsync(async (req, res) => {
if (!req.isGranted('terms')) {
res.status(401).json({error: 'Unauthorised'});
}
@ -90,9 +90,9 @@ router.post('/terms/approve/:id', async (req, res) => {
await approve(req.db, req.params.id);
return res.json('ok');
});
}));
router.post('/terms/remove/:id', async (req, res) => {
router.post('/terms/remove/:id', handleErrorAsync(async (req, res) => {
if (!req.isGranted('terms')) {
res.status(401).json({error: 'Unauthorised'});
}
@ -104,6 +104,6 @@ router.post('/terms/remove/:id', async (req, res) => {
`);
return res.json('ok');
});
}));
export default router;

View File

@ -1,7 +1,7 @@
import { Router } from 'express';
import SQL from 'sql-template-strings';
import {ulid} from "ulid";
import {buildDict, makeId, now} from "../../src/helpers";
import {buildDict, makeId, now, handleErrorAsync} from "../../src/helpers";
import jwt from "../../src/jwt";
import mailer from "../../src/mailer";
import { loadSuml } from '../loader';
@ -174,7 +174,7 @@ const router = Router();
router.use(reloadUser);
router.post('/user/init', async (req, res) => {
router.post('/user/init', handleErrorAsync(async (req, res) => {
let user = undefined;
let usernameOrEmail = req.body.usernameOrEmail;
@ -232,9 +232,9 @@ router.post('/user/init', async (req, res) => {
return res.json({
token: jwt.sign({...payload, code: null, codeKey}, '15m'),
});
});
}));
router.post('/user/validate', async (req, res) => {
router.post('/user/validate', handleErrorAsync(async (req, res) => {
if (!req.rawUser || !req.rawUser.codeKey) {
return res.json({error: 'user.tokenExpired'});
}
@ -251,9 +251,9 @@ router.post('/user/validate', async (req, res) => {
await invalidateAuthenticator(req.db, authenticator);
return res.json({token: await issueAuthentication(req.db, req.rawUser)});
});
}));
router.post('/user/change-username', async (req, res) => {
router.post('/user/change-username', handleErrorAsync(async (req, res) => {
if (!req.user) {
return res.status(401).json({error: 'Unauthorised'});
}
@ -270,9 +270,9 @@ router.post('/user/change-username', async (req, res) => {
await req.db.get(SQL`UPDATE users SET username = ${req.body.username} WHERE id = ${req.user.id}`);
return res.json({token: await issueAuthentication(req.db, req.user)});
});
}));
router.post('/user/change-email', async (req, res) => {
router.post('/user/change-email', handleErrorAsync(async (req, res) => {
if (!req.user) {
return res.status(401).json({error: 'Unauthorised'});
}
@ -319,9 +319,9 @@ router.post('/user/change-email', async (req, res) => {
req.user.email = authenticator.payload.to;
return res.json({token: await issueAuthentication(req.db, req.user)});
});
}));
router.post('/user/delete', async (req, res) => {
router.post('/user/delete', handleErrorAsync(async (req, res) => {
if (!req.user) {
return res.status(401).json({error: 'Unauthorised'});
}
@ -331,9 +331,9 @@ router.post('/user/delete', async (req, res) => {
await req.db.get(SQL`DELETE FROM users WHERE id = ${req.user.id}`)
return res.json(true);
});
}));
router.post('/user/:id/set-roles', async (req, res) => {
router.post('/user/:id/set-roles', handleErrorAsync(async (req, res) => {
if (!req.isGranted('*')) {
return res.status(401).json({error: 'Unauthorised'});
}
@ -341,9 +341,9 @@ router.post('/user/:id/set-roles', async (req, res) => {
await req.db.get(SQL`UPDATE users SET roles = ${req.body.roles} WHERE id = ${req.params.id}`);
return res.json('ok');
});
}));
router.get('/user/social/:provider', async (req, res) => {
router.get('/user/social/:provider', handleErrorAsync(async (req, res) => {
if (!req.session.grant || !req.session.grant.response || !req.session.grant.response.access_token || !socialLoginHandlers[req.params.provider]) {
return res.status(400).redirect('/' + config.user.route);
}
@ -382,9 +382,9 @@ router.get('/user/social/:provider', async (req, res) => {
await saveAuthenticator(req.db, req.params.provider, dbUser, payload);
return res.cookie('token', token).redirect('/' + config.user.route);
});
}));
router.get('/user/social-connections', async (req, res) => {
router.get('/user/social-connections', handleErrorAsync(async (req, res) => {
if (!req.user) {
return res.status(401).json({error: 'Unauthorised'});
}
@ -401,9 +401,9 @@ router.get('/user/social-connections', async (req, res) => {
yield [auth.type, JSON.parse(auth.payload)];
}
}));
});
}));
router.post('/user/social-connection/:provider/disconnect', async (req, res) => {
router.post('/user/social-connection/:provider/disconnect', handleErrorAsync(async (req, res) => {
if (!req.user) {
return res.status(401).json({error: 'Unauthorised'});
}
@ -418,9 +418,9 @@ router.post('/user/social-connection/:provider/disconnect', async (req, res) =>
await invalidateAuthenticator(req.db, auth.id)
return res.json('ok');
});
}));
router.post('/user/set-avatar', async (req, res) => {
router.post('/user/set-avatar', handleErrorAsync(async (req, res) => {
if (!req.user) {
return res.status(401).json({error: 'Unauthorised'});
}
@ -432,6 +432,6 @@ router.post('/user/set-avatar', async (req, res) => {
`)
return res.json({token: await issueAuthentication(req.db, req.user)});
});
}));
export default router;

View File

@ -200,3 +200,7 @@ export const isGranted = (user, locale, area) => {
return false;
}
export const handleErrorAsync = func => (req, res, next) => {
func(req, res, next).catch((error) => next(error));
};