diff --git a/src/routes/account.tsx b/src/routes/account.tsx
index d0fb90b..4307f86 100644
--- a/src/routes/account.tsx
+++ b/src/routes/account.tsx
@@ -1214,7 +1214,9 @@ function ActiveSessions(props: { userId: string }) {
};
const formatDate = (dateStr: string) => {
- return new Date(dateStr).toLocaleString(undefined, {
+ // Database stores UTC time, convert to local timezone
+ const date = new Date(dateStr + (dateStr.includes("Z") ? "" : "Z"));
+ return date.toLocaleString(undefined, {
year: "numeric",
month: "short",
day: "numeric",
@@ -1266,6 +1268,15 @@ function ActiveSessions(props: { userId: string }) {
Expires: {formatDate(session.expiresAt)}
+ {session.rememberMe !== undefined && (
+
+ (
+ {session.rememberMe
+ ? "Remember me"
+ : "Session-only"}
+ )
+
+ )}
diff --git a/src/routes/login/index.tsx b/src/routes/login/index.tsx
index ebc9ea4..89495cd 100644
--- a/src/routes/login/index.tsx
+++ b/src/routes/login/index.tsx
@@ -547,7 +547,12 @@ export default function LoginPage() {
diff --git a/src/server/api/routers/user.ts b/src/server/api/routers/user.ts
index b2706aa..b8325df 100644
--- a/src/server/api/routers/user.ts
+++ b/src/server/api/routers/user.ts
@@ -430,17 +430,27 @@ export const userRouter = createTRPCRouter({
// Get current session to mark it
const currentSession = await getAuthSession(ctx.event as any);
- return res.rows.map((row: any) => ({
- sessionId: row.id,
- tokenFamily: row.token_family,
- createdAt: row.created_at,
- expiresAt: row.expires_at,
- lastActiveAt: row.last_active_at,
- rotationCount: row.rotation_count,
- clientIp: row.ip_address,
- userAgent: row.user_agent,
- isCurrent: currentSession?.sessionId === row.id
- }));
+ return res.rows.map((row: any) => {
+ // Infer rememberMe from expires_at duration
+ // If expires_at is > 2 days from creation, it's a remember-me session
+ const createdAt = new Date(row.created_at);
+ const expiresAt = new Date(row.expires_at);
+ const durationMs = expiresAt.getTime() - createdAt.getTime();
+ const rememberMe = durationMs > 2 * 24 * 60 * 60 * 1000; // > 2 days
+
+ return {
+ sessionId: row.id,
+ tokenFamily: row.token_family,
+ createdAt: row.created_at,
+ expiresAt: row.expires_at,
+ lastActiveAt: row.last_active_at,
+ rotationCount: row.rotation_count,
+ clientIp: row.ip_address,
+ userAgent: row.user_agent,
+ rememberMe,
+ isCurrent: currentSession?.sessionId === row.id
+ };
+ });
}),
revokeSession: publicProcedure