Files
Webklar-Kundenbereich/server/services/passwordVersion.js
T

64 lines
2.3 KiB
JavaScript

import { getUserById } from './appwriteAdmin.js'
/**
* Passwortstand je Appwrite-Konto (users.passwordUpdate, aendert sich nur mit dem Passwort).
* Kunden-Sessions merken sich den Stand beim Login (pwv). Wird das Passwort geaendert - im
* Kundenbereich oder durch uns im Ticketsystem -, gelten aeltere Sessions nicht mehr: der Kunde
* ist auf allen anderen Geraeten abgemeldet. Sessions ohne pwv (vor dieser Pruefung angemeldet)
* laufen normal aus. Kurz zwischengespeichert, damit nicht jede API-Anfrage Appwrite fragt;
* Aenderungen ueber diesen Server gelten sofort (rememberPasswordVersion).
*/
const CACHE_MS = 60 * 1000
const cache = new Map() // appwriteUserId -> { value, at }
let lastWarnAt = 0
function remember(userId, value) {
if (cache.size > 2000) {
const now = Date.now()
for (const [key, entry] of cache) if (now - entry.at > CACHE_MS) cache.delete(key)
}
cache.set(userId, { value, at: Date.now() })
}
export function rememberPasswordVersion(userId, passwordUpdate) {
if (userId) remember(userId, passwordUpdate || '')
}
export function forgetPasswordVersion(userId) {
cache.delete(userId)
}
/** Aktueller Stand; '' = Konto ohne Passwort bzw. geloescht. Wirft bei Appwrite-Fehlern. */
async function currentPasswordVersion(userId) {
const hit = cache.get(userId)
if (hit && Date.now() - hit.at < CACHE_MS) return hit.value
let value
try {
const user = await getUserById(userId)
value = user?.passwordUpdate || ''
} catch (err) {
if (err.status !== 404) throw err
value = ''
}
remember(userId, value)
return value
}
/**
* false, wenn die Kunden-Session von vor der letzten Passwortaenderung stammt. Sessions der
* Kundenansicht (Mitarbeiter) und Sessions ohne pwv werden nicht geprueft. Ist Appwrite nicht
* erreichbar, gilt die Session weiter (sonst waeren bei jeder Stoerung alle abgemeldet).
*/
export async function isSessionPasswordCurrent(session) {
if (!session?.pwv || session.role === 'admin' || !session.appwriteUserId) return true
try {
return (await currentPasswordVersion(session.appwriteUserId)) === session.pwv
} catch (err) {
if (Date.now() - lastWarnAt > 10 * 60 * 1000) {
lastWarnAt = Date.now()
console.warn('[auth] Passwortstand nicht prüfbar, Session gilt weiter:', err.message)
}
return true
}
}