test the login yourself4

This commit is contained in:
Leon Serfaty G
2025-09-01 07:24:29 +00:00
parent fa221bbdc1
commit c5ebbc5f77
8 changed files with 136 additions and 113 deletions
+3 -1
View File
@@ -1,8 +1,9 @@
import { NextRequest, NextResponse } from 'next/server'; import { NextRequest, NextResponse } from 'next/server';
import db from '@/lib/db'; import getDb from '@/lib/db';
export async function GET(req: NextRequest) { export async function GET(req: NextRequest) {
const db = getDb();
try { try {
const stmt = db.prepare('SELECT value FROM settings WHERE key = ?'); const stmt = db.prepare('SELECT value FROM settings WHERE key = ?');
const setting = stmt.get('hourly_rate') as { value: string } | undefined; const setting = stmt.get('hourly_rate') as { value: string } | undefined;
@@ -20,6 +21,7 @@ export async function GET(req: NextRequest) {
} }
export async function POST(req: NextRequest) { export async function POST(req: NextRequest) {
const db = getDb();
try { try {
const { value } = await req.json(); const { value } = await req.json();
+3 -1
View File
@@ -1,8 +1,9 @@
import { NextRequest, NextResponse } from 'next/server'; import { NextRequest, NextResponse } from 'next/server';
import db from '@/lib/db'; import getDb from '@/lib/db';
export async function GET(req: NextRequest) { export async function GET(req: NextRequest) {
const db = getDb();
try { try {
const stmt = db.prepare("SELECT key, value FROM settings WHERE key LIKE 'smtp_%'"); const stmt = db.prepare("SELECT key, value FROM settings WHERE key LIKE 'smtp_%'");
const settings = stmt.all() as { key: string, value: string }[]; const settings = stmt.all() as { key: string, value: string }[];
@@ -18,6 +19,7 @@ export async function GET(req: NextRequest) {
} }
export async function POST(req: NextRequest) { export async function POST(req: NextRequest) {
const db = getDb();
try { try {
const settings = await req.json(); const settings = await req.json();
+3 -1
View File
@@ -2,7 +2,7 @@
'use server'; 'use server';
import { z } from 'zod'; import { z } from 'zod';
import db from '@/lib/db'; import getDb from '@/lib/db';
import { revalidatePath } from 'next/cache'; import { revalidatePath } from 'next/cache';
const emailTemplateSchema = z.object({ const emailTemplateSchema = z.object({
@@ -59,6 +59,7 @@ const defaultBody = `
* If no template is found, it creates and returns a default one. * If no template is found, it creates and returns a default one.
*/ */
export async function getEmailTemplate(): Promise<{ subject: string; body: string }> { export async function getEmailTemplate(): Promise<{ subject: string; body: string }> {
const db = getDb();
try { try {
const stmt = db.prepare('SELECT subject, body FROM email_templates WHERE id = ?'); const stmt = db.prepare('SELECT subject, body FROM email_templates WHERE id = ?');
let template = stmt.get(1) as { subject: string; body: string } | undefined; let template = stmt.get(1) as { subject: string; body: string } | undefined;
@@ -90,6 +91,7 @@ export async function updateEmailTemplate(data: { subject: string; body: string
} }
const { subject, body } = validation.data; const { subject, body } = validation.data;
const db = getDb();
try { try {
const stmt = db.prepare('UPDATE email_templates SET subject = ?, body = ? WHERE id = ?'); const stmt = db.prepare('UPDATE email_templates SET subject = ?, body = ? WHERE id = ?');
+5 -1
View File
@@ -1,7 +1,7 @@
'use server'; 'use server';
import db from '@/lib/db'; import getDb from '@/lib/db';
import { z } from 'zod'; import { z } from 'zod';
import { revalidatePath } from 'next/cache'; import { revalidatePath } from 'next/cache';
import { redirect } from 'next/navigation'; import { redirect } from 'next/navigation';
@@ -29,6 +29,7 @@ type State = {
} }
export async function getFlows(): Promise<Flow[]> { export async function getFlows(): Promise<Flow[]> {
const db = getDb();
try { try {
const stmt = db.prepare( const stmt = db.prepare(
'SELECT id, name, description, path, createdAt, updatedAt FROM flows ORDER BY createdAt DESC' 'SELECT id, name, description, path, createdAt, updatedAt FROM flows ORDER BY createdAt DESC'
@@ -42,6 +43,7 @@ export async function getFlows(): Promise<Flow[]> {
} }
export async function getFlow(id: number): Promise<Flow | null> { export async function getFlow(id: number): Promise<Flow | null> {
const db = getDb();
try { try {
const stmt = db.prepare('SELECT * FROM flows WHERE id = ?'); const stmt = db.prepare('SELECT * FROM flows WHERE id = ?');
const flow = stmt.get(id) as Flow | undefined; const flow = stmt.get(id) as Flow | undefined;
@@ -64,6 +66,7 @@ export async function saveFlow(prevState: State, formData: FormData): Promise<St
} }
const { id, name, description, path } = validatedFields.data; const { id, name, description, path } = validatedFields.data;
const db = getDb();
try { try {
if (id) { if (id) {
@@ -120,6 +123,7 @@ export async function saveFlow(prevState: State, formData: FormData): Promise<St
} }
export async function deleteFlow(id: number): Promise<{ success: boolean, message: string }> { export async function deleteFlow(id: number): Promise<{ success: boolean, message: string }> {
const db = getDb();
try { try {
// Prevent deletion of the default flow (ID 1) // Prevent deletion of the default flow (ID 1)
if (id === 1) { if (id === 1) {
+2 -1
View File
@@ -1,7 +1,7 @@
'use server'; 'use server';
import db from '@/lib/db'; import getDb from '@/lib/db';
export type Lead = { export type Lead = {
id: number; id: number;
@@ -12,6 +12,7 @@ export type Lead = {
}; };
export async function getLeads(): Promise<Lead[]> { export async function getLeads(): Promise<Lead[]> {
const db = getDb();
try { try {
const stmt = db.prepare( const stmt = db.prepare(
'SELECT id, name, email, phone, createdAt FROM leads ORDER BY createdAt DESC' 'SELECT id, name, email, phone, createdAt FROM leads ORDER BY createdAt DESC'
+3 -1
View File
@@ -4,7 +4,7 @@
import { z } from 'zod'; import { z } from 'zod';
import nodemailer from 'nodemailer'; import nodemailer from 'nodemailer';
import { PDFDocument, rgb, StandardFonts } from 'pdf-lib'; import { PDFDocument, rgb, StandardFonts } from 'pdf-lib';
import db from '@/lib/db'; import getDb from '@/lib/db';
import { getEmailTemplate } from './email'; import { getEmailTemplate } from './email';
import type { FormData } from '@/components/cost-estimator/cost-estimator-form'; import type { FormData } from '@/components/cost-estimator/cost-estimator-form';
@@ -21,6 +21,7 @@ type InputType = z.infer<typeof inputSchema>;
// Helper to get SMTP settings from the database // Helper to get SMTP settings from the database
async function getSmtpSettings() { async function getSmtpSettings() {
const db = getDb();
const stmt = db.prepare("SELECT key, value FROM settings WHERE key LIKE 'smtp_%'"); const stmt = db.prepare("SELECT key, value FROM settings WHERE key LIKE 'smtp_%'");
const settings = stmt.all() as { key: string, value: string }[]; const settings = stmt.all() as { key: string, value: string }[];
const config = settings.reduce((acc, setting) => { const config = settings.reduce((acc, setting) => {
@@ -117,6 +118,7 @@ async function createEstimatePdf(data: InputType): Promise<Buffer> {
} }
async function saveLead(name: string, email: string, phone?: string) { async function saveLead(name: string, email: string, phone?: string) {
const db = getDb();
try { try {
const stmt = db.prepare('INSERT INTO leads (name, email, phone) VALUES (?, ?, ?)'); const stmt = db.prepare('INSERT INTO leads (name, email, phone) VALUES (?, ?, ?)');
stmt.run(name, email, phone || null); stmt.run(name, email, phone || null);
+4 -1
View File
@@ -1,7 +1,8 @@
'use server'; 'use server';
import { z } from 'zod'; import { z } from 'zod';
import db from '@/lib/db'; import getDb from '@/lib/db';
import { revalidatePath } from 'next/cache'; import { revalidatePath } from 'next/cache';
import { auth } from '@/auth'; import { auth } from '@/auth';
@@ -21,6 +22,7 @@ type User = {
}; };
export async function getUserByEmail(email: string): Promise<User | null> { export async function getUserByEmail(email: string): Promise<User | null> {
const db = getDb();
try { try {
const stmt = db.prepare('SELECT id, name, email, password FROM users WHERE email = ?'); const stmt = db.prepare('SELECT id, name, email, password FROM users WHERE email = ?');
const user = stmt.get(email) as User | undefined; const user = stmt.get(email) as User | undefined;
@@ -64,6 +66,7 @@ export async function updateUser(data: UserFormValues): Promise<{ success: boole
const { name, email, password } = validation.data; const { name, email, password } = validation.data;
try { try {
const db = getDb();
const userId = session.user.id; const userId = session.user.id;
// Check if the new email is already taken by another user // Check if the new email is already taken by another user
+113 -106
View File
@@ -1,127 +1,134 @@
import Database from 'better-sqlite3'; import Database from 'better-sqlite3';
// Use a file-based database in development let db: Database.Database;
const db = new Database('local.db');
db.pragma('journal_mode = WAL');
// --- SCHEMA CREATION --- function initializeDb() {
// Use a file-based database
const newDb = new Database('local.db');
newDb.pragma('journal_mode = WAL');
// Drop the users table to ensure a clean slate on every start, avoiding schema conflicts. // --- SCHEMA CREATION ---
db.exec('DROP TABLE IF EXISTS users');
// Auth.js tables // Auth.js tables
db.exec(` newDb.exec(`
CREATE TABLE IF NOT EXISTS users ( CREATE TABLE IF NOT EXISTS users (
id TEXT NOT NULL PRIMARY KEY, id TEXT NOT NULL PRIMARY KEY,
name TEXT, name TEXT,
email TEXT NOT NULL UNIQUE, email TEXT NOT NULL UNIQUE,
emailVerified INTEGER, emailVerified INTEGER,
image TEXT, image TEXT,
password TEXT password TEXT
) )
`); `);
db.exec(` newDb.exec(`
CREATE TABLE IF NOT EXISTS accounts ( CREATE TABLE IF NOT EXISTS accounts (
userId TEXT NOT NULL, userId TEXT NOT NULL,
type TEXT NOT NULL, type TEXT NOT NULL,
provider TEXT NOT NULL, provider TEXT NOT NULL,
providerAccountId TEXT NOT NULL, providerAccountId TEXT NOT NULL,
refresh_token TEXT, refresh_token TEXT,
access_token TEXT, access_token TEXT,
expires_at INTEGER, expires_at INTEGER,
token_type TEXT, token_type TEXT,
scope TEXT, scope TEXT,
id_token TEXT, id_token TEXT,
session_state TEXT, session_state TEXT,
PRIMARY KEY (provider, providerAccountId), PRIMARY KEY (provider, providerAccountId),
FOREIGN KEY (userId) REFERENCES users (id) ON DELETE CASCADE FOREIGN KEY (userId) REFERENCES users (id) ON DELETE CASCADE
) )
`); `);
db.exec(` newDb.exec(`
CREATE TABLE IF NOT EXISTS sessions ( CREATE TABLE IF NOT EXISTS sessions (
sessionToken TEXT NOT NULL PRIMARY KEY, sessionToken TEXT NOT NULL PRIMARY KEY,
userId TEXT NOT NULL, userId TEXT NOT NULL,
expires INTEGER NOT NULL, expires INTEGER NOT NULL,
FOREIGN KEY (userId) REFERENCES users (id) ON DELETE CASCADE FOREIGN KEY (userId) REFERENCES users (id) ON DELETE CASCADE
) )
`); `);
db.exec(` newDb.exec(`
CREATE TABLE IF NOT EXISTS verification_tokens ( CREATE TABLE IF NOT EXISTS verification_tokens (
identifier TEXT NOT NULL, identifier TEXT NOT NULL,
token TEXT NOT NULL, token TEXT NOT NULL,
expires INTEGER NOT NULL, expires INTEGER NOT NULL,
PRIMARY KEY (identifier, token) PRIMARY KEY (identifier, token)
) )
`); `);
newDb.exec(`
CREATE TABLE IF NOT EXISTS settings (
key TEXT PRIMARY KEY,
value TEXT
)
`);
db.exec(` newDb.exec(`
CREATE TABLE IF NOT EXISTS settings ( CREATE TABLE IF NOT EXISTS email_templates (
key TEXT PRIMARY KEY, id INTEGER PRIMARY KEY,
value TEXT subject TEXT,
) body TEXT
`); )
`);
db.exec(` newDb.exec(`
CREATE TABLE IF NOT EXISTS email_templates ( CREATE TABLE IF NOT EXISTS leads (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY AUTOINCREMENT,
subject TEXT, name TEXT NOT NULL,
body TEXT email TEXT NOT NULL,
) phone TEXT,
`); createdAt DATETIME DEFAULT CURRENT_TIMESTAMP
)
`);
db.exec(` newDb.exec(`
CREATE TABLE IF NOT EXISTS leads ( CREATE TABLE IF NOT EXISTS flows (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL, name TEXT NOT NULL,
email TEXT NOT NULL, description TEXT,
phone TEXT, path TEXT NOT NULL UNIQUE,
createdAt DATETIME DEFAULT CURRENT_TIMESTAMP createdAt DATETIME DEFAULT CURRENT_TIMESTAMP,
) updatedAt DATETIME DEFAULT CURRENT_TIMESTAMP
`); )
`);
db.exec(` // --- SEEDING LOGIC ---
CREATE TABLE IF NOT EXISTS flows ( console.log('Running database checks and seeding if necessary...');
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
description TEXT,
path TEXT NOT NULL UNIQUE,
createdAt DATETIME DEFAULT CURRENT_TIMESTAMP,
updatedAt DATETIME DEFAULT CURRENT_TIMESTAMP
)
`);
// Seed default user
const userStmt = newDb.prepare('SELECT id FROM users WHERE email = ?');
const defaultUser = userStmt.get('admin@example.com');
if (!defaultUser) {
const insertUser = newDb.prepare(
"INSERT INTO users (id, email, password, name) VALUES (?, ?, ?, ?)"
);
// Note: In a real app, hash the password!
insertUser.run('cl-admin-user-id', 'admin@example.com', 'password', 'Admin User');
console.log('Default user created.');
}
// --- SEEDING LOGIC --- // Seed default flow
console.log('Running database checks and seeding if necessary...'); const flowStmt = newDb.prepare("SELECT id FROM flows WHERE path = ?");
const defaultFlow = flowStmt.get('/');
if (!defaultFlow) {
const insertFlow = newDb.prepare(
"INSERT INTO flows (name, description, path) VALUES (?, ?, ?)"
);
insertFlow.run('Cost Estimator', 'The main cost estimation tool for clients.', '/');
console.log('Default flow created.');
}
// Seed default user console.log('Database setup complete.');
const userStmt = db.prepare('SELECT id FROM users WHERE email = ?'); return newDb;
const defaultUser = userStmt.get('admin@example.com');
if (!defaultUser) {
const insertUser = db.prepare(
"INSERT INTO users (id, email, password, name) VALUES (?, ?, ?, ?)"
);
// Note: In a real app, hash the password!
insertUser.run('cl-admin-user-id', 'admin@example.com', 'password', 'Admin User');
console.log('Default user created.');
} }
// Seed default flow function getDb() {
const flowStmt = db.prepare("SELECT id FROM flows WHERE path = ?"); if (!db) {
const defaultFlow = flowStmt.get('/'); db = initializeDb();
if (!defaultFlow) { }
const insertFlow = db.prepare( return db;
"INSERT INTO flows (name, description, path) VALUES (?, ?, ?)"
);
insertFlow.run('Cost Estimator', 'The main cost estimation tool for clients.', '/');
console.log('Default flow created.');
} }
console.log('Database setup complete.'); export default getDb;
export default db;