/** * Session management procedures - list, revoke, revokeAll sessions */ import { ORPCError } from "@orpc/server"; import { authMiddleware, os } from "../base.js"; /** * List sessions handler * - Requires authentication * - Returns all sessions for the current user * - Includes isCurrent flag to identify active session */ export const listSessions = os.me.sessions.list .use(authMiddleware) .handler(async ({ context }) => { const sessions = await context.db .selectFrom("sessions") .selectAll() .where("user_id", "=", context.user.id) .orderBy("created_at", "desc") .execute(); return sessions.map((s) => ({ id: Number(s.id), ip: s.ip_address ?? "", city: s.city, region: s.region, country: s.country, userAgent: s.user_agent ?? "", trustedMode: s.trusted_mode, createdAt: s.created_at, isCurrent: s.id === context.session.id, revokedAt: s.revoked_at, })); }); /** * Revoke session handler * - Requires authentication * - Cannot revoke current session (use logout instead) * @throws NOT_FOUND if session doesn't exist * @throws BAD_REQUEST if trying to revoke current session */ export const revokeSession = os.me.sessions.revoke .use(authMiddleware) .handler(async ({ input, context }) => { const { sessionId } = input; // Prevent revoking current session (use logout instead) if (String(sessionId) === context.session.id) { throw new ORPCError("BAD_REQUEST", { message: "Cannot revoke current session. Use logout instead.", }); } const result = await context.db .updateTable("sessions") .set({ revoked_at: new Date() }) .where("id", "=", String(sessionId)) .where("user_id", "=", context.user.id) .where("revoked_at", "is", null) .executeTakeFirst(); if (!result.numUpdatedRows || result.numUpdatedRows === 0n) { throw new ORPCError("NOT_FOUND", { message: "Session not found" }); } return { success: true }; }); /** * Revoke all sessions handler * - Requires authentication * - Revokes all sessions except current */ export const revokeAllSessions = os.me.sessions.revokeAll .use(authMiddleware) .handler(async ({ context }) => { // Revoke all sessions except current await context.db .updateTable("sessions") .set({ revoked_at: new Date() }) .where("user_id", "=", context.user.id) .where("id", "!=", context.session.id) .where("revoked_at", "is", null) .execute(); return { success: true }; });