feat(auth): implement Android refresh token handling and session management
- Added support for generating Android access tokens and managing refresh sessions in the auth endpoints. - Implemented new tests for login, logout, and refresh functionalities specific to Android clients. - Enhanced password reset logging with normalization and masking of email addresses. - Created a new diagnostics endpoint for password reset attempts, including filtering and summarizing logs. - Introduced a new utility for managing password reset logs with retention policies. - Added tests for password reset log utilities to ensure proper functionality and privacy compliance. - Updated WebAuthn configuration tests to validate origin handling for production and allowed origins.
This commit is contained in:
@@ -2,6 +2,7 @@ import { importSpielplan } from '../utils/spielplan-import.js'
|
||||
import { importLeagueTables } from '../utils/spielklassen-tables-import.js'
|
||||
import { publishImportedSpielplan } from '../utils/spielplan-publish.js'
|
||||
import { info as loggerInfo, error as loggerError } from '../utils/logger.js'
|
||||
import { cleanupPasswordResetLogs } from '../utils/password-reset-log.js'
|
||||
|
||||
const TIME_ZONE = 'Europe/Berlin'
|
||||
const RUN_HOUR = 7
|
||||
@@ -65,11 +66,22 @@ function nextRunAt(now = new Date()) {
|
||||
return candidate
|
||||
}
|
||||
|
||||
async function runImport(reason) {
|
||||
async function runDailyJobs(reason, skipSpielplanImport = false) {
|
||||
if (running) return
|
||||
|
||||
running = true
|
||||
try {
|
||||
try {
|
||||
const cleanup = await cleanupPasswordResetLogs()
|
||||
loggerInfo(`[password-reset-log] ${reason}: Bereinigung abgeschlossen`, cleanup)
|
||||
} catch (error) {
|
||||
loggerError('[password-reset-log] Bereinigung fehlgeschlagen:', { error })
|
||||
}
|
||||
|
||||
if (skipSpielplanImport) {
|
||||
return
|
||||
}
|
||||
|
||||
const spielplan = await importSpielplan()
|
||||
loggerInfo(`[spielplan-import] ${reason}: ${spielplan.matchCount} Spiele importiert`, { range: `${spielplan.source.season.dateStart} - ${spielplan.source.season.dateEnd}` })
|
||||
|
||||
@@ -96,13 +108,13 @@ async function runImport(reason) {
|
||||
}
|
||||
}
|
||||
|
||||
function scheduleNext() {
|
||||
function scheduleNext(skipSpielplanImport = false) {
|
||||
const runAt = nextRunAt()
|
||||
const delay = Math.min(Math.max(runAt.getTime() - Date.now(), 1_000), MAX_TIMEOUT)
|
||||
|
||||
timer = setTimeout(async () => {
|
||||
await runImport('taeglicher Lauf')
|
||||
scheduleNext()
|
||||
await runDailyJobs('taeglicher Lauf', skipSpielplanImport)
|
||||
scheduleNext(skipSpielplanImport)
|
||||
}, delay)
|
||||
|
||||
timer.unref?.()
|
||||
@@ -110,15 +122,15 @@ function scheduleNext() {
|
||||
}
|
||||
|
||||
export default defineNitroPlugin((nitroApp) => {
|
||||
if (process.env.SPIELPLAN_IMPORT_DISABLED === 'true') {
|
||||
loggerInfo('[spielplan-import] Scheduler deaktiviert')
|
||||
return
|
||||
const skipSpielplanImport = process.env.SPIELPLAN_IMPORT_DISABLED === 'true'
|
||||
if (skipSpielplanImport) {
|
||||
loggerInfo('[spielplan-import] Import deaktiviert; Passwort-Reset-Log-Bereinigung bleibt aktiv')
|
||||
}
|
||||
|
||||
scheduleNext()
|
||||
scheduleNext(skipSpielplanImport)
|
||||
|
||||
if (process.env.SPIELPLAN_IMPORT_RUN_ON_START === 'true') {
|
||||
runImport('Startlauf')
|
||||
runDailyJobs('Startlauf', skipSpielplanImport)
|
||||
}
|
||||
|
||||
nitroApp.hooks.hookOnce('close', () => {
|
||||
|
||||
Reference in New Issue
Block a user