mirror of
https://github.com/9technologygroup/patchmon.net.git
synced 2025-11-11 09:27:30 +00:00
Fixed TFA fingerprint sending in CORS
Ammended firstname and lastname adding issue in profile
This commit is contained in:
@@ -1030,12 +1030,21 @@ router.put(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { username, email, first_name, last_name } = req.body;
|
const { username, email, first_name, last_name } = req.body;
|
||||||
const updateData = {};
|
const updateData = {
|
||||||
|
updated_at: new Date(),
|
||||||
|
};
|
||||||
|
|
||||||
if (username) updateData.username = username;
|
if (username) updateData.username = username;
|
||||||
if (email) updateData.email = email;
|
if (email) updateData.email = email;
|
||||||
if (first_name !== undefined) updateData.first_name = first_name || null;
|
// Handle first_name and last_name - allow empty strings to clear the field
|
||||||
if (last_name !== undefined) updateData.last_name = last_name || null;
|
if (first_name !== undefined) {
|
||||||
|
updateData.first_name =
|
||||||
|
first_name === "" ? null : first_name.trim() || null;
|
||||||
|
}
|
||||||
|
if (last_name !== undefined) {
|
||||||
|
updateData.last_name =
|
||||||
|
last_name === "" ? null : last_name.trim() || null;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if username/email already exists (excluding current user)
|
// Check if username/email already exists (excluding current user)
|
||||||
if (username || email) {
|
if (username || email) {
|
||||||
@@ -1060,6 +1069,7 @@ router.put(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update user with explicit commit
|
||||||
const updatedUser = await prisma.users.update({
|
const updatedUser = await prisma.users.update({
|
||||||
where: { id: req.user.id },
|
where: { id: req.user.id },
|
||||||
data: updateData,
|
data: updateData,
|
||||||
@@ -1076,9 +1086,39 @@ router.put(
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Explicitly refresh user data from database to ensure we return latest data
|
||||||
|
// This ensures consistency especially in high-concurrency scenarios
|
||||||
|
const freshUser = await prisma.users.findUnique({
|
||||||
|
where: { id: req.user.id },
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
username: true,
|
||||||
|
email: true,
|
||||||
|
first_name: true,
|
||||||
|
last_name: true,
|
||||||
|
role: true,
|
||||||
|
is_active: true,
|
||||||
|
last_login: true,
|
||||||
|
updated_at: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Use fresh data if available, otherwise fallback to updatedUser
|
||||||
|
const responseUser = freshUser || updatedUser;
|
||||||
|
|
||||||
|
// Log update for debugging (only log in non-production)
|
||||||
|
if (process.env.NODE_ENV !== "production") {
|
||||||
|
console.log("Profile updated:", {
|
||||||
|
userId: req.user.id,
|
||||||
|
first_name: responseUser.first_name,
|
||||||
|
last_name: responseUser.last_name,
|
||||||
|
updated_at: responseUser.updated_at,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
message: "Profile updated successfully",
|
message: "Profile updated successfully",
|
||||||
user: updatedUser,
|
user: responseUser,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Update profile error:", error);
|
console.error("Update profile error:", error);
|
||||||
|
|||||||
@@ -387,6 +387,7 @@ app.use(
|
|||||||
"Authorization",
|
"Authorization",
|
||||||
"Cookie",
|
"Cookie",
|
||||||
"X-Requested-With",
|
"X-Requested-With",
|
||||||
|
"X-Device-ID", // Allow device ID header for TFA remember-me functionality
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@@ -558,299 +559,6 @@ app.use(`/bullboard`, (req, res, next) => {
|
|||||||
return res.status(503).json({ error: "Bull Board not initialized yet" });
|
return res.status(503).json({ error: "Bull Board not initialized yet" });
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
|
||||||
// OLD MIDDLEWARE - REMOVED FOR SIMPLIFICATION - DO NOT USE
|
|
||||||
if (false) {
|
|
||||||
const sessionId = req.cookies["bull-board-session"];
|
|
||||||
console.log("Bull Board API call - Session ID:", sessionId ? "present" : "missing");
|
|
||||||
console.log("Bull Board API call - Cookies:", req.cookies);
|
|
||||||
console.log("Bull Board API call - Bull Board token cookie:", req.cookies["bull-board-token"] ? "present" : "missing");
|
|
||||||
console.log("Bull Board API call - Query token:", req.query.token ? "present" : "missing");
|
|
||||||
console.log("Bull Board API call - Auth header:", req.headers.authorization ? "present" : "missing");
|
|
||||||
console.log("Bull Board API call - Origin:", req.headers.origin || "missing");
|
|
||||||
console.log("Bull Board API call - Referer:", req.headers.referer || "missing");
|
|
||||||
|
|
||||||
// Check if we have any authentication method available
|
|
||||||
const hasSession = !!sessionId;
|
|
||||||
const hasTokenCookie = !!req.cookies["bull-board-token"];
|
|
||||||
const hasQueryToken = !!req.query.token;
|
|
||||||
const hasAuthHeader = !!req.headers.authorization;
|
|
||||||
const hasReferer = !!req.headers.referer;
|
|
||||||
|
|
||||||
console.log("Bull Board API call - Auth methods available:", {
|
|
||||||
session: hasSession,
|
|
||||||
tokenCookie: hasTokenCookie,
|
|
||||||
queryToken: hasQueryToken,
|
|
||||||
authHeader: hasAuthHeader,
|
|
||||||
referer: hasReferer
|
|
||||||
});
|
|
||||||
|
|
||||||
// Check for valid session first
|
|
||||||
if (sessionId) {
|
|
||||||
const session = bullBoardSessions.get(sessionId);
|
|
||||||
console.log("Bull Board API call - Session found:", !!session);
|
|
||||||
if (session && Date.now() - session.timestamp < 3600000) {
|
|
||||||
// Valid session, extend it
|
|
||||||
session.timestamp = Date.now();
|
|
||||||
console.log("Bull Board API call - Using existing session, proceeding");
|
|
||||||
return next();
|
|
||||||
} else if (session) {
|
|
||||||
// Expired session, remove it
|
|
||||||
console.log("Bull Board API call - Session expired, removing");
|
|
||||||
bullBoardSessions.delete(sessionId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// No valid session, check for token as fallback
|
|
||||||
let token = req.query.token;
|
|
||||||
if (!token && req.headers.authorization) {
|
|
||||||
token = req.headers.authorization.replace("Bearer ", "");
|
|
||||||
}
|
|
||||||
if (!token && req.cookies["bull-board-token"]) {
|
|
||||||
token = req.cookies["bull-board-token"];
|
|
||||||
}
|
|
||||||
|
|
||||||
// For API calls, also check if the token is in the referer URL
|
|
||||||
// This handles cases where the main page hasn't set the cookie yet
|
|
||||||
if (!token && req.headers.referer) {
|
|
||||||
try {
|
|
||||||
const refererUrl = new URL(req.headers.referer);
|
|
||||||
const refererToken = refererUrl.searchParams.get('token');
|
|
||||||
if (refererToken) {
|
|
||||||
token = refererToken;
|
|
||||||
console.log("Bull Board API call - Token found in referer URL:", refererToken.substring(0, 20) + "...");
|
|
||||||
} else {
|
|
||||||
console.log("Bull Board API call - No token found in referer URL");
|
|
||||||
// If no token in referer and no session, return 401 with redirect info
|
|
||||||
if (!sessionId) {
|
|
||||||
console.log("Bull Board API call - No authentication available, returning 401");
|
|
||||||
return res.status(401).json({
|
|
||||||
error: "Authentication required",
|
|
||||||
message: "Please refresh the page to re-authenticate"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log("Bull Board API call - Error parsing referer URL:", error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (token) {
|
|
||||||
console.log("Bull Board API call - Token found, authenticating");
|
|
||||||
// Add token to headers for authentication
|
|
||||||
req.headers.authorization = `Bearer ${token}`;
|
|
||||||
|
|
||||||
// Authenticate the user
|
|
||||||
return authenticateToken(req, res, (err) => {
|
|
||||||
if (err) {
|
|
||||||
console.log("Bull Board API call - Token authentication failed");
|
|
||||||
return res.status(401).json({ error: "Authentication failed" });
|
|
||||||
}
|
|
||||||
return requireAdmin(req, res, (adminErr) => {
|
|
||||||
if (adminErr) {
|
|
||||||
console.log("Bull Board API call - Admin access required");
|
|
||||||
return res.status(403).json({ error: "Admin access required" });
|
|
||||||
}
|
|
||||||
console.log("Bull Board API call - Token authentication successful");
|
|
||||||
return next();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// No valid session or token for API calls, deny access
|
|
||||||
console.log("Bull Board API call - No valid session or token, denying access");
|
|
||||||
return res.status(401).json({ error: "Valid Bull Board session or token required" });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for bull-board-session cookie first
|
|
||||||
const sessionId = req.cookies["bull-board-session"];
|
|
||||||
if (sessionId) {
|
|
||||||
const session = bullBoardSessions.get(sessionId);
|
|
||||||
if (session && Date.now() - session.timestamp < 3600000) {
|
|
||||||
// 1 hour
|
|
||||||
// Valid session, extend it
|
|
||||||
session.timestamp = Date.now();
|
|
||||||
return next();
|
|
||||||
} else if (session) {
|
|
||||||
// Expired session, remove it
|
|
||||||
bullBoardSessions.delete(sessionId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// No valid session, check for token
|
|
||||||
let token = req.query.token;
|
|
||||||
if (!token && req.headers.authorization) {
|
|
||||||
token = req.headers.authorization.replace("Bearer ", "");
|
|
||||||
}
|
|
||||||
if (!token && req.cookies["bull-board-token"]) {
|
|
||||||
token = req.cookies["bull-board-token"];
|
|
||||||
}
|
|
||||||
|
|
||||||
// If no token, deny access
|
|
||||||
if (!token) {
|
|
||||||
return res.status(401).json({ error: "Access token required" });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add token to headers for authentication
|
|
||||||
req.headers.authorization = `Bearer ${token}`;
|
|
||||||
|
|
||||||
// Authenticate the user
|
|
||||||
return authenticateToken(req, res, (err) => {
|
|
||||||
if (err) {
|
|
||||||
return res.status(401).json({ error: "Authentication failed" });
|
|
||||||
}
|
|
||||||
return requireAdmin(req, res, (adminErr) => {
|
|
||||||
if (adminErr) {
|
|
||||||
return res.status(403).json({ error: "Admin access required" });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Authentication successful - create a session
|
|
||||||
const newSessionId = require("node:crypto")
|
|
||||||
.randomBytes(32)
|
|
||||||
.toString("hex");
|
|
||||||
bullBoardSessions.set(newSessionId, {
|
|
||||||
timestamp: Date.now(),
|
|
||||||
userId: req.user.id,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Set session cookie with proper configuration for domain access
|
|
||||||
const isHttps = process.env.NODE_ENV === "production" || process.env.SERVER_PROTOCOL === "https";
|
|
||||||
const cookieOptions = {
|
|
||||||
httpOnly: true,
|
|
||||||
secure: isHttps,
|
|
||||||
maxAge: 3600000, // 1 hour
|
|
||||||
path: "/", // Set path to root so it's available for all Bull Board requests
|
|
||||||
};
|
|
||||||
|
|
||||||
// Configure sameSite based on protocol and environment
|
|
||||||
if (isHttps) {
|
|
||||||
cookieOptions.sameSite = "none"; // Required for HTTPS cross-origin
|
|
||||||
} else {
|
|
||||||
cookieOptions.sameSite = "lax"; // Better for HTTP same-origin
|
|
||||||
}
|
|
||||||
|
|
||||||
res.cookie("bull-board-session", newSessionId, cookieOptions);
|
|
||||||
|
|
||||||
// Clean up old sessions periodically
|
|
||||||
if (bullBoardSessions.size > 100) {
|
|
||||||
const now = Date.now();
|
|
||||||
for (const [sid, session] of bullBoardSessions.entries()) {
|
|
||||||
if (now - session.timestamp > 3600000) {
|
|
||||||
bullBoardSessions.delete(sid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return next();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Second middleware block - COMMENTED OUT - using simplified version above instead
|
|
||||||
/*
|
|
||||||
app.use(`/bullboard`, (req, res, next) => {
|
|
||||||
if (bullBoardRouter) {
|
|
||||||
// If this is the main Bull Board page (not an API call), inject the token and create session
|
|
||||||
if (!req.path.includes("/api/") && !req.path.includes("/static/") && req.path === "/bullboard") {
|
|
||||||
const token = req.query.token;
|
|
||||||
console.log("Bull Board main page - Token:", token ? "present" : "missing");
|
|
||||||
console.log("Bull Board main page - Query params:", req.query);
|
|
||||||
console.log("Bull Board main page - Origin:", req.headers.origin || "missing");
|
|
||||||
console.log("Bull Board main page - Referer:", req.headers.referer || "missing");
|
|
||||||
console.log("Bull Board main page - Cookies:", req.cookies);
|
|
||||||
|
|
||||||
if (token) {
|
|
||||||
// Authenticate the user and create a session immediately on page load
|
|
||||||
req.headers.authorization = `Bearer ${token}`;
|
|
||||||
|
|
||||||
return authenticateToken(req, res, (err) => {
|
|
||||||
if (err) {
|
|
||||||
console.log("Bull Board main page - Token authentication failed");
|
|
||||||
return res.status(401).json({ error: "Authentication failed" });
|
|
||||||
}
|
|
||||||
return requireAdmin(req, res, (adminErr) => {
|
|
||||||
if (adminErr) {
|
|
||||||
console.log("Bull Board main page - Admin access required");
|
|
||||||
return res.status(403).json({ error: "Admin access required" });
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("Bull Board main page - Token authentication successful, creating session");
|
|
||||||
|
|
||||||
// Create a Bull Board session immediately
|
|
||||||
const newSessionId = require("node:crypto")
|
|
||||||
.randomBytes(32)
|
|
||||||
.toString("hex");
|
|
||||||
bullBoardSessions.set(newSessionId, {
|
|
||||||
timestamp: Date.now(),
|
|
||||||
userId: req.user.id,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Set session cookie with proper configuration for domain access
|
|
||||||
const sessionCookieOptions = {
|
|
||||||
httpOnly: true,
|
|
||||||
secure: false, // Always false for HTTP
|
|
||||||
maxAge: 3600000, // 1 hour
|
|
||||||
path: "/", // Set path to root so it's available for all Bull Board requests
|
|
||||||
sameSite: "lax", // Always lax for HTTP
|
|
||||||
};
|
|
||||||
|
|
||||||
res.cookie("bull-board-session", newSessionId, sessionCookieOptions);
|
|
||||||
console.log("Bull Board main page - Session created:", newSessionId);
|
|
||||||
console.log("Bull Board main page - Cookie options:", sessionCookieOptions);
|
|
||||||
|
|
||||||
// Also set a token cookie for API calls as a fallback
|
|
||||||
const tokenCookieOptions = {
|
|
||||||
httpOnly: false, // Allow JavaScript to access it
|
|
||||||
secure: false, // Always false for HTTP
|
|
||||||
maxAge: 3600000, // 1 hour
|
|
||||||
path: "/", // Set path to root for broader compatibility
|
|
||||||
sameSite: "lax", // Always lax for HTTP
|
|
||||||
};
|
|
||||||
|
|
||||||
res.cookie("bull-board-token", token, tokenCookieOptions);
|
|
||||||
console.log("Bull Board main page - Token cookie also set for API fallback");
|
|
||||||
|
|
||||||
// Clean up old sessions periodically
|
|
||||||
if (bullBoardSessions.size > 100) {
|
|
||||||
const now = Date.now();
|
|
||||||
for (const [sid, session] of bullBoardSessions.entries()) {
|
|
||||||
if (now - session.timestamp > 3600000) {
|
|
||||||
bullBoardSessions.delete(sid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now proceed to serve the Bull Board page
|
|
||||||
return bullBoardRouter(req, res, next);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.log("Bull Board main page - No token provided, checking for existing session");
|
|
||||||
// Check if we have an existing session
|
|
||||||
const sessionId = req.cookies["bull-board-session"];
|
|
||||||
if (sessionId) {
|
|
||||||
const session = bullBoardSessions.get(sessionId);
|
|
||||||
if (session && Date.now() - session.timestamp < 3600000) {
|
|
||||||
console.log("Bull Board main page - Using existing session");
|
|
||||||
// Extend session
|
|
||||||
session.timestamp = Date.now();
|
|
||||||
return bullBoardRouter(req, res, next);
|
|
||||||
} else if (session) {
|
|
||||||
console.log("Bull Board main page - Session expired, removing");
|
|
||||||
bullBoardSessions.delete(sessionId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.log("Bull Board main page - No valid session, denying access");
|
|
||||||
return res.status(401).json({ error: "Access token required" });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return bullBoardRouter(req, res, next);
|
|
||||||
}
|
|
||||||
return res.status(503).json({ error: "Bull Board not initialized yet" });
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Error handler specifically for Bull Board routes
|
// Error handler specifically for Bull Board routes
|
||||||
app.use("/bullboard", (err, req, res, _next) => {
|
app.use("/bullboard", (err, req, res, _next) => {
|
||||||
console.error("Bull Board error on", req.method, req.url);
|
console.error("Bull Board error on", req.method, req.url);
|
||||||
|
|||||||
@@ -224,8 +224,30 @@ export const AuthProvider = ({ children }) => {
|
|||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
|
console.log("Profile updated - received user data:", data.user);
|
||||||
|
|
||||||
|
// Validate that we received user data with expected fields
|
||||||
|
if (!data.user || !data.user.id) {
|
||||||
|
console.error("Invalid user data in response:", data);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: "Invalid response from server",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update both state and localStorage atomically
|
||||||
setUser(data.user);
|
setUser(data.user);
|
||||||
localStorage.setItem("user", JSON.stringify(data.user));
|
localStorage.setItem("user", JSON.stringify(data.user));
|
||||||
|
|
||||||
|
// Log update for debugging (only in non-production)
|
||||||
|
if (process.env.NODE_ENV !== "production") {
|
||||||
|
console.log("User data updated in localStorage:", {
|
||||||
|
id: data.user.id,
|
||||||
|
first_name: data.user.first_name,
|
||||||
|
last_name: data.user.last_name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return { success: true, user: data.user };
|
return { success: true, user: data.user };
|
||||||
} else {
|
} else {
|
||||||
// Handle HTTP error responses (like 500 CORS errors)
|
// Handle HTTP error responses (like 500 CORS errors)
|
||||||
|
|||||||
@@ -80,8 +80,10 @@ const Profile = () => {
|
|||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
setMessage({ type: "", text: "" });
|
setMessage({ type: "", text: "" });
|
||||||
|
|
||||||
|
console.log("Submitting profile data:", profileData);
|
||||||
try {
|
try {
|
||||||
const result = await updateProfile(profileData);
|
const result = await updateProfile(profileData);
|
||||||
|
console.log("Profile update result:", result);
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
setMessage({ type: "success", text: "Profile updated successfully!" });
|
setMessage({ type: "success", text: "Profile updated successfully!" });
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user