remix-demo
react router (remix) demo
git clone https://9o.is/git/remix-demo.git
session.server.ts
(2522B)
1 import { Role } from "@prisma/client";
2 import { createCookieSessionStorage, redirect } from "@remix-run/node";
3 import { json } from "remix-utils";
4 import invariant from "tiny-invariant";
5
6 import type { User } from "~/models/user.server";
7 import { getUserById } from "~/models/user.server";
8
9 invariant(process.env.SESSION_SECRET, "SESSION_SECRET must be set");
10
11 export const sessionStorage = createCookieSessionStorage({
12 cookie: {
13 name: "__session",
14 httpOnly: true,
15 path: "/",
16 sameSite: "lax",
17 secrets: [process.env.SESSION_SECRET],
18 secure: process.env.NODE_ENV === "production",
19 },
20 });
21
22 const USER_SESSION_KEY = "userId";
23
24 export async function getSession(request: Request) {
25 const cookie = request.headers.get("Cookie");
26 return sessionStorage.getSession(cookie);
27 }
28
29 export async function getUserId(
30 request: Request
31 ): Promise<User["id"] | undefined> {
32 const session = await getSession(request);
33 return session.get(USER_SESSION_KEY);
34 }
35
36 export async function getUser(request: Request) {
37 const userId = await getUserId(request);
38 if (userId === undefined) return null;
39
40 const user = await getUserById(userId);
41
42 if (user) return user;
43 throw await destroyUserSession(request);
44 }
45
46 export async function requireUserId(request: Request) {
47 const userId = await getUserId(request);
48 if (!userId) {
49 const path = new URL(request.url).pathname;
50
51 if (path.startsWith("/api")) {
52 throw json({ error: "Unauthorized" }, { status: 401 });
53 }
54
55 throw redirect(`/login`);
56 }
57 return userId;
58 }
59
60 export async function requireUser(request: Request) {
61 const userId = await requireUserId(request);
62
63 const user = await getUserById(userId);
64 if (user) return user;
65
66 throw await destroyUserSession(request);
67 }
68
69 export async function requireAdmin(request: Request) {
70 const user = await requireUser(request);
71
72 if (user.role !== Role.ADMIN) {
73 throw json({ error: "Forbidden" }, { status: 403 });
74 }
75
76 return user;
77 }
78
79 export async function createUserSession({
80 request,
81 userId,
82 }: {
83 request: Request;
84 userId: string;
85 }) {
86 const session = await getSession(request);
87 session.set(USER_SESSION_KEY, userId);
88 return redirect("/", {
89 headers: {
90 "Set-Cookie": await sessionStorage.commitSession(session),
91 },
92 });
93 }
94
95 export async function destroyUserSession(request: Request) {
96 const session = await getSession(request);
97 return redirect("/", {
98 headers: {
99 "Set-Cookie": await sessionStorage.destroySession(session),
100 },
101 });
102 }