librelad 875a60f90f LibrePortal v0.1.0 — initial release
A free, open, self-hosted app platform (GNU AGPLv3): one-click app deploys,
Traefik reverse proxy with automatic SSL, rootless Docker support, gluetun
VPN routing, and a web dashboard to manage it all.

Free & open forever to self-host; optional paid hosted services fund it.
See PROMISE.md.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-21 20:37:54 +01:00

47 lines
1.4 KiB
JavaScript
Executable File

const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const AUTH_FILE = path.join(__dirname, '..', '..', 'frontend', '.auth.json');
let authData = null;
async function initAuth(fileConfig) {
if (fs.existsSync(AUTH_FILE)) {
authData = JSON.parse(fs.readFileSync(AUTH_FILE, 'utf8'));
console.log('[Auth] Loaded existing credentials for user:', authData.username);
} else {
const username = fileConfig.CFG_WEBUI_USERNAME || 'admin';
const password = fileConfig.CFG_WEBUI_PASSWORD || 'changeme';
console.log('[Auth] Creating auth credentials for user:', username);
const passwordHash = await bcrypt.hash(password, 12);
const jwtSecret = crypto.randomBytes(32).toString('hex');
authData = { username, passwordHash, jwtSecret };
fs.writeFileSync(AUTH_FILE, JSON.stringify(authData, null, 2), 'utf8');
}
}
function generateToken(username) {
return jwt.sign({ sub: username }, authData.jwtSecret, { expiresIn: '30d' });
}
function verifyToken(token) {
try {
return jwt.verify(token, authData.jwtSecret);
} catch {
return null;
}
}
async function verifyPassword(plain, hash) {
return bcrypt.compare(plain, hash);
}
function getCredentials() {
return authData;
}
module.exports = { initAuth, generateToken, verifyToken, verifyPassword, getCredentials };