diff --git a/src/api/admin.js b/src/api/admin.js index ac0d086..3ce8c39 100644 --- a/src/api/admin.js +++ b/src/api/admin.js @@ -52,14 +52,128 @@ exports.setup = (mstream) => { } }); - mstream.get("/api/v1/admin/db-params", async (req, res) => { + 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 { diff --git a/src/db/task-queue.js b/src/db/task-queue.js index cb18a60..90e5b3e 100644 --- a/src/db/task-queue.js +++ b/src/db/task-queue.js @@ -102,4 +102,11 @@ exports.runAfterBoot = () => { scanIntervalTimer = setInterval(() => scanAll(), config.program.scanOptions.scanInterval * 60 * 60 * 1000); } }, config.program.scanOptions.scanDelay * 1000); +} + +exports.resetScanInterval = () => { + if (scanIntervalTimer) { clearInterval(scanIntervalTimer); } + if (config.program.scanOptions.scanInterval > 0) { + scanIntervalTimer = setInterval(() => scanAll(), config.program.scanOptions.scanInterval * 60 * 60 * 1000); + } } \ No newline at end of file diff --git a/src/state/config.js b/src/state/config.js index ccd84fd..e09d068 100644 --- a/src/state/config.js +++ b/src/state/config.js @@ -12,9 +12,9 @@ const storageJoi = Joi.object({ const scanOptions = Joi.object({ skipImg: Joi.boolean().default(false), - scanInterval: Joi.number().default(24), + scanInterval: Joi.number().min(0).default(24), saveInterval: Joi.number().default(250), - pause: Joi.number().default(0), + pause: Joi.number().min(0).default(0), bootScanDelay: Joi.number().default(3), maxConcurrentTasks: Joi.number().integer().min(1).default(1) }); diff --git a/src/util/admin.js b/src/util/admin.js index 1c7050a..dfe166a 100644 --- a/src/util/admin.js +++ b/src/util/admin.js @@ -3,6 +3,7 @@ const express = require('express'); const auth = require('./auth'); const config = require('../state/config'); const mStreamServer = require('../../mstream'); +const dbQueue = require('../db/task-queue'); exports.loadFile = async (file) => { return JSON.parse(await fs.readFile(file, 'utf-8')); @@ -196,3 +197,60 @@ exports.editSecret = async (val) => { config.program.secret = val; } + +exports.editScanInterval = async (val) => { + const loadConfig = await this.loadFile(config.configFile); + if (!loadConfig.scanOptions) { loadConfig.scanOptions = {}; } + loadConfig.scanOptions.scanInterval = val; + await this.saveFile(loadConfig, config.configFile); + + config.program.scanOptions.scanInterval = val; + + // update timer + dbQueue.resetScanInterval(); +} + +exports.editSaveInterval = async (val) => { + const loadConfig = await this.loadFile(config.configFile); + if (!loadConfig.scanOptions) { loadConfig.scanOptions = {}; } + loadConfig.scanOptions.saveInterval = val; + await this.saveFile(loadConfig, config.configFile); + + config.program.scanOptions.saveInterval = val; +} + +exports.editSkipImg = async (val) => { + const loadConfig = await this.loadFile(config.configFile); + if (!loadConfig.scanOptions) { loadConfig.scanOptions = {}; } + loadConfig.scanOptions.skipImg = val; + await this.saveFile(loadConfig, config.configFile); + + config.program.scanOptions.skipImg = val; +} + +exports.editPause = async (val) => { + const loadConfig = await this.loadFile(config.configFile); + if (!loadConfig.scanOptions) { loadConfig.scanOptions = {}; } + loadConfig.scanOptions.pause = val; + await this.saveFile(loadConfig, config.configFile); + + config.program.scanOptions.pause = val; +} + +exports.editBootScanDelay = async (val) => { + const loadConfig = await this.loadFile(config.configFile); + if (!loadConfig.scanOptions) { loadConfig.scanOptions = {}; } + loadConfig.scanOptions.bootScanDelay = val; + await this.saveFile(loadConfig, config.configFile); + + config.program.scanOptions.bootScanDelay = val; +} + +exports.editMaxConcurrentTasks = async (val) => { + const loadConfig = await this.loadFile(config.configFile); + if (!loadConfig.scanOptions) { loadConfig.scanOptions = {}; } + loadConfig.scanOptions.maxConcurrentTasks = val; + await this.saveFile(loadConfig, config.configFile); + + config.program.scanOptions.maxConcurrentTasks = val; +} diff --git a/webapp/admin/index.css b/webapp/admin/index.css index da63822..995040f 100644 --- a/webapp/admin/index.css +++ b/webapp/admin/index.css @@ -19,4 +19,8 @@ .pad-checkbox { padding-bottom: 20px; +} + +a { + cursor: pointer; } \ No newline at end of file diff --git a/webapp/admin/index.js b/webapp/admin/index.js index e4f4464..4d853ff 100644 --- a/webapp/admin/index.js +++ b/webapp/admin/index.js @@ -45,7 +45,7 @@ const ADMINDATA = (() => { module.getDbParams = async () => { const res = await API.axios({ method: 'GET', - url: `${API.url()}/api/v1/admin/db-params` + url: `${API.url()}/api/v1/admin/db/params` }); Object.keys(res.data).forEach(key=>{ @@ -611,28 +611,44 @@ const dbView = Vue.component('db-view', {
| Scan Interval: {{dbParams.scanInterval}} hours | -[info][edit] | ++ [edit] + | +
| Save Interval: {{dbParams.saveInterval}} files | ++ [edit] + | |
| Boot Scan Delay: {{dbParams.bootScanDelay}} seconds | -[info][edit] | ++ [edit] + |
| Pause Between Files: {{dbParams.pause}} milliseconds | -[info][edit] | ++ [edit] + |
| Skip Image Metadata: {{dbParams.skipImg}} | -[info][edit] | ++ [edit] + |
| Max Concurrent Scans: {{dbParams.maxConcurrentTasks}} | -[info][edit] | ++ [edit] + |