mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-23 23:36:43 +02:00
feat(auth): session management UI and improved account lockout feedback
Session management: - GET /auth/sessions and DELETE /auth/sessions/:id endpoints - listSessions() and revokeSession() in shared-auth client - SessionManager component: active sessions list with device info, "Aktuell" badge, revoke individual or all other sessions - Integrated in ManaCore settings page Account lockout UX: - Dedicated amber lockout banner (distinct from generic rate-limit) - "Konto vorübergehend gesperrt" with MM:SS countdown - "Passwort zurücksetzen" link as alternative action - formatCountdown helper for clean time display Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
2624e5a6b7
commit
8f56feb115
8 changed files with 898 additions and 4 deletions
|
|
@ -213,6 +213,18 @@ export const authStore = {
|
|||
return authService.getSecurityEvents();
|
||||
},
|
||||
|
||||
async listSessions() {
|
||||
const authService = getAuthService();
|
||||
if (!authService) return [];
|
||||
return authService.listSessions();
|
||||
},
|
||||
|
||||
async revokeSession(sessionId: string) {
|
||||
const authService = getAuthService();
|
||||
if (!authService) return { success: false, error: 'Auth not available' };
|
||||
return authService.revokeSession(sessionId);
|
||||
},
|
||||
|
||||
/**
|
||||
* Sign in with email and password
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,7 +1,12 @@
|
|||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { Button, Input, Card, PageHeader, GlobalSettingsSection } from '@manacore/shared-ui';
|
||||
import { PasskeyManager, TwoFactorSetup, AuditLog } from '@manacore/shared-auth-ui';
|
||||
import {
|
||||
PasskeyManager,
|
||||
TwoFactorSetup,
|
||||
AuditLog,
|
||||
SessionManager,
|
||||
} from '@manacore/shared-auth-ui';
|
||||
import { authStore } from '$lib/stores/auth.svelte';
|
||||
import { creditsService } from '$lib/api/credits';
|
||||
import type { CreditBalance } from '$lib/api/credits';
|
||||
|
|
@ -27,6 +32,10 @@
|
|||
let securityEvents = $state<any[]>([]);
|
||||
let securityEventsLoading = $state(false);
|
||||
|
||||
// Sessions
|
||||
let sessions = $state<any[]>([]);
|
||||
let sessionsLoading = $state(false);
|
||||
|
||||
onMount(async () => {
|
||||
if (authStore.isAuthenticated) {
|
||||
try {
|
||||
|
|
@ -38,6 +47,10 @@
|
|||
securityEventsLoading = true;
|
||||
securityEvents = await authStore.getSecurityEvents();
|
||||
securityEventsLoading = false;
|
||||
// Load sessions
|
||||
sessionsLoading = true;
|
||||
sessions = await authStore.listSessions();
|
||||
sessionsLoading = false;
|
||||
} catch (e) {
|
||||
console.error('Failed to load data:', e);
|
||||
}
|
||||
|
|
@ -302,6 +315,23 @@
|
|||
</div>
|
||||
</Card>
|
||||
|
||||
<!-- Sessions Section -->
|
||||
<Card>
|
||||
<div class="p-6">
|
||||
<SessionManager
|
||||
{sessions}
|
||||
loading={sessionsLoading}
|
||||
onRevoke={(id) => authStore.revokeSession(id)}
|
||||
onRefresh={async () => {
|
||||
sessionsLoading = true;
|
||||
sessions = await authStore.listSessions();
|
||||
sessionsLoading = false;
|
||||
}}
|
||||
primaryColor="#6366f1"
|
||||
/>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
<!-- Two-Factor Authentication Section -->
|
||||
<Card>
|
||||
<div class="p-6">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue