feat(session): handle sessions for admin
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
import { apiFetch, apiJson } from '$lib/api/client';
|
||||
import { getCsrfHeaders } from '$lib/api/csrf';
|
||||
import type {
|
||||
AdminSessionsPage,
|
||||
AdminUsersPage,
|
||||
Drive,
|
||||
DriveMember,
|
||||
@@ -241,6 +242,39 @@ export async function deleteDriveAdmin(driveId: string): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
// ── Sessions (admin panel) ──────────────────────────────────────────────
|
||||
|
||||
/** Options for {@link listAdminSessions}. */
|
||||
export interface ListSessionsOpts {
|
||||
/** Narrow to one user's sessions; omit for cross-user listing. */
|
||||
userId?: string;
|
||||
/** Include revoked / expired rows. Default `false` (active-only UX). */
|
||||
includeRevoked?: boolean;
|
||||
/** Page size — server caps at 500. */
|
||||
limit?: number;
|
||||
/** Pagination offset. */
|
||||
offset?: number;
|
||||
}
|
||||
|
||||
/** Global sessions listing — `GET /api/admin/sessions`. */
|
||||
export function listAdminSessions(opts: ListSessionsOpts = {}): Promise<AdminSessionsPage> {
|
||||
const params = new URLSearchParams();
|
||||
if (opts.userId) params.set('user_id', opts.userId);
|
||||
if (opts.includeRevoked) params.set('include_revoked', 'true');
|
||||
if (opts.limit !== undefined) params.set('limit', String(opts.limit));
|
||||
if (opts.offset !== undefined) params.set('offset', String(opts.offset));
|
||||
const qs = params.toString();
|
||||
return apiJson<AdminSessionsPage>(`/api/admin/sessions${qs ? '?' + qs : ''}`, {
|
||||
credentials: 'same-origin'
|
||||
});
|
||||
}
|
||||
|
||||
/** Revoke a session — `DELETE /api/admin/sessions/{id}`. Sets
|
||||
* `revoked=true`; the row stays in the DB for audit visibility. */
|
||||
export function revokeAdminSession(sessionId: string): Promise<void> {
|
||||
return mutate(`/api/admin/sessions/${encodeURIComponent(sessionId)}`, 'DELETE');
|
||||
}
|
||||
|
||||
// ── Users ───────────────────────────────────────────────────────────────
|
||||
|
||||
/** List the compact rows rendered by the management table; full account
|
||||
|
||||
@@ -734,3 +734,31 @@ export interface Finding {
|
||||
detail: Record<string, unknown>;
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Admin sessions-panel row shape. Backend: `SessionSummaryDto` in
|
||||
* `src/application/dtos/session_dto.rs`. Deliberately narrower than
|
||||
* the DB row — the refresh token is never serialised, and the full
|
||||
* DPoP thumbprint is truncated to an 8-char prefix so admins viewing
|
||||
* other users' sessions can't exfiltrate the full binding fingerprint.
|
||||
*/
|
||||
export interface SessionSummary {
|
||||
id: string;
|
||||
user_id: string;
|
||||
created_at: string;
|
||||
expires_at: string;
|
||||
ip_address: string | null;
|
||||
user_agent: string | null;
|
||||
is_bound: boolean;
|
||||
dpop_jkt_prefix: string | null;
|
||||
is_revoked: boolean;
|
||||
is_active: boolean;
|
||||
oidc_sid: string | null;
|
||||
}
|
||||
|
||||
/** Wire response of `GET /api/admin/sessions`. */
|
||||
export interface AdminSessionsPage {
|
||||
sessions: SessionSummary[];
|
||||
limit: number;
|
||||
offset: number;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user