|
|
import sqlite3 |
|
|
from datetime import datetime |
|
|
|
|
|
DB_PATH = "chatai.db" |
|
|
|
|
|
def get_conn(): |
|
|
return sqlite3.connect(DB_PATH, check_same_thread=False) |
|
|
|
|
|
def init_db(): |
|
|
conn = get_conn() |
|
|
c = conn.cursor() |
|
|
c.execute(""" |
|
|
CREATE TABLE IF NOT EXISTS users ( |
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT, |
|
|
username TEXT UNIQUE NOT NULL, |
|
|
password_hash BLOB NOT NULL, |
|
|
role TEXT NOT NULL DEFAULT 'user', |
|
|
is_active INTEGER NOT NULL DEFAULT 1, |
|
|
created_at TEXT NOT NULL |
|
|
) |
|
|
""") |
|
|
c.execute(""" |
|
|
CREATE TABLE IF NOT EXISTS conversations ( |
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT, |
|
|
user_id INTEGER NOT NULL, |
|
|
title TEXT, |
|
|
created_at TEXT NOT NULL, |
|
|
FOREIGN KEY(user_id) REFERENCES users(id) |
|
|
) |
|
|
""") |
|
|
c.execute(""" |
|
|
CREATE TABLE IF NOT EXISTS messages ( |
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT, |
|
|
conversation_id INTEGER NOT NULL, |
|
|
role TEXT NOT NULL, |
|
|
content TEXT NOT NULL, |
|
|
attachments TEXT, |
|
|
created_at TEXT NOT NULL, |
|
|
FOREIGN KEY(conversation_id) REFERENCES conversations(id) |
|
|
) |
|
|
""") |
|
|
conn.commit() |
|
|
return conn |
|
|
|
|
|
|
|
|
def create_user(username, password_hash, role="user", is_active=True): |
|
|
conn = get_conn() |
|
|
c = conn.cursor() |
|
|
c.execute( |
|
|
"INSERT INTO users (username, password_hash, role, is_active, created_at) VALUES (?,?,?,?,?)", |
|
|
(username, password_hash, role, 1 if is_active else 0, datetime.utcnow().isoformat()), |
|
|
) |
|
|
conn.commit() |
|
|
return c.lastrowid |
|
|
|
|
|
def get_user_by_username(username): |
|
|
conn = get_conn() |
|
|
c = conn.cursor() |
|
|
c.execute("SELECT id, username, password_hash, role, is_active, created_at FROM users WHERE username = ?", (username,)) |
|
|
row = c.fetchone() |
|
|
if not row: return None |
|
|
return {"id": row[0], "username": row[1], "password_hash": row[2], "role": row[3], "is_active": bool(row[4]), "created_at": row[5]} |
|
|
|
|
|
def get_user_by_id(user_id): |
|
|
conn = get_conn() |
|
|
c = conn.cursor() |
|
|
c.execute("SELECT id, username, password_hash, role, is_active, created_at FROM users WHERE id = ?", (user_id,)) |
|
|
row = c.fetchone() |
|
|
if not row: return None |
|
|
return {"id": row[0], "username": row[1], "password_hash": row[2], "role": row[3], "is_active": bool(row[4]), "created_at": row[5]} |
|
|
|
|
|
def list_users(): |
|
|
conn = get_conn() |
|
|
c = conn.cursor() |
|
|
c.execute("SELECT id, username, role, is_active, created_at FROM users ORDER BY id ASC") |
|
|
rows = c.fetchall() |
|
|
return [{"id": r[0], "username": r[1], "role": r[2], "is_active": bool(r[3]), "created_at": r[4]} for r in rows] |
|
|
|
|
|
def set_user_active(user_id, active: bool): |
|
|
conn = get_conn() |
|
|
c = conn.cursor() |
|
|
c.execute("UPDATE users SET is_active=? WHERE id=?", (1 if active else 0, user_id)) |
|
|
conn.commit() |
|
|
|
|
|
def set_user_role(user_id, role: str): |
|
|
conn = get_conn() |
|
|
c = conn.cursor() |
|
|
c.execute("UPDATE users SET role=? WHERE id=?", (role, user_id)) |
|
|
conn.commit() |
|
|
|
|
|
def update_user_password(user_id, new_password_hash): |
|
|
conn = get_conn() |
|
|
c = conn.cursor() |
|
|
c.execute("UPDATE users SET password_hash=? WHERE id=?", (new_password_hash, user_id)) |
|
|
conn.commit() |
|
|
|
|
|
def delete_user(user_id): |
|
|
conn = get_conn() |
|
|
c = conn.cursor() |
|
|
c.execute("DELETE FROM users WHERE id=?", (user_id,)) |
|
|
conn.commit() |
|
|
|
|
|
|
|
|
def create_conversation(user_id, title="New Chat"): |
|
|
conn = get_conn() |
|
|
c = conn.cursor() |
|
|
c.execute("INSERT INTO conversations (user_id, title, created_at) VALUES (?,?,?)", |
|
|
(user_id, title, datetime.utcnow().isoformat())) |
|
|
conn.commit() |
|
|
return c.lastrowid |
|
|
|
|
|
def list_conversations(user_id): |
|
|
conn = get_conn() |
|
|
c = conn.cursor() |
|
|
c.execute("SELECT id, title, created_at FROM conversations WHERE user_id=? ORDER BY id DESC", (user_id,)) |
|
|
rows = c.fetchall() |
|
|
return [{"id": r[0], "title": r[1], "created_at": r[2]} for r in rows] |
|
|
|
|
|
def rename_conversation(conversation_id, title): |
|
|
conn = get_conn() |
|
|
c = conn.cursor() |
|
|
c.execute("UPDATE conversations SET title=? WHERE id=?", (title, conversation_id)) |
|
|
conn.commit() |
|
|
|
|
|
def delete_conversation(conversation_id): |
|
|
conn = get_conn() |
|
|
c = conn.cursor() |
|
|
c.execute("DELETE FROM messages WHERE conversation_id=?", (conversation_id,)) |
|
|
c.execute("DELETE FROM conversations WHERE id=?", (conversation_id,)) |
|
|
conn.commit() |
|
|
|
|
|
def add_message(conversation_id, role, content, attachments=None): |
|
|
conn = get_conn() |
|
|
c = conn.cursor() |
|
|
c.execute("INSERT INTO messages (conversation_id, role, content, attachments, created_at) VALUES (?,?,?,?,?)", |
|
|
(conversation_id, role, content, attachments or "[]", datetime.utcnow().isoformat())) |
|
|
conn.commit() |
|
|
return c.lastrowid |
|
|
|
|
|
def get_messages(conversation_id): |
|
|
conn = get_conn() |
|
|
c = conn.cursor() |
|
|
c.execute("SELECT role, content, attachments, created_at FROM messages WHERE conversation_id=? ORDER BY id ASC", |
|
|
(conversation_id,)) |
|
|
rows = c.fetchall() |
|
|
msgs = [] |
|
|
for r in rows: |
|
|
msgs.append({"role": r[0], "content": r[1], "attachments": r[2], "created_at": r[3]}) |
|
|
return msgs |
|
|
|