diff --git a/package.json b/package.json index 97c22eb..97aacc6 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "preview": "vite preview", "dev:full": "npm-run-all --parallel dev \"dev --prefix server\"", "dev:full:bg": "npm-run-all --parallel dev \"dev --prefix server\" &", - "prod:full": "npm-run-all --parallel preview \"start:prod --prefix server\"", + "prod:full": "npm-run-all --parallel preview server:prod", + "server:prod": "npm run start:prod --prefix server", "server:test": "npm run start:test --prefix server", "test:full": "npm-run-all --parallel dev server:test" }, diff --git a/server/admin_check.js b/server/admin_check.js deleted file mode 100644 index 2dd4d96..0000000 --- a/server/admin_check.js +++ /dev/null @@ -1,12 +0,0 @@ -const { PrismaClient } = require('@prisma/client'); -(async () => { - const prisma = new PrismaClient(); - try { - const admin = await prisma.user.findFirst({ where: { role: 'ADMIN' } }); - console.log('Admin user:', admin); - } catch (e) { - console.error('Error:', e); - } finally { - await prisma.$disconnect(); - } -})(); diff --git a/server/check_adapter.ts b/server/check_adapter.ts new file mode 100644 index 0000000..cc52126 --- /dev/null +++ b/server/check_adapter.ts @@ -0,0 +1,30 @@ + +import { PrismaBetterSqlite3 } from '@prisma/adapter-better-sqlite3'; +import Database from 'better-sqlite3'; + +try { + console.log("Attempting incorrect usage..."); + // @ts-ignore + new PrismaBetterSqlite3({ url: 'file:./dev.db' }); + console.log("Incorrect usage presumed worked? (Unexpected)"); +} catch (e) { + console.log("Incorrect usage failed as expected:", e.message); +} + +try { + console.log("Attempting correct usage..."); + const db = new Database('./dev.db'); + new PrismaBetterSqlite3(db); + console.log("Correct usage worked."); +} catch (e) { + console.log("Correct usage failed:", e); +} + +try { + console.log("Attempting correct usage with file: prefix..."); + const db = new Database('file:./dev.db'); + new PrismaBetterSqlite3(db); + console.log("Correct usage with prefix worked."); +} catch (e) { + console.log("Correct usage with prefix failed:", e.message); +} diff --git a/server/dev.db b/server/dev.db index fd39be3..e69de29 100644 Binary files a/server/dev.db and b/server/dev.db differ diff --git a/server/package.json b/server/package.json index ca9c69b..56a9361 100644 --- a/server/package.json +++ b/server/package.json @@ -5,7 +5,7 @@ "main": "src/index.ts", "scripts": { "start": "npm run start:prod", - "start:prod": "cross-env APP_MODE=prod node dist/index.js", + "start:prod": "cross-env APP_MODE=prod DATABASE_URL=file:./prod.db npx prisma db push && cross-env APP_MODE=prod DATABASE_URL_PROD=file:./prod.db ts-node-dev -r dotenv/config --respawn --transpile-only src/index.ts", "start:test": "cross-env APP_MODE=test DATABASE_URL=file:./test.db DATABASE_URL_TEST=file:./test.db npx prisma db push --accept-data-loss && cross-env APP_MODE=test DATABASE_URL_TEST=file:./test.db ts-node-dev -r dotenv/config --respawn --transpile-only src/index.ts", "dev": "cross-env APP_MODE=dev ts-node-dev -r dotenv/config --respawn --transpile-only src/index.ts", "build": "tsc", diff --git a/server/prisma.config.ts b/server/prisma.config.ts index fe69e01..4f1306e 100644 --- a/server/prisma.config.ts +++ b/server/prisma.config.ts @@ -1,5 +1,9 @@ -export default { +import 'dotenv/config'; +import { defineConfig, env } from 'prisma/config'; + +export default defineConfig({ + schema: 'prisma/schema.prisma', datasource: { - url: process.env.DATABASE_URL || "file:./dev.db", + url: env('DATABASE_URL'), }, -}; +}); diff --git a/server/prisma/dev.db b/server/prisma/dev.db index a3984b6..a8455d4 100644 Binary files a/server/prisma/dev.db and b/server/prisma/dev.db differ diff --git a/server/prisma/prod.db b/server/prisma/prod.db index 48dc7ec..607ce3b 100644 Binary files a/server/prisma/prod.db and b/server/prisma/prod.db differ diff --git a/server/prod.db b/server/prod.db index e2ae7a7..05771a2 100644 Binary files a/server/prod.db and b/server/prod.db differ diff --git a/server/repro_login.ts b/server/repro_login.ts new file mode 100644 index 0000000..2654674 --- /dev/null +++ b/server/repro_login.ts @@ -0,0 +1,37 @@ + +import { AuthService } from './src/services/auth.service'; +import prisma from './src/lib/prisma'; +import bcrypt from 'bcryptjs'; + +// const prisma = new PrismaClient(); // Removed local instance + +async function run() { + try { + console.log("Setting up test user..."); + const email = 'repro_user@gymflow.ai'; + const password = 'password123'; + const hashed = await bcrypt.hash(password, 10); + + await prisma.user.upsert({ + where: { email }, + update: { password: hashed, isBlocked: false }, + create: { + email, + password: hashed, + role: 'USER', + profile: { create: { weight: 70 } } + } + }); + + console.log("Attempting login..."); + const result = await AuthService.login(email, password); + console.log("Login success:", result ? "OK" : "No result"); + } catch (error) { + console.error("Login failed with error:"); + console.error(error); + } finally { + await prisma.$disconnect(); + } +} + +run(); diff --git a/server/src/lib/prisma.ts b/server/src/lib/prisma.ts index 646bfe5..bf89831 100644 --- a/server/src/lib/prisma.ts +++ b/server/src/lib/prisma.ts @@ -1,7 +1,5 @@ import { PrismaClient } from '@prisma/client'; import { PrismaBetterSqlite3 } from '@prisma/adapter-better-sqlite3'; - -// Ensure env vars are loaded import 'dotenv/config'; declare global { @@ -13,44 +11,46 @@ declare global { const mode = process.env.APP_MODE || 'dev'; console.log(`[Prisma] Initializing in ${mode.toUpperCase()} mode`); -let dbUrl: string | undefined; +let dbPath: string; switch (mode) { case 'test': - dbUrl = process.env.DATABASE_URL_TEST; + dbPath = process.env.DATABASE_URL_TEST || './test.db'; break; case 'prod': - dbUrl = process.env.DATABASE_URL_PROD; + dbPath = process.env.DATABASE_URL_PROD || './prod.db'; break; case 'dev': default: - dbUrl = process.env.DATABASE_URL_DEV; + dbPath = process.env.DATABASE_URL_DEV || './dev.db'; break; } -// Fallback to generic DATABASE_URL if specific one is missing -if (!dbUrl) { - console.warn(`[Prisma] DATABASE_URL_${mode.toUpperCase()} not found, falling back to DATABASE_URL`); - dbUrl = process.env.DATABASE_URL; +// Remove 'file:' prefix if present +if (dbPath.startsWith('file:')) { + dbPath = dbPath.slice(5); } -if (!dbUrl) { - throw new Error(`DATABASE_URL environment variable is not set for mode ${mode}. Please check your .env file.`); +console.log('Initializing Prisma Client with database:', dbPath); + +let prisma: PrismaClient; + +try { + const adapter = new PrismaBetterSqlite3({ url: dbPath }); + + prisma = + global.prisma || + new PrismaClient({ + adapter: adapter as any, + }); +} catch (e: any) { + console.error('Failed to initialize Prisma Client:', e.message); + process.exit(1); } -console.log('Initializing Prisma Adapter with URL:', dbUrl); - -// Use the options object as required by the library definitions -const adapter = new PrismaBetterSqlite3({ url: dbUrl }); - -const prisma = - global.prisma || - new PrismaClient({ - adapter, - }); - if (process.env.NODE_ENV !== 'production') { global.prisma = prisma; } export default prisma; + diff --git a/server/src/middleware/validate.ts b/server/src/middleware/validate.ts index c30d41f..8765f82 100644 --- a/server/src/middleware/validate.ts +++ b/server/src/middleware/validate.ts @@ -10,7 +10,11 @@ export const validate = (schema: ZodSchema) => async (req: Request, res: Re params: req.params, }); return next(); - } catch (error) { - return sendError(res, `Validation Error: ${JSON.stringify(error)}`, 400); + } catch (error: any) { + console.error('Validation error:', { + body: req.body, + error: error.errors || error + }); + return sendError(res, `Validation Error: ${JSON.stringify(error.errors || error)}`, 400); } }; diff --git a/server/test.db b/server/test.db index 24ada2b..98b1294 100644 Binary files a/server/test.db and b/server/test.db differ diff --git a/server/test_user.js b/server/test_user.js deleted file mode 100644 index 2fe8e29..0000000 --- a/server/test_user.js +++ /dev/null @@ -1,64 +0,0 @@ -import { PrismaClient } from '@prisma/client'; -import bcrypt from 'bcryptjs'; - -async function createTestUsers() { - const prisma = new PrismaClient(); - - // Create a regular user - const user1Email = 'user1@gymflow.ai'; - const user1Password = 'user1pass'; - const hashedUser1Password = await bcrypt.hash(user1Password, 10); - await prisma.user.upsert({ - where: { email: user1Email }, - update: { password: hashedUser1Password }, - create: { - email: user1Email, - password: hashedUser1Password, - role: 'USER', - profile: { create: { weight: 70 } }, - }, - }); - - // Create another regular user - const user2Email = 'user2@gymflow.ai'; - const user2Password = 'user2pass'; - const hashedUser2Password = await bcrypt.hash(user2Password, 10); - await prisma.user.upsert({ - where: { email: user2Email }, - update: { password: hashedUser2Password }, - create: { - email: user2Email, - password: hashedUser2Password, - role: 'USER', - profile: { create: { weight: 75 } }, - }, - }); - - // Create a user that will be blocked - const blockedUserEmail = 'blocked@gymflow.ai'; - const blockedUserPassword = 'blockedpass'; - const hashedBlockedUserPassword = await bcrypt.hash(blockedUserPassword, 10); - await prisma.user.upsert({ - where: { email: blockedUserEmail }, - update: { password: hashedBlockedUserPassword, isBlocked: true }, - create: { - email: blockedUserEmail, - password: hashedBlockedUserPassword, - role: 'USER', - isBlocked: true, - profile: { create: { weight: 80 } }, - }, - }); - - console.log('Test users created or updated successfully.'); - await prisma.$disconnect(); -} - -createTestUsers() - .catch((e) => { - console.error(e); - process.exit(1); - }) - .finally(async () => { - // This script is meant to be run once to seed data, so we don't need to keep it running. - });