Skip to content

Commit 462f8ad

Browse files
committed
ATM-10 Create session actions
1 parent 8d5c920 commit 462f8ad

1 file changed

Lines changed: 135 additions & 0 deletions

File tree

src/lib/session.ts

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
"use server";
2+
import { prisma } from "./prisma";
3+
import crypto from "crypto";
4+
5+
6+
function generateSessionToken() {
7+
return crypto.randomBytes(32).toString("hex"); // 64-char token
8+
}
9+
10+
function hashToken(token: string) {
11+
return crypto.createHash("sha256").update(token).digest("hex");
12+
}
13+
14+
export type GetSessionsFilters = {
15+
userId?: string;
16+
projectId?: string;
17+
};
18+
19+
export type UpdateSessionData = {
20+
expiresAt?: Date;
21+
};
22+
23+
/**
24+
* Creates a new session with a userId and projectId
25+
* @param userId The userId of the user for the session
26+
* @param projectId The projectId of the project for the session
27+
* @returns The created session
28+
*/
29+
export async function createSession(userId: string, projectId: string) {
30+
const rawToken = generateSessionToken();
31+
const hashedToken = hashToken(rawToken);
32+
33+
const expiresAt = new Date();
34+
expiresAt.setDate(expiresAt.getDate() + 1); // 1 day
35+
const session = prisma.session.create({
36+
data: {
37+
userId,
38+
projectId,
39+
token: hashedToken,
40+
expiresAt,
41+
}
42+
})
43+
return {
44+
...session,
45+
token: rawToken,
46+
}
47+
}
48+
49+
/**
50+
* Gets a session based on a session id
51+
* @param id The session id
52+
* @returns The session
53+
*/
54+
export const getSession = async (id: string) =>
55+
prisma.session.findUnique({ where: { id, expiresAt: { gt: new Date() }, } });
56+
57+
/**
58+
* Gets all sessions by filter
59+
* @param filters userId and projectId
60+
* @returns All sessions associated with the filters
61+
*/
62+
export async function getSessions(filters: {
63+
userId: string;
64+
projectId: string;
65+
}) {
66+
const sessions = await prisma.session.findMany({
67+
where: { ...(filters?.userId && { userId: filters.userId }),
68+
...(filters?.projectId && { projectId: filters.projectId }),
69+
expiresAt: {
70+
gt: new Date(), // only active sessions
71+
},
72+
},
73+
orderBy: {
74+
createdAt: "desc",
75+
},
76+
});
77+
78+
if (!sessions) return null;
79+
80+
return sessions;
81+
}
82+
83+
/**
84+
* Updates a session to extend the expireAt
85+
* @param id The session id
86+
* @param data When the new expireAt should be
87+
* @returns The updated session
88+
*/
89+
export async function updateSession(id: string, data: { expiresAt: Date }) {
90+
const newExpiry = data.expiresAt;
91+
92+
const session = await prisma.session.findUnique({
93+
where: { id },
94+
});
95+
96+
if (!session) return null;
97+
98+
// don't extend expired sessions
99+
if (session.expiresAt < new Date()) {
100+
return null;
101+
}
102+
return prisma.session.update({
103+
where: { id },
104+
data: {
105+
expiresAt: newExpiry,
106+
},
107+
});
108+
}
109+
110+
/**
111+
* Deletes a session
112+
* @param id The session id
113+
* @returns If the delete was successful
114+
*/
115+
export const deleteSession = async (id: string) =>
116+
prisma.session.delete({ where: { id } });
117+
118+
/**
119+
* Validates a session based on a token and project
120+
* @param token The token associated with the session
121+
* @param projectId The projectId associated with a project
122+
* @returns a session
123+
*/
124+
export async function validateSession(token: string, projectId: string){
125+
const hashedToken = hashToken(token);
126+
return prisma.session.findFirst({
127+
where: {
128+
token: hashedToken,
129+
projectId,
130+
expiresAt: {
131+
gt: new Date(),
132+
},
133+
},
134+
});
135+
}

0 commit comments

Comments
 (0)