74 lines
2.2 KiB
JavaScript
Executable File
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)
|
|
};
|
|
}
|