mStream/src/api/admin.js
IrosTheBeggar 31f42c6e56 write logs
2021-01-12 01:54:19 -05:00

473 lines
13 KiB
JavaScript

const path = require('path');
const Joi = require('joi');
const fileExplorer = require('../util/file-explorer');
const admin = require('../util/admin');
const config = require('../state/config');
const dbQueue = require('../db/task-queue');
const winston = require('winston');
exports.setup = (mstream) => {
// The admin file explorer can view the entire system
mstream.post("/api/v1/admin/file-explorer", async (req, res) => {
try {
const schema = Joi.object({
directory: Joi.string().required(),
joinDirectory: Joi.string().optional()
});
await schema.validateAsync(req.body);
}catch (err) {
return res.status(500).json({ error: 'Validation Error' });
}
try {
// Handle home directory
let thisDirectory = req.body.directory;
if (req.body.directory === '~') {
thisDirectory = require('os').homedir();
}
if (req.body.joinDirectory) {
thisDirectory = path.join(thisDirectory, req.body.joinDirectory);
}
const folderContents = await fileExplorer.getDirectoryContents(thisDirectory, {}, true);
res.json({
path: thisDirectory,
directories: folderContents.directories,
files: folderContents.files
});
}catch (err) {
console.log(err);
return res.status(500).json({ error: 'Failed to get directory contents' });
}
});
mstream.get("/api/v1/admin/directories", async (req, res) => {
try {
res.json(config.program.folders);
} catch (err) {
console.log(err)
return res.status(500).json({ error: 'Failed to get vpaths' });
}
});
mstream.get("/api/v1/admin/db/params", async (req, res) => {
try {
res.json(config.program.scanOptions);
} catch (err) {
console.log(err)
return res.status(500).json({ error: 'Failed to get scan options' });
}
});
mstream.post("/api/v1/admin/db/params/scan-interval", async (req, res) => {
try {
const schema = Joi.object({
scanInterval: Joi.number().integer().min(0).required()
});
await schema.validateAsync(req.body);
}catch (err) {
return res.status(500).json({ error: 'Validation Error' });
}
try {
await admin.editScanInterval(req.body.scanInterval);
res.json({});
} catch (err) {
console.log(err);
return res.status(500).json({ error: 'Failed' });
}
});
mstream.post("/api/v1/admin/db/params/save-interval", async (req, res) => {
try {
const schema = Joi.object({
saveInterval: Joi.number().integer().min(0).required()
});
await schema.validateAsync(req.body);
}catch (err) {
return res.status(500).json({ error: 'Validation Error' });
}
try {
await admin.editSaveInterval(req.body.saveInterval);
res.json({});
} catch (err) {
console.log(err);
return res.status(500).json({ error: 'Failed' });
}
});
mstream.post("/api/v1/admin/db/params/skip-img", async (req, res) => {
try {
const schema = Joi.object({
skipImg: Joi.boolean().required()
});
await schema.validateAsync(req.body);
}catch (err) {
return res.status(500).json({ error: 'Validation Error' });
}
try {
await admin.editSkipImg(req.body.skipImg);
res.json({});
} catch (err) {
console.log(err);
return res.status(500).json({ error: 'Failed' });
}
});
mstream.post("/api/v1/admin/db/params/pause", async (req, res) => {
try {
const schema = Joi.object({
pause: Joi.number().integer().min(0).required()
});
await schema.validateAsync(req.body);
}catch (err) {
return res.status(500).json({ error: 'Validation Error' });
}
try {
await admin.editPause(req.body.pause);
res.json({});
} catch (err) {
console.log(err);
return res.status(500).json({ error: 'Failed' });
}
});
mstream.post("/api/v1/admin/db/params/boot-scan-delay", async (req, res) => {
try {
const schema = Joi.object({
bootScanDelay: Joi.number().integer().min(0).required()
});
await schema.validateAsync(req.body);
}catch (err) {
return res.status(500).json({ error: 'Validation Error' });
}
try {
await admin.editBootScanDelay(req.body.bootScanDelay);
res.json({});
} catch (err) {
console.log(err);
return res.status(500).json({ error: 'Failed' });
}
});
mstream.post("/api/v1/admin/db/params/max-concurrent-scans", async (req, res) => {
try {
const schema = Joi.object({
maxConcurrentTasks: Joi.number().integer().min(0).required()
});
await schema.validateAsync(req.body);
}catch (err) {
return res.status(500).json({ error: 'Validation Error' });
}
try {
await admin.editMaxConcurrentTasks(req.body.maxConcurrentTasks);
res.json({});
} catch (err) {
console.log(err);
return res.status(500).json({ error: 'Failed' });
}
});
mstream.get("/api/v1/admin/users", async (req, res) => {
try {
// Scrub passwords
const memClone = JSON.parse(JSON.stringify(config.program.users));
Object.keys(memClone).forEach(key => {
if(key === 'password' || key === 'salt') {
delete memClone[key];
}
});
res.json(memClone);
} catch (err) {
console.log(err)
return res.status(500).json({ error: 'Failed to get vpaths' });
}
});
mstream.put("/api/v1/admin/directory", async (req, res) => {
try {
const schema = Joi.object({
directory: Joi.string().required(),
vpath: Joi.string().pattern(/[a-zA-Z0-9-]+/).required(),
autoAccess: Joi.boolean().default(false)
});
var input = await schema.validateAsync(req.body);
}catch (err) {
console.log(err)
return res.status(500).json({ error: 'Validation Error' });
}
try {
await admin.addDirectory(input.directory, input.vpath, input.autoAccess, mstream);
res.json({});
} catch (err) {
console.log(err)
return res.status(500).json({ error: 'Failed to set new directory' });
}
try {
dbQueue.scanVPath(input.vpath);
}catch (err) {
winston.error('/api/v1/admin/directory failed to add ', { stack: err });
}
});
mstream.delete("/api/v1/admin/directory", async (req, res) => {
try {
const schema = Joi.object({
vpath: Joi.string().pattern(/[a-zA-Z0-9-]+/).required()
});
await schema.validateAsync(req.body);
}catch (err) {
console.log(err)
return res.status(500).json({ error: 'Validation Error' });
}
try {
await admin.removeDirectory(req.body.vpath);
res.json({});
} catch (err) {
console.log(err)
return res.status(500).json({ error: 'Failed to set new directory' });
}
});
mstream.put("/api/v1/admin/users", async (req, res) => {
try {
const schema = Joi.object({
username: Joi.string().required(),
password: Joi.string().required(),
vpaths: Joi.array().items(Joi.string()).required(),
admin: Joi.boolean().optional().default(false),
guest: Joi.boolean().optional().default(false)
});
var input = await schema.validateAsync(req.body);
}catch (err) {
console.log(err)
return res.status(500).json({ error: 'Validation Error' });
}
try {
await admin.addUser(
input.username,
input.password,
input.admin,
input.guest,
input.vpaths
);
res.json({});
} catch (err) {
console.log(err)
return res.status(500).json({ error: 'Failed to set new directory' });
}
});
mstream.post("/api/v1/admin/db/scan/all", async (req, res) => {
try {
dbQueue.scanAll();
res.json({});
} catch(err) {
res.status(500).json({});
}
});
mstream.delete("/api/v1/admin/users", async (req, res) => {
try {
const schema = Joi.object({
username: Joi.string().required()
});
await schema.validateAsync(req.body);
}catch (err) {
return res.status(500).json({ error: 'Validation Error' });
}
try {
await admin.deleteUser(req.body.username);
res.json({});
} catch (err) {
console.log(err)
return res.status(500).json({ error: 'Failed to delete user' });
}
});
mstream.post("/api/v1/admin/users/password", async (req, res) => {
try {
const schema = Joi.object({
username: Joi.string().required(),
password: Joi.string().required()
});
await schema.validateAsync(req.body);
}catch (err) {
return res.status(500).json({ error: 'Validation Error' });
}
try {
await admin.editUserPassword(req.body.username, req.body.password);
res.json({});
} catch (err) {
console.log(err);
return res.status(500).json({ error: 'Failed to update password' });
}
});
mstream.post("/api/v1/admin/users/vpaths", async (req, res) => {
try {
const schema = Joi.object({
username: Joi.string().required(),
vpaths: Joi.array().items(Joi.string()).required()
});
await schema.validateAsync(req.body);
}catch (err) {
return res.status(500).json({ error: 'Validation Error' });
}
try {
await admin.editUserVPaths(req.body.username, req.body.vpaths);
res.json({});
} catch (err) {
console.log(err);
return res.status(500).json({ error: 'Failed to update user' });
}
});
mstream.post("/api/v1/admin/users/access", async (req, res) => {
try {
const schema = Joi.object({
username: Joi.string().required(),
admin: Joi.boolean().required(),
guest: Joi.boolean().required()
});
await schema.validateAsync(req.body);
}catch (err) {
return res.status(500).json({ error: 'Validation Error' });
}
try {
await admin.editUserAccess(req.body.username, req.body.admin, req.body.guest);
res.json({});
} catch (err) {
console.log(err);
return res.status(500).json({ error: 'Failed to update user' });
}
});
mstream.get("/api/v1/admin/config", async (req, res) => {
try {
res.json({
address: config.program.address,
port: config.program.port,
noUpload: config.program.noUpload,
writeLogs: config.program.writeLogs,
secret: config.program.secret.slice(-4),
ssl: config.program.ssl
});
} catch (err) {
console.log(err);
return res.status(500).json({ error: 'Failed' });
}
});
mstream.post("/api/v1/admin/config/port", async (req, res) => {
try {
const schema = Joi.object({
port: Joi.number().required()
});
await schema.validateAsync(req.body);
}catch (err) {
return res.status(500).json({ error: 'Validation Error' });
}
try {
await admin.editPort(req.body.port);
res.json({});
} catch (err) {
console.log(err);
return res.status(500).json({ error: 'Failed' });
}
});
mstream.post("/api/v1/admin/config/address", async (req, res) => {
try {
const schema = Joi.object({
address: Joi.string().ip({ cidr: 'forbidden' }).required(),
});
await schema.validateAsync(req.body);
}catch (err) {
return res.status(500).json({ error: 'Validation Error' });
}
try {
await admin.editAddress(req.body.address);
res.json({});
} catch (err) {
console.log(err);
return res.status(500).json({ error: 'Failed' });
}
});
mstream.post("/api/v1/admin/config/noupload", async (req, res) => {
try {
const schema = Joi.object({
noUpload: Joi.boolean().required()
});
await schema.validateAsync(req.body);
}catch (err) {
return res.status(500).json({ error: 'Validation Error' });
}
try {
await admin.editUpload(req.body.noUpload);
res.json({});
} catch (err) {
console.log(err);
return res.status(500).json({ error: 'Failed' });
}
});
mstream.post("/api/v1/admin/config/write-logs", async (req, res) => {
try {
const schema = Joi.object({
writeLogs: Joi.boolean().required()
});
await schema.validateAsync(req.body);
}catch (err) {
return res.status(500).json({ error: 'Validation Error' });
}
try {
await admin.editWriteLogs(req.body.writeLogs);
res.json({});
} catch (err) {
console.log(err);
return res.status(500).json({ error: 'Failed' });
}
});
mstream.post("/api/v1/admin/config/secret", async (req, res) => {
try {
const schema = Joi.object({
strength: Joi.number().integer().positive().required()
});
await schema.validateAsync(req.body);
}catch (err) {
return res.status(500).json({ error: 'Validation Error' });
}
try {
const secret = await config.asyncRandom(req.body.strength);
await admin.editSecret(secret);
res.json({});
} catch (err) {
console.log(err);
return res.status(500).json({ error: 'Failed' });
}
});
}