summaryrefslogtreecommitdiff
path: root/Biz/PodcastItLater/Core.py
diff options
context:
space:
mode:
authorBen Sima <ben@bsima.me>2025-09-04 11:15:50 -0400
committerBen Sima <ben@bsima.me>2025-09-04 11:40:35 -0400
commitddad1f4c648ae4e1f1197949c2ad864f422ad25c (patch)
treee36a72a8be1a16565a658f2e0331aecf27b0b2e2 /Biz/PodcastItLater/Core.py
parent7ea6ef1b4ebccedeba52d670565741fb1b3e8202 (diff)
Add User Status Management to PodcastItLater
Implement user status tracking with pending, active, and disabled states. This allows administrators to control user access and provides a mechanism for approving new users before granting full system access. Added database migration, admin interface, and authentication checks to support this feature.
Diffstat (limited to 'Biz/PodcastItLater/Core.py')
-rw-r--r--Biz/PodcastItLater/Core.py57
1 files changed, 55 insertions, 2 deletions
diff --git a/Biz/PodcastItLater/Core.py b/Biz/PodcastItLater/Core.py
index 542bb8b..1756fc6 100644
--- a/Biz/PodcastItLater/Core.py
+++ b/Biz/PodcastItLater/Core.py
@@ -125,6 +125,9 @@ class Database: # noqa: PLR0904
# Run migration to add episode metadata fields
Database.migrate_add_episode_metadata(db_path)
+ # Run migration to add user status field
+ Database.migrate_add_user_status(db_path)
+
@staticmethod
def add_to_queue( # noqa: PLR0913, PLR0917
url: str,
@@ -558,6 +561,34 @@ class Database: # noqa: PLR0904
logger.info("Database migrated to support episode metadata fields")
@staticmethod
+ def migrate_add_user_status(db_path: str | None = None) -> None:
+ """Add status field to users table."""
+ if db_path is None:
+ db_path = Database.get_default_db_path()
+ with Database.get_connection(db_path) as conn:
+ cursor = conn.cursor()
+
+ # Check if column already exists
+ cursor.execute("PRAGMA table_info(users)")
+ users_info = cursor.fetchall()
+ users_columns = [col[1] for col in users_info]
+
+ if "status" not in users_columns:
+ # Add status column with default 'pending'
+ cursor.execute(
+ "ALTER TABLE users ADD COLUMN status TEXT "
+ "DEFAULT 'pending'",
+ )
+
+ # Set all existing users to 'active'
+ cursor.execute(
+ "UPDATE users SET status = 'active' WHERE status IS NULL",
+ )
+
+ conn.commit()
+ logger.info("Database migrated to support user status")
+
+ @staticmethod
def create_user(email: str, db_path: str | None = None) -> tuple[int, str]:
"""Create a new user and return (user_id, token).
@@ -574,8 +605,8 @@ class Database: # noqa: PLR0904
cursor = conn.cursor()
try:
cursor.execute(
- "INSERT INTO users (email, token) VALUES (?, ?)",
- (email, token),
+ "INSERT INTO users (email, token, status) VALUES (?, ?, ?)",
+ (email, token, "pending"),
)
conn.commit()
user_id = cursor.lastrowid
@@ -701,6 +732,28 @@ class Database: # noqa: PLR0904
rows = cursor.fetchall()
return [dict(row) for row in rows]
+ @staticmethod
+ def update_user_status(
+ user_id: int,
+ status: str,
+ db_path: str | None = None,
+ ) -> None:
+ """Update user account status."""
+ if db_path is None:
+ db_path = Database.get_default_db_path()
+ if status not in {"pending", "active", "disabled"}:
+ msg = f"Invalid status: {status}"
+ raise ValueError(msg)
+
+ with Database.get_connection(db_path) as conn:
+ cursor = conn.cursor()
+ cursor.execute(
+ "UPDATE users SET status = ? WHERE id = ?",
+ (status, user_id),
+ )
+ conn.commit()
+ logger.info("Updated user %s status to %s", user_id, status)
+
class TestDatabase(Test.TestCase):
"""Test the Database class."""