Recv/lib/api/admin.js

387 lines
9.1 KiB
JavaScript

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 ExpirationUnits = require('../expirationunits');
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 (config.code.maxExpiration !== null)
{
let now = new Date();
if (ExpirationUnits.apply(postedCode.expiration) > ExpirationUnits.apply(config.code.maxExpiration))
{
res.sendStatus(400);
return;
}
}
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,
created: postedCode.created || new Date(),
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);
});
}));
router.get('/expiration', asyncHandler(async (req, res) =>
{
await checkAuthorization(req, res, repository, async (user) =>
{
res.send({
max: config.code.maxExpiration,
default: config.code.defaultExpiration
});
});
}));
/*
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;
}
await repository.uploads.delete(upload.id);
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;
}