Initial commit: UOMysticmoon backend (Express + MariaDB + JWT)
- Layered API (router -> controller -> model -> db), serverlinkr pattern - Public / auth / admin route groups; posts, wiki, settings, users, activity models - JWT httpOnly-cookie auth (Secure auto-detected: LAN HTTP + Pangolin HTTPS) - Site LIVE/MAINTENANCE mode with admin preview bypass - Dual file+console logging (info/warn/error/debug) + HTTP access logs - Docker Compose (app + MariaDB), schema.sql + seed, .env.example - Verified end-to-end against MariaDB (27/27 smoke checks) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
25
server/src/model/settings/settings.db.js
Normal file
25
server/src/model/settings/settings.db.js
Normal file
@@ -0,0 +1,25 @@
|
||||
const { query } = require('../../utils/db')
|
||||
|
||||
async function getAll() {
|
||||
return query('SELECT `key`, value, updated_at FROM settings ORDER BY `key`')
|
||||
}
|
||||
|
||||
async function get(key) {
|
||||
const rows = await query('SELECT value FROM settings WHERE `key` = ? LIMIT 1', [key])
|
||||
return rows[0] ? rows[0].value : null
|
||||
}
|
||||
|
||||
async function set(key, value, updatedBy = null) {
|
||||
await query(
|
||||
'INSERT INTO settings (`key`, value, updated_by) VALUES (?, ?, ?) ' +
|
||||
'ON DUPLICATE KEY UPDATE value = VALUES(value), updated_by = VALUES(updated_by)',
|
||||
[key, value, updatedBy],
|
||||
)
|
||||
}
|
||||
|
||||
// Insert a default only if the key does not already exist.
|
||||
async function seedDefault(key, value) {
|
||||
await query('INSERT IGNORE INTO settings (`key`, value) VALUES (?, ?)', [key, value])
|
||||
}
|
||||
|
||||
module.exports = { getAll, get, set, seedDefault }
|
||||
43
server/src/model/settings/settings.model.js
Normal file
43
server/src/model/settings/settings.model.js
Normal file
@@ -0,0 +1,43 @@
|
||||
const settingsDb = require('./settings.db')
|
||||
|
||||
// Keys safe to expose on the public site.
|
||||
const PUBLIC_KEYS = [
|
||||
'site_mode',
|
||||
'maintenance_message',
|
||||
'status_message',
|
||||
'homepage_teaser',
|
||||
'contact_email',
|
||||
'site_title',
|
||||
]
|
||||
|
||||
async function get(key) {
|
||||
return settingsDb.get(key)
|
||||
}
|
||||
|
||||
async function set(key, value, updatedBy = null) {
|
||||
return settingsDb.set(key, value, updatedBy)
|
||||
}
|
||||
|
||||
async function setMany(obj, updatedBy = null) {
|
||||
for (const [key, value] of Object.entries(obj)) {
|
||||
await settingsDb.set(key, value, updatedBy)
|
||||
}
|
||||
}
|
||||
|
||||
async function getAll() {
|
||||
const rows = await settingsDb.getAll()
|
||||
return rows.reduce((acc, row) => {
|
||||
acc[row.key] = row.value
|
||||
return acc
|
||||
}, {})
|
||||
}
|
||||
|
||||
async function getPublic() {
|
||||
const all = await getAll()
|
||||
return PUBLIC_KEYS.reduce((acc, key) => {
|
||||
if (all[key] !== undefined) acc[key] = all[key]
|
||||
return acc
|
||||
}, {})
|
||||
}
|
||||
|
||||
module.exports = { get, set, setMany, getAll, getPublic, PUBLIC_KEYS }
|
||||
Reference in New Issue
Block a user