import { APIError } from "better-auth/api"; import { fromNodeHeaders } from "better-auth/node"; import { eq } from "drizzle-orm"; import { Router } from "express"; import z from "zod"; import { db } from "../db/db.controller.js"; import { user } from "../db/schema/auth.schema.js"; import { auth } from "../utils/auth.utils.js"; import { apiReturn } from "../utils/returnHelper.utils.js"; // interface EmailLoginRequest { // email: string; // password: string; // } // interface LoginResponse { // redirect: boolean; // token: string; // user: { // name: string; // email: string; // emailVerified: boolean; // image: string | null; // createdAt: string; // updatedAt: string; // role: string; // banned: boolean; // banReason: string | null; // banExpires: string | null; // username: string; // displayUsername: string; // lastLogin: string; // id: string; // }; // } const base = { password: z.string().min(8, "Password must be at least 8 characters"), }; const signin = z.union([ z.object({ ...base, email: z.email(), username: z.undefined(), }), z.object({ ...base, username: z.string(), email: z.undefined(), }), ]); const r = Router(); r.post("/", async (req, res) => { let login: unknown | any; try { const validated = signin.parse(req.body); if ("email" in validated) { login = await auth.api.signInEmail({ body: { email: validated.email as string, password: validated.password, }, headers: fromNodeHeaders(req.headers), }); } if ("username" in validated) { const getEmail = await db .select({ email: user.email }) .from(user) .where(eq(user.username, validated.username as string)); if (getEmail.length === 0) { return apiReturn(res, { success: false, level: "error", //connect.success ? "info" : "error", module: "routes", subModule: "auth", message: `${validated.username} dose not appear to be a valid username please try again`, data: [], status: 401, //connect.success ? 200 : 400, }); } // do the login with email login = await auth.api.signInEmail({ body: { email: getEmail[0]?.email as string, password: validated.password, }, headers: fromNodeHeaders(req.headers), asResponse: true, }); login.headers.forEach((value: string, key: string) => { if (key.toLowerCase() === "set-cookie") { res.append("set-cookie", value); } else { res.setHeader(key, value); } }); } // make sure we update the lastLogin // if (login?.user?.id) { // const updated = await db // .update(user) // .set({ lastLogin: sql`NOW()` }) // .where(eq(user.id, login.user.id)) // .returning({ lastLogin: user.lastLogin }); // const lastLoginTimestamp = updated[0]?.lastLogin; // console.log("Updated lastLogin:", lastLoginTimestamp); // } else // console.warn("User ID unavailable — skipping lastLogin update"); return apiReturn(res, { success: true, level: "info", //connect.success ? "info" : "error", module: "routes", subModule: "auth", message: `Welcome back ${validated.username}`, data: [login], status: 200, //connect.success ? 200 : 400, }); } catch (err) { if (err instanceof z.ZodError) { const flattened = z.flattenError(err); // return res.status(400).json({ // error: "Validation failed", // details: flattened, // }); return apiReturn(res, { success: false, level: "error", //connect.success ? "info" : "error", module: "routes", subModule: "auth", message: "Validation failed", data: [flattened.fieldErrors], status: 400, //connect.success ? 200 : 400, }); } if (err instanceof APIError) { return apiReturn(res, { success: false, level: "error", //connect.success ? "info" : "error", module: "routes", subModule: "auth", message: err.message, data: [err.status], status: 400, //connect.success ? 200 : 400, }); } return apiReturn(res, { success: false, level: "error", module: "routes", subModule: "auth", message: "System Error", data: [err], status: 400, }); } }); export default r;