From a0f36968b3b44ca58239236fe07cbb767d34d89d Mon Sep 17 00:00:00 2001 From: chamikaJ Date: Thu, 29 May 2025 16:13:36 +0530 Subject: [PATCH] feat(auth): add debug logging for authentication processes - Introduced detailed console logging in the auth controller, deserialize, serialize, and passport strategies to aid in debugging authentication flows. - Enhanced error handling and response messaging during user registration and login processes, providing clearer feedback for success and failure scenarios. - Updated the signup and login functions to include more informative logs, improving traceability of user actions and system responses. --- .../src/controllers/auth-controller.ts | 21 +++++++- worklenz-backend/src/passport/deserialize.ts | 19 +++++++ .../passport-local-login.ts | 4 ++ .../passport-local-signup.ts | 50 +++++++++++++++---- worklenz-backend/src/passport/serialize.ts | 4 ++ 5 files changed, 88 insertions(+), 10 deletions(-) diff --git a/worklenz-backend/src/controllers/auth-controller.ts b/worklenz-backend/src/controllers/auth-controller.ts index 8364d59c..46370f2a 100644 --- a/worklenz-backend/src/controllers/auth-controller.ts +++ b/worklenz-backend/src/controllers/auth-controller.ts @@ -28,20 +28,39 @@ export default class AuthController extends WorklenzControllerBase { } public static verify(req: IWorkLenzRequest, res: IWorkLenzResponse) { + console.log("=== VERIFY DEBUG ==="); + console.log("req.user:", req.user); + console.log("req.isAuthenticated():", req.isAuthenticated()); + console.log("req.session.passport:", (req.session as any).passport); + console.log("req.query.strategy:", req.query.strategy); + // Flash messages sent from passport-local-signup.ts and passport-local-login.ts const errors = req.flash()["error"] || []; const messages = req.flash()["success"] || []; + + console.log("Flash errors:", errors); + console.log("Flash messages:", messages); + // If there are multiple messages, we will send one at a time. const auth_error = errors.length > 0 ? errors[0] : null; const message = messages.length > 0 ? messages[0] : null; const midTitle = req.query.strategy === "login" ? "Login Failed!" : "Signup Failed!"; const title = req.query.strategy ? midTitle : null; + + console.log("Title:", title); + console.log("Auth error:", auth_error); + console.log("Success message:", message); + console.log("Is authenticated:", req.isAuthenticated()); + console.log("Has user:", !!req.user); if (req.user) req.user.build_v = FileConstants.getRelease(); - return res.status(200).send(new AuthResponse(title, req.isAuthenticated(), req.user || null, auth_error, message)); + const response = new AuthResponse(title, req.isAuthenticated(), req.user || null, auth_error, message); + console.log("Sending response:", response); + + return res.status(200).send(response); } public static logout(req: IWorkLenzRequest, res: IWorkLenzResponse) { diff --git a/worklenz-backend/src/passport/deserialize.ts b/worklenz-backend/src/passport/deserialize.ts index bbbd5352..fa52fa7c 100644 --- a/worklenz-backend/src/passport/deserialize.ts +++ b/worklenz-backend/src/passport/deserialize.ts @@ -22,17 +22,30 @@ async function clearEmailInvitations(email: string, teamId: string) { // Check whether the user still exists on the database export async function deserialize(user: { id: string | null }, done: IDeserializeCallback) { try { + console.log("=== DESERIALIZE DEBUG ==="); + console.log("User object:", user); + if (!user || !user.id) { + console.log("No user or user.id, returning null"); return done(null, null); } const {id} = user; + console.log("Deserializing user ID:", id); + const excludedSubscriptionTypes = ["TRIAL", "PADDLE"]; const q = `SELECT deserialize_user($1) AS user;`; const result = await db.query(q, [id]); + + console.log("Database query result rows length:", result.rows.length); + if (result.rows.length) { const [data] = result.rows; + console.log("Database result data:", data); + if (data?.user) { + console.log("User data found:", data.user); + const realExpiredDate = moment(data.user.valid_till_date).add(7, "days"); data.user.is_expired = false; @@ -42,11 +55,17 @@ export async function deserialize(user: { id: string | null }, done: IDeserializ void setLastActive(data.user.id); void clearEmailInvitations(data.user.email, data.user.team_id); + console.log("Returning successful user:", data.user); return done(null, data.user as IPassportSession); } + console.log("No user data in result"); } + console.log("No rows returned from database"); + + console.log("Returning null user"); return done(null, null); } catch (error) { + console.log("Deserialize error:", error); return done(error, null); } } diff --git a/worklenz-backend/src/passport/passport-strategies/passport-local-login.ts b/worklenz-backend/src/passport/passport-strategies/passport-local-login.ts index 7d29fae8..259e3142 100644 --- a/worklenz-backend/src/passport/passport-strategies/passport-local-login.ts +++ b/worklenz-backend/src/passport/passport-strategies/passport-local-login.ts @@ -22,6 +22,7 @@ async function handleLogin(req: Request, email: string, password: string, done: console.log("User query result count:", result.rowCount); const [data] = result.rows; + console.log("data", data); if (!data?.password) { console.log("No account found"); @@ -33,6 +34,9 @@ async function handleLogin(req: Request, email: string, password: string, done: if (passwordMatch && email === data.email) { delete data.password; + console.log("=== LOGIN SUCCESS DEBUG ==="); + console.log("About to call done with user:", data); + console.log("User structure:", JSON.stringify(data, null, 2)); return done(null, data, {message: "User successfully logged in"}); } return done(null, false, { message: "Incorrect email or password" }); diff --git a/worklenz-backend/src/passport/passport-strategies/passport-local-signup.ts b/worklenz-backend/src/passport/passport-strategies/passport-local-signup.ts index 56395066..4e83706c 100644 --- a/worklenz-backend/src/passport/passport-strategies/passport-local-signup.ts +++ b/worklenz-backend/src/passport/passport-strategies/passport-local-signup.ts @@ -37,8 +37,15 @@ async function registerUser(password: string, team_id: string, name: string, tea team_member_id, }; + console.log("=== REGISTER USER DEBUG ==="); + console.log("Calling register_user with body:", body); + const result = await db.query(q, [JSON.stringify(body)]); const [data] = result.rows; + + console.log("Register user result:", data); + console.log("User object returned:", data.user); + return data.user; } @@ -47,41 +54,66 @@ async function handleSignUp(req: Request, email: string, password: string, done: // team = Invited team_id if req.body.from_invitation is true const {name, team_name, team_member_id, team_id, timezone} = req.body; - if (!team_name) return done(null, null, req.flash(ERROR_KEY, "Team name is required")); + if (!team_name) { + req.flash(ERROR_KEY, "Team name is required"); + return done(null, null, {message: "Team name is required"}); + } const googleAccountFound = await isGoogleAccountFound(email); - if (googleAccountFound) - return done(null, null, req.flash(ERROR_KEY, `${req.body.email} is already linked with a Google account.`)); + if (googleAccountFound) { + req.flash(ERROR_KEY, `${req.body.email} is already linked with a Google account.`); + return done(null, null, {message: `${req.body.email} is already linked with a Google account.`}); + } try { + console.log("=== SIGNUP DEBUG ==="); + console.log("About to register user with data:", {name, team_name, email, timezone, team_member_id, team_id}); + const user = await registerUser(password, team_id, name, team_name, email, timezone, team_member_id); + + console.log("User registration successful, user object:", user); + sendWelcomeEmail(email, name); - return done(null, user, req.flash(SUCCESS_KEY, "Registration successful. Please check your email for verification.")); + + console.log("About to call done with user:", user); + req.flash(SUCCESS_KEY, "Registration successful. Please check your email for verification."); + return done(null, user, {message: "Registration successful. Please check your email for verification."}); } catch (error: any) { + console.log("=== SIGNUP ERROR ==="); + console.log("Error during signup:", error); + const message = (error?.message) || ""; if (message === "ERROR_INVALID_JOINING_EMAIL") { - return done(null, null, req.flash(ERROR_KEY, `No invitations found for email ${req.body.email}.`)); + req.flash(ERROR_KEY, `No invitations found for email ${req.body.email}.`); + return done(null, null, {message: `No invitations found for email ${req.body.email}.`}); } // if error.message is "email already exists" then it should have the email address in the error message after ":". if (message.includes("EMAIL_EXISTS_ERROR") || error.constraint === "users_google_id_uindex") { const [, value] = error.message.split(":"); - return done(null, null, req.flash(ERROR_KEY, `Worklenz account already exists for email ${value}.`)); + const errorMsg = `Worklenz account already exists for email ${value}.`; + req.flash(ERROR_KEY, errorMsg); + return done(null, null, {message: errorMsg}); } if (message.includes("TEAM_NAME_EXISTS_ERROR")) { const [, value] = error.message.split(":"); - return done(null, null, req.flash(ERROR_KEY, `Team name "${value}" already exists. Please choose a different team name.`)); + const errorMsg = `Team name "${value}" already exists. Please choose a different team name.`; + req.flash(ERROR_KEY, errorMsg); + return done(null, null, {message: errorMsg}); } // The Team name is already taken. if (error.constraint === "teams_url_uindex" || error.constraint === "teams_name_uindex") { - return done(null, null, req.flash(ERROR_KEY, `Team name "${team_name}" is already taken. Please choose a different team name.`)); + const errorMsg = `Team name "${team_name}" is already taken. Please choose a different team name.`; + req.flash(ERROR_KEY, errorMsg); + return done(null, null, {message: errorMsg}); } log_error(error, req.body); - return done(null, null, req.flash(ERROR_KEY, DEFAULT_ERROR_MESSAGE)); + req.flash(ERROR_KEY, DEFAULT_ERROR_MESSAGE); + return done(null, null, {message: DEFAULT_ERROR_MESSAGE}); } } diff --git a/worklenz-backend/src/passport/serialize.ts b/worklenz-backend/src/passport/serialize.ts index b3c603f6..8b33136e 100644 --- a/worklenz-backend/src/passport/serialize.ts +++ b/worklenz-backend/src/passport/serialize.ts @@ -3,5 +3,9 @@ import {IPassportSession} from "../interfaces/passport-session"; // Parse the user id to deserialize function export function serialize($user: IPassportSession, done: ISerializeCallback) { + console.log("=== SERIALIZE DEBUG ==="); + console.log("Serializing user:", $user); + console.log("User ID:", $user?.id); + done(null, { id: $user?.id ?? null }); }