feature(auth): replace clerk.com with custom auth (#103)
* feature(auth): replace clerk.com with custom auth * minor fixes * remove notification preferences * decrease live events interval fix(api): cookies.. # Conflicts: # .gitignore # apps/api/src/index.ts # apps/dashboard/src/app/providers.tsx # packages/trpc/src/trpc.ts
This commit is contained in:
committed by
Carl-Gerhard Lindesvärd
parent
f28802b1c2
commit
d31d9924a5
83
packages/auth/src/session.ts
Normal file
83
packages/auth/src/session.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
import crypto from 'node:crypto';
|
||||
import { type Session, type User, db } from '@openpanel/db';
|
||||
import { sha256 } from '@oslojs/crypto/sha2';
|
||||
import {
|
||||
encodeBase32LowerCaseNoPadding,
|
||||
encodeHexLowerCase,
|
||||
} from '@oslojs/encoding';
|
||||
|
||||
export function generateSessionToken(): string {
|
||||
const bytes = new Uint8Array(20);
|
||||
crypto.getRandomValues(bytes);
|
||||
const token = encodeBase32LowerCaseNoPadding(bytes);
|
||||
return token;
|
||||
}
|
||||
|
||||
export async function createSession(
|
||||
token: string,
|
||||
userId: string,
|
||||
): Promise<Session> {
|
||||
const sessionId = encodeHexLowerCase(sha256(new TextEncoder().encode(token)));
|
||||
const session: Session = {
|
||||
id: sessionId,
|
||||
userId,
|
||||
expiresAt: new Date(Date.now() + 1000 * 60 * 60 * 24 * 30),
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
await db.session.create({
|
||||
data: session,
|
||||
});
|
||||
return session;
|
||||
}
|
||||
|
||||
export const EMPTY_SESSION: SessionValidationResult = {
|
||||
session: null,
|
||||
user: null,
|
||||
userId: null,
|
||||
};
|
||||
|
||||
export async function validateSessionToken(
|
||||
token: string | null,
|
||||
): Promise<SessionValidationResult> {
|
||||
if (!token) {
|
||||
return EMPTY_SESSION;
|
||||
}
|
||||
const sessionId = encodeHexLowerCase(sha256(new TextEncoder().encode(token)));
|
||||
const result = await db.session.findUnique({
|
||||
where: {
|
||||
id: sessionId,
|
||||
},
|
||||
include: {
|
||||
user: true,
|
||||
},
|
||||
});
|
||||
if (result === null) {
|
||||
return EMPTY_SESSION;
|
||||
}
|
||||
const { user, ...session } = result;
|
||||
if (Date.now() >= session.expiresAt.getTime()) {
|
||||
await db.session.delete({ where: { id: sessionId } });
|
||||
return EMPTY_SESSION;
|
||||
}
|
||||
if (Date.now() >= session.expiresAt.getTime() - 1000 * 60 * 60 * 24 * 15) {
|
||||
session.expiresAt = new Date(Date.now() + 1000 * 60 * 60 * 24 * 30);
|
||||
await db.session.update({
|
||||
where: {
|
||||
id: session.id,
|
||||
},
|
||||
data: {
|
||||
expiresAt: session.expiresAt,
|
||||
},
|
||||
});
|
||||
}
|
||||
return { session, user, userId: user.id };
|
||||
}
|
||||
|
||||
export async function invalidateSession(sessionId: string): Promise<void> {
|
||||
await db.session.delete({ where: { id: sessionId } });
|
||||
}
|
||||
|
||||
export type SessionValidationResult =
|
||||
| { session: Session; user: User; userId: string }
|
||||
| { session: null; user: null; userId: null };
|
||||
Reference in New Issue
Block a user