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
+47 -40
View File
@@ -1,17 +1,17 @@
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,
@@ -20,9 +20,9 @@ db.exec(`
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,
@@ -38,43 +38,42 @@ db.exec(`
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(`
db.exec(`
CREATE TABLE IF NOT EXISTS settings ( CREATE TABLE IF NOT EXISTS settings (
key TEXT PRIMARY KEY, key TEXT PRIMARY KEY,
value TEXT value TEXT
) )
`); `);
db.exec(` newDb.exec(`
CREATE TABLE IF NOT EXISTS email_templates ( CREATE TABLE IF NOT EXISTS email_templates (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
subject TEXT, subject TEXT,
body TEXT body TEXT
) )
`); `);
db.exec(` newDb.exec(`
CREATE TABLE IF NOT EXISTS leads ( CREATE TABLE IF NOT EXISTS leads (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL, name TEXT NOT NULL,
@@ -82,9 +81,9 @@ db.exec(`
phone TEXT, phone TEXT,
createdAt DATETIME DEFAULT CURRENT_TIMESTAMP createdAt DATETIME DEFAULT CURRENT_TIMESTAMP
) )
`); `);
db.exec(` newDb.exec(`
CREATE TABLE IF NOT EXISTS flows ( CREATE TABLE IF NOT EXISTS flows (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL, name TEXT NOT NULL,
@@ -93,35 +92,43 @@ db.exec(`
createdAt DATETIME DEFAULT CURRENT_TIMESTAMP, createdAt DATETIME DEFAULT CURRENT_TIMESTAMP,
updatedAt DATETIME DEFAULT CURRENT_TIMESTAMP updatedAt DATETIME DEFAULT CURRENT_TIMESTAMP
) )
`); `);
// --- SEEDING LOGIC ---
console.log('Running database checks and seeding if necessary...');
// --- SEEDING LOGIC --- // Seed default user
console.log('Running database checks and seeding if necessary...'); const userStmt = newDb.prepare('SELECT id FROM users WHERE email = ?');
const defaultUser = userStmt.get('admin@example.com');
// Seed default user if (!defaultUser) {
const userStmt = db.prepare('SELECT id FROM users WHERE email = ?'); const insertUser = newDb.prepare(
const defaultUser = userStmt.get('admin@example.com');
if (!defaultUser) {
const insertUser = db.prepare(
"INSERT INTO users (id, email, password, name) VALUES (?, ?, ?, ?)" "INSERT INTO users (id, email, password, name) VALUES (?, ?, ?, ?)"
); );
// Note: In a real app, hash the password! // Note: In a real app, hash the password!
insertUser.run('cl-admin-user-id', 'admin@example.com', 'password', 'Admin User'); insertUser.run('cl-admin-user-id', 'admin@example.com', 'password', 'Admin User');
console.log('Default user created.'); console.log('Default user created.');
} }
// Seed default flow // Seed default flow
const flowStmt = db.prepare("SELECT id FROM flows WHERE path = ?"); const flowStmt = newDb.prepare("SELECT id FROM flows WHERE path = ?");
const defaultFlow = flowStmt.get('/'); const defaultFlow = flowStmt.get('/');
if (!defaultFlow) { if (!defaultFlow) {
const insertFlow = db.prepare( const insertFlow = newDb.prepare(
"INSERT INTO flows (name, description, path) VALUES (?, ?, ?)" "INSERT INTO flows (name, description, path) VALUES (?, ?, ?)"
); );
insertFlow.run('Cost Estimator', 'The main cost estimation tool for clients.', '/'); insertFlow.run('Cost Estimator', 'The main cost estimation tool for clients.', '/');
console.log('Default flow created.'); console.log('Default flow created.');
}
console.log('Database setup complete.');
return newDb;
} }
console.log('Database setup complete.'); function getDb() {
if (!db) {
db = initializeDb();
}
return db;
}
export default db; export default getDb;