Work with DB fixed including default Admin creation
This commit is contained in:
@@ -9,7 +9,8 @@
|
|||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"dev:full": "npm-run-all --parallel dev \"dev --prefix server\"",
|
"dev:full": "npm-run-all --parallel dev \"dev --prefix server\"",
|
||||||
"dev:full:bg": "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",
|
"server:test": "npm run start:test --prefix server",
|
||||||
"test:full": "npm-run-all --parallel dev server:test"
|
"test:full": "npm-run-all --parallel dev server:test"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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();
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
30
server/check_adapter.ts
Normal file
30
server/check_adapter.ts
Normal file
@@ -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);
|
||||||
|
}
|
||||||
BIN
server/dev.db
BIN
server/dev.db
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "npm run start:prod",
|
"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",
|
"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",
|
"dev": "cross-env APP_MODE=dev ts-node-dev -r dotenv/config --respawn --transpile-only src/index.ts",
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
export default {
|
import 'dotenv/config';
|
||||||
|
import { defineConfig, env } from 'prisma/config';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
schema: 'prisma/schema.prisma',
|
||||||
datasource: {
|
datasource: {
|
||||||
url: process.env.DATABASE_URL || "file:./dev.db",
|
url: env('DATABASE_URL'),
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
BIN
server/prod.db
BIN
server/prod.db
Binary file not shown.
37
server/repro_login.ts
Normal file
37
server/repro_login.ts
Normal file
@@ -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();
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
import { PrismaClient } from '@prisma/client';
|
import { PrismaClient } from '@prisma/client';
|
||||||
import { PrismaBetterSqlite3 } from '@prisma/adapter-better-sqlite3';
|
import { PrismaBetterSqlite3 } from '@prisma/adapter-better-sqlite3';
|
||||||
|
|
||||||
// Ensure env vars are loaded
|
|
||||||
import 'dotenv/config';
|
import 'dotenv/config';
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
@@ -13,44 +11,46 @@ declare global {
|
|||||||
const mode = process.env.APP_MODE || 'dev';
|
const mode = process.env.APP_MODE || 'dev';
|
||||||
console.log(`[Prisma] Initializing in ${mode.toUpperCase()} mode`);
|
console.log(`[Prisma] Initializing in ${mode.toUpperCase()} mode`);
|
||||||
|
|
||||||
let dbUrl: string | undefined;
|
let dbPath: string;
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case 'test':
|
case 'test':
|
||||||
dbUrl = process.env.DATABASE_URL_TEST;
|
dbPath = process.env.DATABASE_URL_TEST || './test.db';
|
||||||
break;
|
break;
|
||||||
case 'prod':
|
case 'prod':
|
||||||
dbUrl = process.env.DATABASE_URL_PROD;
|
dbPath = process.env.DATABASE_URL_PROD || './prod.db';
|
||||||
break;
|
break;
|
||||||
case 'dev':
|
case 'dev':
|
||||||
default:
|
default:
|
||||||
dbUrl = process.env.DATABASE_URL_DEV;
|
dbPath = process.env.DATABASE_URL_DEV || './dev.db';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback to generic DATABASE_URL if specific one is missing
|
// Remove 'file:' prefix if present
|
||||||
if (!dbUrl) {
|
if (dbPath.startsWith('file:')) {
|
||||||
console.warn(`[Prisma] DATABASE_URL_${mode.toUpperCase()} not found, falling back to DATABASE_URL`);
|
dbPath = dbPath.slice(5);
|
||||||
dbUrl = process.env.DATABASE_URL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dbUrl) {
|
console.log('Initializing Prisma Client with database:', dbPath);
|
||||||
throw new Error(`DATABASE_URL environment variable is not set for mode ${mode}. Please check your .env file.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('Initializing Prisma Adapter with URL:', dbUrl);
|
let prisma: PrismaClient;
|
||||||
|
|
||||||
// Use the options object as required by the library definitions
|
try {
|
||||||
const adapter = new PrismaBetterSqlite3({ url: dbUrl });
|
const adapter = new PrismaBetterSqlite3({ url: dbPath });
|
||||||
|
|
||||||
const prisma =
|
prisma =
|
||||||
global.prisma ||
|
global.prisma ||
|
||||||
new PrismaClient({
|
new PrismaClient({
|
||||||
adapter,
|
adapter: adapter as any,
|
||||||
});
|
});
|
||||||
|
} catch (e: any) {
|
||||||
|
console.error('Failed to initialize Prisma Client:', e.message);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
if (process.env.NODE_ENV !== 'production') {
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
global.prisma = prisma;
|
global.prisma = prisma;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default prisma;
|
export default prisma;
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,11 @@ export const validate = (schema: ZodSchema<any>) => async (req: Request, res: Re
|
|||||||
params: req.params,
|
params: req.params,
|
||||||
});
|
});
|
||||||
return next();
|
return next();
|
||||||
} catch (error) {
|
} catch (error: any) {
|
||||||
return sendError(res, `Validation Error: ${JSON.stringify(error)}`, 400);
|
console.error('Validation error:', {
|
||||||
|
body: req.body,
|
||||||
|
error: error.errors || error
|
||||||
|
});
|
||||||
|
return sendError(res, `Validation Error: ${JSON.stringify(error.errors || error)}`, 400);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
BIN
server/test.db
BIN
server/test.db
Binary file not shown.
@@ -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.
|
|
||||||
});
|
|
||||||
Reference in New Issue
Block a user