Add session management: track active sessions, show on profile, allow revocation
Some checks failed
Deploy / Deploy Production (push) Has been skipped
Deploy / Deploy Preview (push) Failing after 1s
Deploy / Cleanup Preview (push) Has been skipped
CI / UI / Build (pull_request) Failing after 13s
CI / Scraper / Lint (pull_request) Successful in 19s
CI / Scraper / Test (pull_request) Successful in 20s
CI / Scraper / Build (pull_request) Successful in 12s

- Add user_sessions PocketBase collection (user_id, session_id, user_agent, ip, created/last_seen)
- Extend auth token format to include a per-login authSessionId (4th segment)
- Hook validates authSessionId against DB on each request; revoked sessions are cleared immediately
- Login/register create a session record capturing user-agent and IP
- Profile page shows all active sessions with current session highlighted; per-session End/Sign out buttons
- GET /api/sessions and DELETE /api/sessions/[id] endpoints for client-side revocation
- Backward compatible: legacy 3-segment tokens pass through without DB check
This commit is contained in:
Admin
2026-03-07 11:53:16 +05:00
parent 70dd14e5c8
commit 1eb70e9b9b
9 changed files with 406 additions and 20 deletions

View File

@@ -1,14 +1,30 @@
import { fail, redirect } from '@sveltejs/kit';
import type { Actions, PageServerLoad } from './$types';
import { changePassword } from '$lib/server/pocketbase';
import { changePassword, listUserSessions } from '$lib/server/pocketbase';
import { log } from '$lib/server/logger';
export const load: PageServerLoad = async ({ locals }) => {
if (!locals.user) {
redirect(302, '/login');
}
let sessions: Awaited<ReturnType<typeof listUserSessions>> = [];
try {
sessions = await listUserSessions(locals.user.id);
} catch (e) {
log.warn('profile', 'listUserSessions failed (non-fatal)', { err: String(e) });
}
return {
user: locals.user
user: locals.user,
sessions: sessions.map((s) => ({
id: s.id,
user_agent: s.user_agent,
ip: s.ip,
created_at: s.created_at,
last_seen: s.last_seen,
is_current: s.session_id === locals.user!.authSessionId
}))
};
};