diff --git a/attached_assets/image_1756817062713.png b/attached_assets/image_1756817062713.png new file mode 100644 index 0000000..823d911 Binary files /dev/null and b/attached_assets/image_1756817062713.png differ diff --git a/server/replitAuth.ts b/server/replitAuth.ts index 8411e88..9de7547 100644 --- a/server/replitAuth.ts +++ b/server/replitAuth.ts @@ -6,6 +6,7 @@ import type { Express, RequestHandler } from "express"; import memoize from "memoizee"; import connectPg from "connect-pg-simple"; import { storage } from "./storage"; +import { createHash } from "crypto"; if (!process.env.REPLIT_DOMAINS) { throw new Error("Environment variable REPLIT_DOMAINS not provided"); @@ -53,9 +54,23 @@ function updateUserSession( user.expires_at = user.claims?.exp; } +function generateDeterministicUUID(replitId: string): string { + // Create a deterministic UUID from Replit ID + // This ensures the same Replit user always gets the same UUID + const hash = createHash('sha256').update(`replit_${replitId}`).digest('hex'); + // Format as UUID v4: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx + return [ + hash.substring(0, 8), + hash.substring(8, 12), + '4' + hash.substring(13, 16), + (parseInt(hash.substring(16, 17), 16) & 0x3 | 0x8).toString(16) + hash.substring(17, 20), + hash.substring(20, 32) + ].join('-'); +} + async function upsertUser(claims: any) { - // Convert Replit numeric ID to string format compatible with our schema - const userId = `replit_${claims["sub"]}`; + // Generate a deterministic UUID from Replit ID + const userId = generateDeterministicUUID(claims["sub"]); await storage.upsertUser({ id: userId, @@ -163,8 +178,8 @@ export const isAdmin: RequestHandler = async (req, res, next) => { } try { - // Convert Replit numeric ID to our internal format - const userId = `replit_${user.claims.sub}`; + // Generate the same deterministic UUID from Replit ID + const userId = generateDeterministicUUID(user.claims.sub); const dbUser = await storage.getUser(userId); if (!dbUser || !dbUser.isAdmin) { return res.status(403).json({ message: "Admin access required" }); diff --git a/server/routes.ts b/server/routes.ts index aa78b69..7e8f709 100644 --- a/server/routes.ts +++ b/server/routes.ts @@ -860,9 +860,28 @@ export async function registerRoutes(app: Express): Promise { // Auth route to get current user app.get('/api/auth/user', isAuthenticated, async (req: any, res) => { try { - const userId = `replit_${req.user.claims.sub}`; + // Import the generateDeterministicUUID function from replitAuth + const { createHash } = await import('crypto'); + function generateDeterministicUUID(replitId: string): string { + const hash = createHash('sha256').update(`replit_${replitId}`).digest('hex'); + return [ + hash.substring(0, 8), + hash.substring(8, 12), + '4' + hash.substring(13, 16), + (parseInt(hash.substring(16, 17), 16) & 0x3 | 0x8).toString(16) + hash.substring(17, 20), + hash.substring(20, 32) + ].join('-'); + } + + const userId = generateDeterministicUUID(req.user.claims.sub); const user = await storage.getUser(userId); - res.json(user); + if (!user) { + return res.status(404).json({ message: "User not found" }); + } + + // Remove sensitive data + const { passwordHash, ...userResponse } = user; + res.json(userResponse); } catch (error) { console.error("Error fetching user:", error); res.status(500).json({ message: "Failed to fetch user" });