Other files
This commit is contained in:
@@ -150,6 +150,17 @@ class Database:
|
||||
)
|
||||
""")
|
||||
|
||||
# Checkout profiles table — stores AES-encrypted shipping + payment data
|
||||
cursor.execute("""
|
||||
CREATE TABLE IF NOT EXISTS user_profiles (
|
||||
user_id INTEGER PRIMARY KEY,
|
||||
salt BLOB NOT NULL,
|
||||
ciphertext BLOB NOT NULL,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||
)
|
||||
""")
|
||||
|
||||
# Create indexes for common queries
|
||||
cursor.execute("CREATE INDEX IF NOT EXISTS idx_products_site ON products(site)")
|
||||
cursor.execute("CREATE INDEX IF NOT EXISTS idx_products_category ON products(category)")
|
||||
@@ -1068,6 +1079,49 @@ class Database:
|
||||
"""Update user's location settings"""
|
||||
return self.update_user(user_id, zip_code=zip_code, radius_miles=radius_miles)
|
||||
|
||||
# ==================== Checkout Profile Methods ====================
|
||||
|
||||
def save_user_profile(self, user_id: int, salt: bytes, ciphertext: bytes):
|
||||
"""Save or replace an encrypted checkout profile for a user."""
|
||||
with self.get_connection() as conn:
|
||||
conn.execute(
|
||||
"""INSERT INTO user_profiles (user_id, salt, ciphertext, updated_at)
|
||||
VALUES (?, ?, ?, CURRENT_TIMESTAMP)
|
||||
ON CONFLICT(user_id) DO UPDATE SET
|
||||
salt=excluded.salt,
|
||||
ciphertext=excluded.ciphertext,
|
||||
updated_at=CURRENT_TIMESTAMP""",
|
||||
(user_id, salt, ciphertext),
|
||||
)
|
||||
|
||||
def get_user_profile(self, user_id: int) -> Optional[Dict]:
|
||||
"""Return {salt, ciphertext} for a user, or None if no profile saved."""
|
||||
with self.get_connection() as conn:
|
||||
conn.row_factory = sqlite3.Row
|
||||
row = conn.execute(
|
||||
"SELECT salt, ciphertext, updated_at FROM user_profiles WHERE user_id = ?",
|
||||
(user_id,),
|
||||
).fetchone()
|
||||
if not row:
|
||||
return None
|
||||
return {"salt": row["salt"], "ciphertext": row["ciphertext"], "updated_at": row["updated_at"]}
|
||||
|
||||
def delete_user_profile(self, user_id: int) -> bool:
|
||||
"""Delete a user's checkout profile."""
|
||||
with self.get_connection() as conn:
|
||||
cursor = conn.execute(
|
||||
"DELETE FROM user_profiles WHERE user_id = ?", (user_id,)
|
||||
)
|
||||
return cursor.rowcount > 0
|
||||
|
||||
def user_has_profile(self, user_id: int) -> bool:
|
||||
"""Return True if a saved (encrypted) profile exists for this user."""
|
||||
with self.get_connection() as conn:
|
||||
row = conn.execute(
|
||||
"SELECT 1 FROM user_profiles WHERE user_id = ?", (user_id,)
|
||||
).fetchone()
|
||||
return row is not None
|
||||
|
||||
# ==================== Stats Summary ====================
|
||||
|
||||
def get_dashboard_stats(self) -> Dict:
|
||||
|
||||
Reference in New Issue
Block a user