Keeby-smilyai's picture
Update backend/database.py
4ab59e5 verified
# backend/database.py
import sqlite3
import bcrypt
import os
import time
DATABASE_PATH = 'data.db'
def get_db_connection():
"""Establishes a connection to the SQLite database."""
conn = sqlite3.connect(DATABASE_PATH)
return conn
def init_db():
"""
Initializes the database by creating the necessary tables.
This function should be called once on application startup.
"""
conn = get_db_connection()
c = conn.cursor()
c.execute("""
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE NOT NULL,
password_hash TEXT NOT NULL
)
""")
c.execute("""
CREATE TABLE IF NOT EXISTS projects (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
title TEXT NOT NULL,
prompt TEXT NOT NULL,
status TEXT NOT NULL,
created_at INTEGER NOT NULL,
logs TEXT,
zip_path TEXT,
FOREIGN KEY (user_id) REFERENCES users (id)
)
""")
conn.commit()
conn.close()
def create_user(username, password):
"""
Creates a new user in the database.
Returns the user ID or None if the username is already taken.
"""
conn = get_db_connection()
c = conn.cursor()
hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
try:
c.execute("INSERT INTO users (username, password_hash) VALUES (?, ?)", (username, hashed_password))
conn.commit()
return c.lastrowid
except sqlite3.IntegrityError:
return None
finally:
conn.close()
def get_user_by_username(username):
"""Fetches a user by their username."""
conn = get_db_connection()
c = conn.cursor()
c.execute("SELECT * FROM users WHERE username = ?", (username,))
user = c.fetchone()
conn.close()
if user:
columns = [desc[0] for desc in c.description]
return dict(zip(columns, user))
return None
def verify_password(password, password_hash):
"""Verifies a password against its hash."""
return bcrypt.checkpw(password.encode('utf-8'), password_hash.encode('utf-8'))
def create_project(user_id, title, prompt):
"""Creates a new project record and returns its ID."""
conn = get_db_connection()
c = conn.cursor()
c.execute("INSERT INTO projects (user_id, title, prompt, status, created_at) VALUES (?, ?, ?, ?, ?)",
(user_id, title, prompt, "queued", int(time.time())))
project_id = c.lastrowid
conn.commit()
conn.close()
return project_id
def get_user_projects(user_id):
"""Retrieves all projects for a given user, ordered by creation date."""
conn = get_db_connection()
c = conn.cursor()
c.execute("SELECT * FROM projects WHERE user_id = ? ORDER BY created_at DESC", (user_id,))
projects = c.fetchall()
conn.close()
project_list = []
if projects:
columns = [desc[0] for desc in c.description]
for project in projects:
project_list.append(dict(zip(columns, project)))
return project_list
def get_project(project_id):
"""
Fetches a single project record by its unique ID.
This function is used by the front end for live log updates.
"""
conn = get_db_connection()
c = conn.cursor()
c.execute("SELECT * FROM projects WHERE id = ?", (project_id,))
project = c.fetchone()
conn.close()
if project:
columns = [desc[0] for desc in c.description]
return dict(zip(columns, project))
return None
def update_project_status(project_id, status, logs=None, zip_path=None):
"""Updates the status and optional logs/zip path for a project."""
conn = get_db_connection()
c = conn.cursor()
if logs is not None and zip_path is not None:
c.execute("UPDATE projects SET status = ?, logs = ?, zip_path = ? WHERE id = ?", (status, logs, zip_path, project_id))
elif logs is not None:
c.execute("UPDATE projects SET status = ?, logs = ? WHERE id = ?", (status, logs, project_id))
else:
c.execute("UPDATE projects SET status = ? WHERE id = ?", (status, project_id))
conn.commit()
conn.close()