Recv/lib/api/admin.js
Mark van Renswoude 7aa680c26d Implemented user admin API
Renamed repository methods for consistency
2018-04-28 10:18:27 +02:00

379 lines
8.9 KiB
JavaScript

const config = require('../../config');
const express = require('Express');
const asyncHandler = require('express-async-handler');
const jwt = require('jsonwebtoken');
const path = require('path');
const resolvePath = require('resolve-path');
const AuthTokens = require('../authtokens');
const disk = require('diskusage');
const fs = require('mz/fs');
async function checkAuthorization(req, res, repository, onVerified)
{
var token;
if (req.headers.authorization)
{
if (req.headers.authorization.split(' ')[0] !== 'Bearer')
{
res.sendStatus(400);
return;
}
token = req.headers.authorization.split(' ')[1];
}
else if (req.cookies && req.cookies.adminToken)
{
token = req.cookies.adminToken;
}
else
{
res.sendStatus(403);
return;
}
jwt.verify(token, config.jwtSecret, async (err, decoded) =>
{
try
{
if (err)
{
res.sendStatus(403);
return;
}
if (decoded.userId)
{
var user = await repository.users.get(decoded.userId);
if (user === null || !user.active)
{
res.sendStatus(403);
return;
}
else
await onVerified(user);
}
else
res.sendStatus(400);
}
catch (e)
{
console.log(e);
res.sendStatus(500);
}
});
}
module.exports = (repository) =>
{
var router = express.Router();
router.get('/whoami', asyncHandler(async (req, res) =>
{
await checkAuthorization(req, res, repository, async (user) =>
{
res.send({
userId: user.id,
username: user.username,
auth: user.auth
});
});
}));
router.get('/diskspace', asyncHandler(async (req, res) =>
{
await checkAuthorization(req, res, repository, async (user) =>
{
disk.check(config.fileUpload.path, (err, info) =>
{
if (err)
{
res.sendStatus(500);
return;
}
res.send(info);
});
});
}));
/*
Codes
*/
router.get('/codes', asyncHandler(async (req, res) =>
{
await checkAuthorization(req, res, repository, async (user) =>
{
var codes = await repository.codes.list(user.hasAuth(AuthTokens.ViewAllCodes) ? null : user.id);
var usernames = await repository.users.getNames();
codes.forEach((item) =>
{
item.username = usernames[item.userId];
});
res.send(codes);
});
}));
router.get('/codes/:id', asyncHandler(async (req, res) =>
{
await checkAuthorization(req, res, repository, async (user) =>
{
var code = await repository.codes.get(req.params.id);
if (code === null || (code.userId !== user.id && !user.hasAuth(AuthTokens.ViewAllCodes)))
{
res.sendStatus(404);
return;
}
var user = await repository.users.get(code.userId);
if (user !== null)
code.username = user.name;
res.send(code);
});
}));
router.post('/codes', asyncHandler(async (req, res) =>
{
await checkAuthorization(req, res, repository, async (user) =>
{
var postedCode = req.body;
if (postedCode.id)
{
var code = await repository.codes.get(postedCode.id);
if (code === null || (code.userId !== user.id && !user.hasAuth(AuthTokens.ViewAllCodes)))
{
res.sendStatus(404);
return;
}
await repository.codes.update({
id: postedCode.id,
expiration: postedCode.expiration,
description: postedCode.description,
message: postedCode.message
});
res.sendStatus(200);
}
else
{
var codeId = await repository.codes.insert({
userId: user.id,
expiration: postedCode.expiration,
description: postedCode.description,
message: postedCode.message
});
}
res.send(codeId);
});
}));
router.delete('/codes/:id', asyncHandler(async (req, res) =>
{
await checkAuthorization(req, res, repository, async (user) =>
{
var code = await repository.codes.get(req.params.id);
if (code == null || (code.userId !== user.id && !user.hasAuth(AuthTokens.ViewAllCodes)))
{
res.sendStatus(404);
return;
}
repository.codes.delete(code.id);
res.sendStatus(200);
});
}));
/*
Uploads
*/
router.get('/uploads', asyncHandler(async (req, res) =>
{
await checkAuthorization(req, res, repository, async (user) =>
{
var files = await repository.uploads.list(user.hasAuth(AuthTokens.ViewAllUploads) ? null : user.id);
var usernames = await repository.users.getNames();
var codedescriptions = await repository.codes.getDescriptions();
files.forEach((item) =>
{
item.username = item.userId !== null ? usernames[item.userId] : null;
item.codedescription = item.code !== null ? codedescriptions[item.code] : null;
});
res.send(files);
});
}));
router.delete('/uploads/:id', asyncHandler(async (req, res) =>
{
await checkAuthorization(req, res, repository, async (user) =>
{
var upload = await repository.uploads.get(req.params.id);
if (upload == null || (upload.userId !== user.id && !user.hasAuth(AuthTokens.ViewAllUploads)))
{
res.sendStatus(404);
return;
}
repository.uploads.delete(upload.id);
await Promise.all(upload.files.map(async (file) =>
{
if (!file.id) return;
if (!(await repository.uploads.fileExists(file.id)))
{
var fullpath = resolvePath(config.fileUpload.path, file.id);
try
{
await fs.unlink(fullpath);
}
catch (err)
{
console.log('Failed to delete ' + fullpath);
}
}
}));
res.sendStatus(200);
});
}));
router.get('/download/:fileid/:displayname', asyncHandler(async (req, res) =>
{
await checkAuthorization(req, res, repository, async (user) =>
{
// TODO should we check if the user has access to the file?
// for now not that important, if you know the file's UID and are logged in
var fullpath = resolvePath(config.fileUpload.path, req.params.fileid);
res.download(fullpath, req.params.displayname);
});
}));
/*
Users
*/
router.get('/users', asyncHandler(async (req, res) =>
{
await checkAuthorization(req, res, repository, async (user) =>
{
if (!user.hasAuth(AuthTokens.ManageUsers))
{
res.sendStatus(403);
return;
}
var users = await repository.users.list();
res.send(users);
});
}));
router.get('/users/:id', asyncHandler(async (req, res) =>
{
await checkAuthorization(req, res, repository, async (user) =>
{
if (req.params.id !== user.id && !user.hasAuth(AuthTokens.ManageUsers))
{
res.sendStatus(404);
return;
}
var user = await repository.users.get(req.params.id);
if (user === null)
{
res.sendStatus(404);
return;
}
res.send(user);
});
}));
router.post('/users', asyncHandler(async (req, res) =>
{
await checkAuthorization(req, res, repository, async (user) =>
{
var postedUser = req.body;
if (postedUser.id)
{
if (postedUser.id !== user.id && !user.hasAuth(AuthTokens.ManageUsers))
{
res.sendStatus(403);
return;
}
await repository.users.update({
id: postedUser.id,
username: postedUser.username,
name: postedUser.name,
password: postedUser.password,
email: postedUser.email,
auth: postedUser.auth,
active: postedUser.active
});
res.sendStatus(200);
}
else
{
if (!user.hasAuth(AuthTokens.ManageUsers))
{
res.sendStatus(403);
return;
}
var userId = await repository.users.insert({
username: postedUser.username,
name: postedUser.name,
password: postedUser.password,
email: postedUser.email,
auth: postedUser.auth,
active: postedUser.active,
createdByUserId: postedUser.createdByUserId
});
}
res.send(userId);
});
}));
router.delete('/users/:id', asyncHandler(async (req, res) =>
{
await checkAuthorization(req, res, repository, async (user) =>
{
if (!user.hasAuth(AuthTokens.ManageUsers))
{
res.sendStatus(403);
return;
}
repository.users.delete(req.params.id);
res.sendStatus(200);
});
}));
return router;
}