remove lucia

This commit is contained in:
Milo Schwartz
2024-10-13 17:13:47 -04:00
parent f14fb90ab6
commit 99d6cababa
39 changed files with 234 additions and 167 deletions

View File

@@ -2,7 +2,7 @@ import { Request, Response, NextFunction } from "express";
import createHttpError from "http-errors";
import HttpCode from "@server/types/HttpCode";
import { fromError } from "zod-validation-error";
import lucia, { unauthorized } from "@server/auth";
import { unauthorized, invalidateAllSessions } from "@server/auth";
import { z } from "zod";
import { db } from "@server/db";
import { User, users } from "@server/db/schema";
@@ -74,7 +74,7 @@ export async function changePassword(
const validOTP = await verifyTotpCode(
code!,
user.twoFactorSecret!,
user.id,
user.userId,
);
if (!validOTP) {
@@ -94,9 +94,9 @@ export async function changePassword(
.set({
passwordHash: hash,
})
.where(eq(users.id, user.id));
.where(eq(users.userId, user.userId));
await lucia.invalidateUserSessions(user.id);
await invalidateAllSessions(user.userId);
// TODO: send email to user confirming password change

View File

@@ -69,7 +69,7 @@ export async function disable2fa(
const validOTP = await verifyTotpCode(
code,
user.twoFactorSecret!,
user.id,
user.userId,
);
if (!validOTP) {
@@ -84,11 +84,11 @@ export async function disable2fa(
await db
.update(users)
.set({ twoFactorEnabled: false })
.where(eq(users.id, user.id));
.where(eq(users.userId, user.userId));
await db
.delete(twoFactorBackupCodes)
.where(eq(twoFactorBackupCodes.userId, user.id));
.where(eq(twoFactorBackupCodes.userId, user.userId));
// TODO: send email to user confirming two-factor authentication is disabled

View File

@@ -6,7 +6,7 @@ import createHttpError from 'http-errors';
import HttpCode from '@server/types/HttpCode';
export async function getUserOrgs(req: Request, res: Response, next: NextFunction) {
const userId = req.user?.id; // Assuming you have user information in the request
const userId = req.user?.userId; // Assuming you have user information in the request
if (!userId) {
return next(createHttpError(HttpCode.UNAUTHORIZED, 'User not authenticated'));
@@ -30,4 +30,4 @@ export async function getUserOrgs(req: Request, res: Response, next: NextFunctio
} catch (error) {
next(createHttpError(HttpCode.INTERNAL_SERVER_ERROR, 'Error retrieving user organizations'));
}
}
}

View File

@@ -1,5 +1,10 @@
import { verify } from "@node-rs/argon2";
import lucia, { verifySession } from "@server/auth";
import {
createSession,
generateSessionToken,
serializeSessionCookie,
verifySession,
} from "@server/auth";
import db from "@server/db";
import { users } from "@server/db/schema";
import HttpCode from "@server/types/HttpCode";
@@ -102,7 +107,7 @@ export async function login(
const validOTP = await verifyTotpCode(
code,
existingUser.twoFactorSecret!,
existingUser.id,
existingUser.userId,
);
if (!validOTP) {
@@ -115,13 +120,11 @@ export async function login(
}
}
const session = await lucia.createSession(existingUser.id, {});
const cookie = lucia.createSessionCookie(session.id).serialize();
const token = generateSessionToken();
await createSession(token, existingUser.userId);
const cookie = serializeSessionCookie(token);
res.appendHeader(
"Set-Cookie",
cookie
);
res.appendHeader("Set-Cookie", cookie);
if (!existingUser.emailVerified) {
return response<LoginResponse>(res, {

View File

@@ -1,16 +1,20 @@
import { Request, Response, NextFunction } from "express";
import { lucia } from "@server/auth";
import createHttpError from "http-errors";
import HttpCode from "@server/types/HttpCode";
import response from "@server/utils/response";
import logger from "@server/logger";
import {
createBlankSessionTokenCookie,
invalidateSession,
SESSION_COOKIE_NAME,
} from "@server/auth";
export async function logout(
req: Request,
res: Response,
next: NextFunction,
): Promise<any> {
const sessionId = req.cookies[lucia.sessionCookieName];
const sessionId = req.cookies[SESSION_COOKIE_NAME];
if (!sessionId) {
return next(
@@ -22,11 +26,8 @@ export async function logout(
}
try {
await lucia.invalidateSession(sessionId);
res.setHeader(
"Set-Cookie",
lucia.createBlankSessionCookie().serialize(),
);
await invalidateSession(sessionId);
res.setHeader("Set-Cookie", createBlankSessionTokenCookie());
return response<null>(res, {
data: null,

View File

@@ -26,7 +26,7 @@ export async function requestEmailVerificationCode(
);
}
await sendEmailVerificationCode(user.email, user.id);
await sendEmailVerificationCode(user.email, user.userId);
return response<RequestEmailVerificationCodeResponse>(res, {
data: {

View File

@@ -8,10 +8,11 @@ import { db } from "@server/db";
import { passwordResetTokens, users } from "@server/db/schema";
import { eq } from "drizzle-orm";
import { sha256 } from "oslo/crypto";
import { generateIdFromEntropySize, TimeSpan } from "lucia";
import { encodeHex } from "oslo/encoding";
import { createDate } from "oslo";
import logger from "@server/logger";
import { generateIdFromEntropySize } from "@server/auth";
import { TimeSpan } from "oslo";
export const requestPasswordResetBody = z.object({
email: z.string().email(),
@@ -58,7 +59,7 @@ export async function requestPasswordReset(
await db
.delete(passwordResetTokens)
.where(eq(passwordResetTokens.userId, existingUser[0].id));
.where(eq(passwordResetTokens.userId, existingUser[0].userId));
const token = generateIdFromEntropySize(25);
const tokenHash = encodeHex(
@@ -66,7 +67,7 @@ export async function requestPasswordReset(
);
await db.insert(passwordResetTokens).values({
userId: existingUser[0].id,
userId: existingUser[0].userId,
tokenHash,
expiresAt: createDate(new TimeSpan(2, "h")).getTime(),
});
@@ -89,7 +90,7 @@ export async function requestPasswordReset(
return next(
createHttpError(
HttpCode.INTERNAL_SERVER_ERROR,
"Failed to process password reset request"
"Failed to process password reset request",
),
);
}

View File

@@ -72,7 +72,7 @@ export async function requestTotpSecret(
.set({
twoFactorSecret: secret,
})
.where(eq(users.id, user.id));
.where(eq(users.userId, user.userId));
return response<RequestTotpSecretResponse>(res, {
data: {

View File

@@ -13,7 +13,7 @@ import { verifyTotpCode } from "@server/auth/2fa";
import { passwordSchema } from "@server/auth/passwordSchema";
import { encodeHex } from "oslo/encoding";
import { isWithinExpirationDate } from "oslo";
import lucia from "@server/auth";
import { invalidateAllSessions } from "@server/auth";
export const resetPasswordBody = z.object({
token: z.string(),
@@ -71,7 +71,7 @@ export async function resetPassword(
const user = await db
.select()
.from(users)
.where(eq(users.id, resetRequest[0].userId));
.where(eq(users.userId, resetRequest[0].userId));
if (!user || !user.length) {
return next(
@@ -96,7 +96,7 @@ export async function resetPassword(
const validOTP = await verifyTotpCode(
code!,
user[0].twoFactorSecret!,
user[0].id,
user[0].userId,
);
if (!validOTP) {
@@ -111,12 +111,12 @@ export async function resetPassword(
const passwordHash = await hashPassword(newPassword);
await lucia.invalidateUserSessions(resetRequest[0].userId);
await invalidateAllSessions(resetRequest[0].userId);
await db
.update(users)
.set({ passwordHash })
.where(eq(users.id, resetRequest[0].userId));
.where(eq(users.userId, resetRequest[0].userId));
await db
.delete(passwordResetTokens)

View File

@@ -3,9 +3,7 @@ import db from "@server/db";
import { hash } from "@node-rs/argon2";
import HttpCode from "@server/types/HttpCode";
import { z } from "zod";
import { generateId } from "lucia";
import { users } from "@server/db/schema";
import lucia from "@server/auth";
import { fromError } from "zod-validation-error";
import createHttpError from "http-errors";
import response from "@server/utils/response";
@@ -14,6 +12,12 @@ import { sendEmailVerificationCode } from "./sendEmailVerificationCode";
import { passwordSchema } from "@server/auth/passwordSchema";
import { eq } from "drizzle-orm";
import moment from "moment";
import {
createSession,
generateId,
generateSessionToken,
serializeSessionCookie,
} from "@server/auth";
export const signupBodySchema = z.object({
email: z.string().email(),
@@ -85,22 +89,21 @@ export async function signup(
);
} else {
// If the user was created more than 2 hours ago, we want to delete the old user and create a new one
await db.delete(users).where(eq(users.id, user.id));
await db.delete(users).where(eq(users.userId, user.userId));
}
}
await db.insert(users).values({
id: userId,
userId: userId,
email: email,
passwordHash,
dateCreated: moment().toISOString(),
});
const session = await lucia.createSession(userId, {});
res.appendHeader(
"Set-Cookie",
lucia.createSessionCookie(session.id).serialize(),
);
const token = generateSessionToken();
await createSession(token, userId);
const cookie = serializeSessionCookie(token);
res.appendHeader("Set-Cookie", cookie);
sendEmailVerificationCode(email, userId);

View File

@@ -51,14 +51,14 @@ export async function verifyEmail(
if (valid) {
await db
.delete(emailVerificationCodes)
.where(eq(emailVerificationCodes.userId, user.id));
.where(eq(emailVerificationCodes.userId, user.userId));
await db
.update(users)
.set({
emailVerified: true,
})
.where(eq(users.id, user.id));
.where(eq(users.userId, user.userId));
} else {
return next(
createHttpError(
@@ -93,7 +93,7 @@ async function isValidCode(user: User, code: string): Promise<boolean> {
const codeRecord = await db
.select()
.from(emailVerificationCodes)
.where(eq(emailVerificationCodes.userId, user.id))
.where(eq(emailVerificationCodes.userId, user.userId))
.limit(1);
if (user.email !== codeRecord[0].email) {

View File

@@ -7,7 +7,7 @@ import HttpCode from '@server/types/HttpCode';
import { AuthenticatedRequest } from '@server/types/Auth';
export function verifyOrgAccess(req: Request, res: Response, next: NextFunction) {
const userId = req.user!.id; // Assuming you have user information in the request
const userId = req.user!.userId; // Assuming you have user information in the request
const orgId = parseInt(req.params.orgId);
if (!userId) {

View File

@@ -6,7 +6,7 @@ import createHttpError from 'http-errors';
import HttpCode from '@server/types/HttpCode';
export async function verifyResourceAccess(req: Request, res: Response, next: NextFunction) {
const userId = req.user!.id; // Assuming you have user information in the request
const userId = req.user!.userId; // Assuming you have user information in the request
const resourceId = req.params.resourceId || req.body.resourceId || req.query.resourceId;
if (!userId) {
@@ -75,4 +75,4 @@ export async function verifyResourceAccess(req: Request, res: Response, next: Ne
} catch (error) {
return next(createHttpError(HttpCode.INTERNAL_SERVER_ERROR, 'Error verifying resource access'));
}
}
}

View File

@@ -7,7 +7,7 @@ import HttpCode from '@server/types/HttpCode';
import logger from '@server/logger';
export async function verifyRoleAccess(req: Request, res: Response, next: NextFunction) {
const userId = req.user?.id; // Assuming you have user information in the request
const userId = req.user?.userId; // Assuming you have user information in the request
const roleId = parseInt(req.params.roleId || req.body.roleId || req.query.roleId);
if (!userId) {
@@ -47,4 +47,4 @@ export async function verifyRoleAccess(req: Request, res: Response, next: NextFu
logger.error('Error verifying role access:', error);
return next(createHttpError(HttpCode.INTERNAL_SERVER_ERROR, 'Error verifying role access'));
}
}
}

View File

@@ -6,7 +6,7 @@ import createHttpError from 'http-errors';
import HttpCode from '@server/types/HttpCode';
export async function verifySiteAccess(req: Request, res: Response, next: NextFunction) {
const userId = req.user!.id; // Assuming you have user information in the request
const userId = req.user!.userId; // Assuming you have user information in the request
const siteId = parseInt(req.params.siteId || req.body.siteId || req.query.siteId);
if (!userId) {
@@ -76,4 +76,4 @@ export async function verifySiteAccess(req: Request, res: Response, next: NextFu
} catch (error) {
return next(createHttpError(HttpCode.INTERNAL_SERVER_ERROR, 'Error verifying site access'));
}
}
}

View File

@@ -7,7 +7,7 @@ import HttpCode from '@server/types/HttpCode';
import logger from '@server/logger';
export async function verifySuperuser(req: Request, res: Response, next: NextFunction) {
const userId = req.user?.id; // Assuming you have user information in the request
const userId = req.user?.userId; // Assuming you have user information in the request
const orgId = req.userOrgId;
if (!userId) {
@@ -18,7 +18,7 @@ export async function verifySuperuser(req: Request, res: Response, next: NextFun
return next(createHttpError(HttpCode.UNAUTHORIZED, 'User not authenticated'));
}
try {
try {
// Check if the user has a role in the organization
const userOrgRole = await db.select()
.from(userOrgs)
@@ -35,7 +35,7 @@ export async function verifySuperuser(req: Request, res: Response, next: NextFun
.from(roles)
.where(eq(roles.roleId, userOrgRole[0].roleId))
.limit(1);
if (userRole.length === 0 || !userRole[0].isSuperuserRole) {
return next(createHttpError(HttpCode.FORBIDDEN, 'User does not have superuser access'));
}
@@ -45,4 +45,4 @@ export async function verifySuperuser(req: Request, res: Response, next: NextFun
logger.error('Error verifying role access:', error);
return next(createHttpError(HttpCode.INTERNAL_SERVER_ERROR, 'Error verifying role access'));
}
}
}

View File

@@ -6,7 +6,7 @@ import createHttpError from 'http-errors';
import HttpCode from '@server/types/HttpCode';
export async function verifyTargetAccess(req: Request, res: Response, next: NextFunction) {
const userId = req.user!.id; // Assuming you have user information in the request
const userId = req.user!.userId; // Assuming you have user information in the request
const targetId = parseInt(req.params.targetId);
if (!userId) {
@@ -81,4 +81,4 @@ export async function verifyTargetAccess(req: Request, res: Response, next: Next
.catch((error) => {
next(createHttpError(HttpCode.INTERNAL_SERVER_ERROR, 'Error verifying organization access'));
});
}
}

View File

@@ -61,7 +61,7 @@ export async function verifyTotp(
}
try {
const valid = await verifyTotpCode(code, user.twoFactorSecret, user.id);
const valid = await verifyTotpCode(code, user.twoFactorSecret, user.userId);
let codes;
if (valid) {
@@ -69,7 +69,7 @@ export async function verifyTotp(
await db
.update(users)
.set({ twoFactorEnabled: true })
.where(eq(users.id, user.id));
.where(eq(users.userId, user.userId));
const backupCodes = await generateBackupCodes();
codes = backupCodes;
@@ -77,7 +77,7 @@ export async function verifyTotp(
const hash = await hashPassword(code);
await db.insert(twoFactorBackupCodes).values({
userId: user.id,
userId: user.userId,
codeHash: hash,
});
}

View File

@@ -6,7 +6,7 @@ import createHttpError from 'http-errors';
import HttpCode from '@server/types/HttpCode';
export async function verifyUserAccess(req: Request, res: Response, next: NextFunction) {
const userId = req.user!.id; // Assuming you have user information in the request
const userId = req.user!.userId; // Assuming you have user information in the request
const reqUserId = req.params.userId || req.body.userId || req.query.userId;
if (!userId) {
@@ -18,7 +18,7 @@ export async function verifyUserAccess(req: Request, res: Response, next: NextFu
}
try {
const userOrg = await db.select()
.from(userOrgs)
.where(and(eq(userOrgs.userId, userId), eq(userOrgs.orgId, req.userOrgId!)))
@@ -34,4 +34,4 @@ export async function verifyUserAccess(req: Request, res: Response, next: NextFu
} catch (error) {
return next(createHttpError(HttpCode.INTERNAL_SERVER_ERROR, 'Error verifying site access'));
}
}
}