Update dependencies to include TinyMCE and Quill, enhance Navigation component with a new Newsletter submenu, and implement role-based access control for CMS features. Refactor user role handling to support multiple roles and improve user management functionality across various API endpoints.
This commit is contained in:
@@ -4,6 +4,27 @@ import { promises as fs } from 'fs'
|
||||
import path from 'path'
|
||||
import { encryptObject, decryptObject } from './encryption.js'
|
||||
|
||||
// Export migrateUserRoles für Verwendung in anderen Modulen
|
||||
export function migrateUserRoles(user) {
|
||||
if (!user) return user
|
||||
|
||||
// Wenn bereits roles Array vorhanden, nichts tun
|
||||
if (Array.isArray(user.roles)) {
|
||||
return user
|
||||
}
|
||||
|
||||
// Wenn role vorhanden, zu roles Array konvertieren
|
||||
if (user.role) {
|
||||
user.roles = [user.role]
|
||||
delete user.role
|
||||
} else {
|
||||
// Fallback: Standard-Rolle
|
||||
user.roles = ['mitglied']
|
||||
}
|
||||
|
||||
return user
|
||||
}
|
||||
|
||||
const JWT_SECRET = process.env.JWT_SECRET || 'harheimertc-secret-key-change-in-production'
|
||||
|
||||
// Handle both dev and production paths
|
||||
@@ -50,17 +71,17 @@ export async function readUsers() {
|
||||
const data = await fs.readFile(USERS_FILE, 'utf-8')
|
||||
|
||||
const encrypted = isEncrypted(data)
|
||||
let users = []
|
||||
|
||||
if (encrypted) {
|
||||
const encryptionKey = getEncryptionKey()
|
||||
try {
|
||||
return decryptObject(data, encryptionKey)
|
||||
users = decryptObject(data, encryptionKey)
|
||||
} catch (decryptError) {
|
||||
console.error('Fehler beim Entschlüsseln der Benutzerdaten:', decryptError)
|
||||
try {
|
||||
const plainData = JSON.parse(data)
|
||||
users = JSON.parse(data)
|
||||
console.warn('Entschlüsselung fehlgeschlagen, versuche als unverschlüsseltes Format zu lesen')
|
||||
return plainData
|
||||
} catch (parseError) {
|
||||
console.error('Konnte Benutzerdaten weder entschlüsseln noch als JSON lesen')
|
||||
return []
|
||||
@@ -68,14 +89,30 @@ export async function readUsers() {
|
||||
}
|
||||
} else {
|
||||
// Plain JSON - migrate to encrypted format
|
||||
const users = JSON.parse(data)
|
||||
users = JSON.parse(data)
|
||||
console.log('Migriere unverschlüsselte Benutzerdaten zu verschlüsselter Speicherung...')
|
||||
|
||||
// Write back encrypted
|
||||
await writeUsers(users)
|
||||
|
||||
return users
|
||||
}
|
||||
|
||||
// Migriere Rollen von role zu roles Array
|
||||
let needsMigration = false
|
||||
users = users.map(user => {
|
||||
const migrated = migrateUserRoles(user)
|
||||
if (!Array.isArray(user.roles) && user.role) {
|
||||
needsMigration = true
|
||||
}
|
||||
return migrated
|
||||
})
|
||||
|
||||
// Wenn Migration nötig war, speichere zurück
|
||||
if (needsMigration) {
|
||||
console.log('Migriere Rollen von role zu roles Array...')
|
||||
await writeUsers(users)
|
||||
} else if (!encrypted) {
|
||||
// Write back encrypted wenn noch nicht verschlüsselt
|
||||
await writeUsers(users)
|
||||
}
|
||||
|
||||
return users
|
||||
} catch (error) {
|
||||
if (error.code === 'ENOENT') {
|
||||
return []
|
||||
@@ -98,21 +135,65 @@ export async function writeUsers(users) {
|
||||
}
|
||||
}
|
||||
|
||||
// Read sessions from file
|
||||
// Prüft ob Sessions-Daten verschlüsselt sind
|
||||
function isSessionsEncrypted(data) {
|
||||
try {
|
||||
const parsed = JSON.parse(data.trim())
|
||||
if (Array.isArray(parsed)) {
|
||||
return false
|
||||
}
|
||||
if (typeof parsed === 'object' && parsed !== null && !parsed.encryptedData) {
|
||||
return false
|
||||
}
|
||||
return false
|
||||
} catch (e) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// Read sessions from file (with encryption support)
|
||||
export async function readSessions() {
|
||||
try {
|
||||
const data = await fs.readFile(SESSIONS_FILE, 'utf-8')
|
||||
return JSON.parse(data)
|
||||
const encrypted = isSessionsEncrypted(data)
|
||||
|
||||
if (encrypted) {
|
||||
const encryptionKey = getEncryptionKey()
|
||||
try {
|
||||
return decryptObject(data, encryptionKey)
|
||||
} catch (decryptError) {
|
||||
console.error('Fehler beim Entschlüsseln der Sessions:', decryptError)
|
||||
try {
|
||||
const plainData = JSON.parse(data)
|
||||
console.warn('Entschlüsselung fehlgeschlagen, versuche als unverschlüsseltes Format zu lesen')
|
||||
return plainData
|
||||
} catch (parseError) {
|
||||
console.error('Konnte Sessions weder entschlüsseln noch als JSON lesen')
|
||||
return []
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Plain JSON - migriere zu verschlüsselter Speicherung
|
||||
const sessions = JSON.parse(data)
|
||||
console.log('Migriere unverschlüsselte Sessions zu verschlüsselter Speicherung...')
|
||||
await writeSessions(sessions)
|
||||
return sessions
|
||||
}
|
||||
} catch (error) {
|
||||
if (error.code === 'ENOENT') {
|
||||
return []
|
||||
}
|
||||
console.error('Fehler beim Lesen der Sessions:', error)
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
// Write sessions to file
|
||||
// Write sessions to file (always encrypted)
|
||||
export async function writeSessions(sessions) {
|
||||
try {
|
||||
await fs.writeFile(SESSIONS_FILE, JSON.stringify(sessions, null, 2), 'utf-8')
|
||||
const encryptionKey = getEncryptionKey()
|
||||
const encryptedData = encryptObject(sessions, encryptionKey)
|
||||
await fs.writeFile(SESSIONS_FILE, encryptedData, 'utf-8')
|
||||
return true
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Schreiben der Sessions:', error)
|
||||
@@ -133,11 +214,15 @@ export async function verifyPassword(password, hash) {
|
||||
|
||||
// Generate JWT token
|
||||
export function generateToken(user) {
|
||||
// Stelle sicher, dass Rollen migriert sind
|
||||
const migratedUser = migrateUserRoles({ ...user })
|
||||
const roles = Array.isArray(migratedUser.roles) ? migratedUser.roles : (migratedUser.role ? [migratedUser.role] : ['mitglied'])
|
||||
|
||||
return jwt.sign(
|
||||
{
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
role: user.role
|
||||
roles: roles
|
||||
},
|
||||
JWT_SECRET,
|
||||
{ expiresIn: '7d' }
|
||||
@@ -156,13 +241,37 @@ export function verifyToken(token) {
|
||||
// Get user by ID
|
||||
export async function getUserById(id) {
|
||||
const users = await readUsers()
|
||||
return users.find(u => u.id === id)
|
||||
const user = users.find(u => u.id === id)
|
||||
return user ? migrateUserRoles(user) : null
|
||||
}
|
||||
|
||||
// Get user by email
|
||||
export async function getUserByEmail(email) {
|
||||
const users = await readUsers()
|
||||
return users.find(u => u.email === email)
|
||||
const user = users.find(u => u.email === email)
|
||||
return user ? migrateUserRoles(user) : null
|
||||
}
|
||||
|
||||
|
||||
// Prüft ob Benutzer eine bestimmte Rolle hat
|
||||
export function hasRole(user, role) {
|
||||
if (!user) return false
|
||||
const roles = Array.isArray(user.roles) ? user.roles : (user.role ? [user.role] : [])
|
||||
return roles.includes(role)
|
||||
}
|
||||
|
||||
// Prüft ob Benutzer eine der angegebenen Rollen hat
|
||||
export function hasAnyRole(user, ...roles) {
|
||||
if (!user) return false
|
||||
const userRoles = Array.isArray(user.roles) ? user.roles : (user.role ? [user.role] : [])
|
||||
return roles.some(role => userRoles.includes(role))
|
||||
}
|
||||
|
||||
// Prüft ob Benutzer alle angegebenen Rollen hat
|
||||
export function hasAllRoles(user, ...roles) {
|
||||
if (!user) return false
|
||||
const userRoles = Array.isArray(user.roles) ? user.roles : (user.role ? [user.role] : [])
|
||||
return roles.every(role => userRoles.includes(role))
|
||||
}
|
||||
|
||||
// Get user from token
|
||||
@@ -171,7 +280,14 @@ export async function getUserFromToken(token) {
|
||||
if (!decoded) return null
|
||||
|
||||
const users = await readUsers()
|
||||
return users.find(u => u.id === decoded.id)
|
||||
const user = users.find(u => u.id === decoded.id)
|
||||
|
||||
// Migriere Rollen beim Laden
|
||||
if (user) {
|
||||
migrateUserRoles(user)
|
||||
}
|
||||
|
||||
return user
|
||||
}
|
||||
|
||||
// Create session
|
||||
|
||||
Reference in New Issue
Block a user