Files
singlechat/server/chat-auth.js
Torsten Schulz (local) bfe28a25fa
All checks were successful
Deploy SingleChat / deploy (push) Successful in 40s
android app, extension of stats
2026-08-10 14:03:34 +02:00

74 lines
2.2 KiB
JavaScript
Executable File

import crypto from 'crypto';
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
import { join } from 'path';
const CHAT_USERS_FILE_NAME = 'chat-users.json';
function ensureLogsDir(baseDir) {
const logsDir = join(baseDir, '../logs');
if (!existsSync(logsDir)) {
mkdirSync(logsDir, { recursive: true });
}
return logsDir;
}
function getChatUsersPath(baseDir) {
return join(ensureLogsDir(baseDir), CHAT_USERS_FILE_NAME);
}
function sha256(value) {
return crypto.createHash('sha256').update(value).digest('hex');
}
export function ensureChatUsersFile(baseDir) {
const usersPath = getChatUsersPath(baseDir);
if (existsSync(usersPath)) return;
writeFileSync(usersPath, '[]\n', 'utf-8');
console.warn(
`[Auth] ${CHAT_USERS_FILE_NAME} wurde neu erstellt. Bitte mindestens einen Admin-User mit Passwort-Hash konfigurieren.`
);
}
export function loadChatUsers(baseDir) {
ensureChatUsersFile(baseDir);
const usersPath = getChatUsersPath(baseDir);
const raw = readFileSync(usersPath, 'utf-8').trim();
if (!raw) return [];
let users = [];
try {
users = JSON.parse(raw);
} catch (error) {
throw new Error(`Ungültige ${CHAT_USERS_FILE_NAME}: ${error.message}`);
}
if (!Array.isArray(users)) {
throw new Error(`${CHAT_USERS_FILE_NAME} muss ein Array sein`);
}
return users
.filter((entry) => entry && typeof entry.username === 'string')
.map((entry) => ({
username: entry.username.trim(),
passwordHash: typeof entry.passwordHash === 'string' ? entry.passwordHash.trim() : '',
rights: Array.isArray(entry.rights) ? entry.rights.map((r) => String(r).toLowerCase()) : []
}))
.filter((entry) => entry.username && entry.passwordHash);
}
export function verifyChatUser(baseDir, username, password) {
if (!username || !password) return null;
const normalizedUser = String(username).trim();
const passwordHash = sha256(password);
const user = loadChatUsers(baseDir).find(
(entry) => entry.username.toLowerCase() === normalizedUser.toLowerCase() && entry.passwordHash === passwordHash
);
if (!user) return null;
return {
username: user.username,
rights: new Set(user.rights)
};
}