feat: comprehensive security and architecture improvements

- Add Zod validation schemas with strong password requirements (12+ chars, complexity)
- Implement rate limiting for authentication endpoints (registration, password reset)
- Remove duplicate MetricCard component, consolidate to ui/metric-card.tsx
- Update README.md to use pnpm commands consistently
- Enhance authentication security with 12-round bcrypt hashing
- Add comprehensive input validation for all API endpoints
- Fix security vulnerabilities in user registration and password reset flows

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-06-28 01:52:53 +02:00
parent 192f9497b4
commit 7f48a085bf
68 changed files with 8045 additions and 4542 deletions

View File

@ -1,7 +1,7 @@
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import { PrismaClient } from '@prisma/client';
import { describe, it, expect, beforeAll, afterAll } from "vitest";
import { PrismaClient } from "@prisma/client";
describe('Database Configuration', () => {
describe("Database Configuration", () => {
let prisma: PrismaClient;
beforeAll(() => {
@ -12,62 +12,62 @@ describe('Database Configuration', () => {
await prisma.$disconnect();
});
it('should connect to the test database', async () => {
it("should connect to the test database", async () => {
// Verify we can connect to the database
const result = await prisma.$queryRaw`SELECT 1 as test`;
expect(result).toBeDefined();
});
it('should use PostgreSQL as the database provider', async () => {
it("should use PostgreSQL as the database provider", async () => {
// Query the database to verify it's PostgreSQL
const result = await prisma.$queryRaw`SELECT version()` as any[];
expect(result[0].version).toContain('PostgreSQL');
const result = (await prisma.$queryRaw`SELECT version()`) as any[];
expect(result[0].version).toContain("PostgreSQL");
});
it('should be using the test database URL', () => {
it("should be using the test database URL", () => {
// Verify that DATABASE_URL is set to the test database
expect(process.env.DATABASE_URL).toBeDefined();
expect(process.env.DATABASE_URL).toContain('postgresql://');
expect(process.env.DATABASE_URL).toContain("postgresql://");
// If DATABASE_URL_TEST is set, DATABASE_URL should match it (from our test setup)
if (process.env.DATABASE_URL_TEST) {
expect(process.env.DATABASE_URL).toBe(process.env.DATABASE_URL_TEST);
}
});
it('should have all required tables', async () => {
it("should have all required tables", async () => {
// Verify all our tables exist
const tables = await prisma.$queryRaw`
const tables = (await prisma.$queryRaw`
SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'public'
AND table_type = 'BASE TABLE'
ORDER BY table_name
` as any[];
`) as any[];
const tableNames = tables.map(t => t.table_name);
expect(tableNames).toContain('Company');
expect(tableNames).toContain('User');
expect(tableNames).toContain('Session');
expect(tableNames).toContain('SessionImport');
expect(tableNames).toContain('Message');
expect(tableNames).toContain('Question');
expect(tableNames).toContain('SessionQuestion');
expect(tableNames).toContain('AIProcessingRequest');
const tableNames = tables.map((t) => t.table_name);
expect(tableNames).toContain("Company");
expect(tableNames).toContain("User");
expect(tableNames).toContain("Session");
expect(tableNames).toContain("SessionImport");
expect(tableNames).toContain("Message");
expect(tableNames).toContain("Question");
expect(tableNames).toContain("SessionQuestion");
expect(tableNames).toContain("AIProcessingRequest");
});
it('should be able to create and query data', async () => {
it("should be able to create and query data", async () => {
// Test basic CRUD operations
const company = await prisma.company.create({
data: {
name: 'Test Company',
csvUrl: 'https://example.com/test.csv',
name: "Test Company",
csvUrl: "https://example.com/test.csv",
},
});
expect(company.id).toBeDefined();
expect(company.name).toBe('Test Company');
expect(company.name).toBe("Test Company");
// Clean up
await prisma.company.delete({