Listing management (#223)

* upgrading dependencies, fixing image placeholder

* improving processing times label and hide when screen width is too low

* aligning run now button

* renaming settings -> general settings

* smaller security and memory improvements

* improving footer

* preparing listing management

* improve filtering for listings

* preparing new settings page

* preparing new settings page

* storing settings in db

* next release version
This commit is contained in:
Christian Kellner
2025-12-09 13:56:46 +01:00
committed by GitHub
parent 5cfa674d7f
commit 3e5cd97400
30 changed files with 656 additions and 282 deletions

View File

@@ -1,10 +1,11 @@
import restana from 'restana';
import { config } from '../../utils.js';
import { getSettings } from '../../services/storage/settingsStorage.js';
const service = restana();
const demoRouter = service.newRouter();
demoRouter.get('/', async (req, res) => {
res.body = Object.assign({}, { demoMode: config.demoMode });
const settings = await getSettings();
res.body = Object.assign({}, { demoMode: settings.demoMode });
res.send();
});

View File

@@ -0,0 +1,12 @@
import restana from 'restana';
import getFeatures from '../../features.js';
const service = restana();
const featureRouter = service.newRouter();
featureRouter.get('/', async (req, res) => {
const features = getFeatures();
res.body = Object.assign({}, { features });
res.send();
});
export { featureRouter };

View File

@@ -1,24 +1,30 @@
import restana from 'restana';
import { config, getDirName, readConfigFromStorage, refreshConfig } from '../../utils.js';
import { getDirName } from '../../utils.js';
import fs from 'fs';
import { ensureDemoUserExists } from '../../services/storage/userStorage.js';
import logger from '../../services/logger.js';
import { getSettings, upsertSettings } from '../../services/storage/settingsStorage.js';
const service = restana();
const generalSettingsRouter = service.newRouter();
generalSettingsRouter.get('/', async (req, res) => {
res.body = Object.assign({}, config);
res.body = Object.assign({}, await getSettings());
res.send();
});
generalSettingsRouter.post('/', async (req, res) => {
const settings = req.body;
const { sqlitepath, ...appSettings } = req.body || {};
const localSettings = await getSettings();
if (localSettings.demoMode) {
res.send(new Error('In demo mode, it is not allowed to change these settings.'));
return;
}
try {
if (config.demoMode) {
res.send(new Error('In demo mode, it is not allowed to change these settings.'));
return;
if (typeof sqlitepath !== 'undefined') {
fs.writeFileSync(`${getDirName()}/../conf/config.json`, JSON.stringify({ sqlitepath }));
}
const currentConfig = await readConfigFromStorage();
fs.writeFileSync(`${getDirName()}/../conf/config.json`, JSON.stringify({ ...currentConfig, ...settings }));
await refreshConfig();
upsertSettings(appSettings);
ensureDemoUserExists();
} catch (err) {
logger.error(err);

View File

@@ -1,10 +1,10 @@
import restana from 'restana';
import * as jobStorage from '../../services/storage/jobStorage.js';
import * as userStorage from '../../services/storage/userStorage.js';
import { config } from '../../utils.js';
import { isAdmin } from '../security.js';
import logger from '../../services/logger.js';
import { bus } from '../../services/events/event-bus.js';
import { getSettings } from '../../services/storage/settingsStorage.js';
const service = restana();
const jobRouter = service.newRouter();
@@ -44,9 +44,10 @@ jobRouter.get('/', async (req, res) => {
});
jobRouter.get('/processingTimes', async (req, res) => {
const settings = await getSettings();
res.body = {
interval: config.interval,
lastRun: config.lastRun || null,
interval: settings.interval,
lastRun: settings.lastRun || null,
};
res.send();
});

View File

@@ -1,9 +1,9 @@
import restana from 'restana';
import * as userStorage from '../../services/storage/userStorage.js';
import * as hasher from '../../services/security/hash.js';
import { config } from '../../utils.js';
import { trackDemoAccessed } from '../../services/tracking/Tracker.js';
import logger from '../../services/logger.js';
import { getSettings } from '../../services/storage/settingsStorage.js';
const service = restana();
const loginRouter = service.newRouter();
loginRouter.get('/user', async (req, res) => {
@@ -20,6 +20,7 @@ loginRouter.get('/user', async (req, res) => {
res.send();
});
loginRouter.post('/', async (req, res) => {
const settings = await getSettings();
const { username, password } = req.body;
const user = userStorage.getUsers(true).find((user) => user.username === username);
if (user == null) {
@@ -27,7 +28,7 @@ loginRouter.post('/', async (req, res) => {
return;
}
if (user.password === hasher.hash(password)) {
if (config.demoMode) {
if (settings.demoMode) {
await trackDemoAccessed();
}

View File

@@ -1,7 +1,7 @@
import restana from 'restana';
import * as userStorage from '../../services/storage/userStorage.js';
import * as jobStorage from '../../services/storage/jobStorage.js';
import { config } from '../../utils.js';
import { getSettings } from '../../services/storage/settingsStorage.js';
const service = restana();
const userRouter = service.newRouter();
function checkIfAnyAdminAfterRemovingUser(userIdToBeRemoved, allUser) {
@@ -23,7 +23,8 @@ userRouter.get('/:userId', async (req, res) => {
res.send();
});
userRouter.delete('/', async (req, res) => {
if (config.demoMode) {
const settings = await getSettings();
if (settings.demoMode) {
res.send(new Error('In demo mode, it is not allowed to remove user.'));
return;
}
@@ -44,7 +45,8 @@ userRouter.delete('/', async (req, res) => {
res.send();
});
userRouter.post('/', async (req, res) => {
if (config.demoMode) {
const settings = await getSettings();
if (settings.demoMode) {
res.send(new Error('In demo mode, it is not allowed to change or add user.'));
return;
}