Advertisement
djbob2000

Untitled

Jan 21st, 2025
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import { cookies } from "next/headers.js";
  2. import { getSession } from "@server/auth/session-db";
  3. import { lucia } from "@/fd/fd-toolbox/auth/lucia";
  4. import jwt from "jsonwebtoken";
  5. import { envSettingKeys } from "@root/infra/env-settings";
  6. import { Cookie } from "lucia";
  7. import { setCoreCache } from "@server/fd/fd-toolbox/cachings/core-memory-cache";
  8. import { fdCacheKeys } from "@server/fd/fd-toolbox-web/constants/fd-cache-keys";
  9. import { getNowAsString, parseStringEndDate } from "@/fd/fd-toolbox/dates/date-times";
  10. import { WithIndexer } from "@server/fd/fd-toolbox/types/with-indexer";
  11.  
  12. interface SessionValidationResult {
  13.     userId: string;
  14.     workspaceId: string | null;
  15. }
  16.  
  17. interface SessionTokenPayload {
  18.     sessionId: string;
  19.     userId: string;
  20.     passwordHash: string;
  21.     workspaceId: string;
  22.     expires: string;
  23. }
  24.  
  25. const sessionConfig = {
  26.     durationInDays: 30,
  27.     secondsInDay: 24 * 60 * 60,
  28.     cookieOptions: {
  29.         httpOnly: true,
  30.         secure: true,
  31.         sameSite: "strict" as const,
  32.         path: "/",
  33.     },
  34. } as const;
  35.  
  36. const sessionDurationSeconds = sessionConfig.durationInDays * sessionConfig.secondsInDay;
  37.  
  38. const emptySessionValidationResult: SessionValidationResult = {
  39.     userId: null!,
  40.     workspaceId: null,
  41. };
  42.  
  43. const sessionTokenRequiredProperties = [
  44.     "sessionId",
  45.     "userId",
  46.     "passwordHash",
  47.     "workspaceId",
  48.     "expires",
  49. ] as const;
  50.  
  51. export function getSessionToken() {
  52.     const sessionCookie = cookies().get(lucia.sessionCookieName);
  53.     return sessionCookie?.value;
  54. }
  55.  
  56. export async function validateSessionToken(sessionToken: string) {
  57.     const session = await getSession(sessionToken);
  58.  
  59.     if (!session) {
  60.         await lucia.invalidateSession(sessionToken);
  61.         return emptySessionValidationResult;
  62.     }
  63.  
  64.     const result: SessionValidationResult = {
  65.         userId: session.userId,
  66.         workspaceId: session.workspaceId,
  67.     };
  68.  
  69.     return result;
  70. }
  71.  
  72. export function decodeSessionToken(token: string) {
  73.     const decoded = jwt.verify(token, envSettingKeys.JwtKey);
  74.  
  75.     if (validateDecodedToken(decoded)) {
  76.         return extractSessionData(decoded);
  77.     }
  78.  
  79.     return null;
  80. }
  81.  
  82. export async function createSession(userId: string, workspaceId: string, passwordHash: string | undefined) {
  83.     const expiresDate = parseStringEndDate(getNowAsString(), sessionDurationSeconds);
  84.  
  85.     const session = await lucia.createSession(userId, { workspaceId });
  86.  
  87.     const sessionPayload = {
  88.         sessionId: session.id,
  89.         userId,
  90.         passwordHash,
  91.         workspaceId,
  92.         expires: expiresDate,
  93.     };
  94.  
  95.     const token = jwt.sign(sessionPayload, envSettingKeys.JwtKey, {
  96.         expiresIn: `${sessionConfig.durationInDays}d`,
  97.     });
  98.  
  99.     const sessionCookie = new Cookie(lucia.sessionCookieName, token, {
  100.         ...sessionConfig.cookieOptions,
  101.         expires: new Date(expiresDate),
  102.     });
  103.  
  104.     cookies().set(sessionCookie.name, sessionCookie.value, sessionCookie.attributes);
  105.  
  106.     setCoreCache(session.id, session, {
  107.         absoluteExpirationRelativeToNowSeconds: fdCacheKeys.secondsInFifteenMinutes,
  108.     });
  109.  
  110.     return { sessionCookie, session };
  111. }
  112.  
  113. function isObject(value: unknown): value is WithIndexer<unknown> {
  114.     return typeof value === "object" && value !== null;
  115. }
  116.  
  117. function validateDecodedToken(decoded: unknown): decoded is SessionTokenPayload {
  118.     if (!isObject(decoded)) return false;
  119.  
  120.     return sessionTokenRequiredProperties.every(
  121.         (prop) => prop in decoded && typeof decoded[prop] === "string",
  122.     );
  123. }
  124.  
  125. function extractSessionData(decoded: SessionTokenPayload) {
  126.     return {
  127.         sessionId: decoded.sessionId,
  128.         userId: decoded.userId,
  129.         passwordHash: decoded.passwordHash,
  130.         workspaceId: decoded.workspaceId,
  131.         expires: decoded.expires,
  132.     };
  133. }
  134.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement