aa
This commit is contained in:
@@ -2,13 +2,16 @@ import "server-only";
|
||||
import { randomBytes } from "node:crypto";
|
||||
import bcrypt from "bcryptjs";
|
||||
import { cookies } from "next/headers";
|
||||
import { and, eq, gt } from "drizzle-orm";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { db } from "./client";
|
||||
import { sessions, users } from "./schema";
|
||||
import type { User } from "@/lib/types";
|
||||
|
||||
export const SESSION_COOKIE = "places_session";
|
||||
const SESSION_DAYS = 30;
|
||||
// Best-effort persistence — Chrome/Safari now cap cookie lifetime to ~400d
|
||||
// regardless of what we set. The DB row has no expiry (expires_at = NULL),
|
||||
// so re-login isn't required even if the cookie eventually gets pruned.
|
||||
const COOKIE_MAX_AGE_SECONDS = 60 * 60 * 24 * 365 * 10; // 10 years
|
||||
|
||||
function newToken(): string {
|
||||
return randomBytes(32).toString("base64url");
|
||||
@@ -119,15 +122,14 @@ export async function loginUser(
|
||||
|
||||
async function createSessionCookie(userId: number): Promise<void> {
|
||||
const token = newToken();
|
||||
const expiresAt = new Date(Date.now() + SESSION_DAYS * 24 * 60 * 60 * 1000);
|
||||
await db.insert(sessions).values({ id: token, userId, expiresAt });
|
||||
await db.insert(sessions).values({ id: token, userId, expiresAt: null });
|
||||
const c = await cookies();
|
||||
c.set(SESSION_COOKIE, token, {
|
||||
httpOnly: true,
|
||||
sameSite: "lax",
|
||||
secure: process.env.NODE_ENV === "production",
|
||||
path: "/",
|
||||
expires: expiresAt,
|
||||
maxAge: COOKIE_MAX_AGE_SECONDS,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -138,10 +140,12 @@ export async function getCurrentUserId(): Promise<number | null> {
|
||||
const [row] = await db
|
||||
.select({ userId: sessions.userId, expiresAt: sessions.expiresAt })
|
||||
.from(sessions)
|
||||
.where(and(eq(sessions.id, token), gt(sessions.expiresAt, new Date())))
|
||||
.where(eq(sessions.id, token))
|
||||
.limit(1);
|
||||
if (!row) {
|
||||
// Clean up an expired/invalid token if present.
|
||||
if (!row) return null;
|
||||
// expiresAt = NULL means the session never expires. Legacy rows with a
|
||||
// timestamp value still respect that expiry.
|
||||
if (row.expiresAt && row.expiresAt.getTime() < Date.now()) {
|
||||
await db.delete(sessions).where(eq(sessions.id, token));
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user