diff options
| author | Ben Sima <ben@bsima.me> | 2025-09-04 11:15:50 -0400 |
|---|---|---|
| committer | Ben Sima <ben@bsima.me> | 2025-09-04 11:40:35 -0400 |
| commit | ddad1f4c648ae4e1f1197949c2ad864f422ad25c (patch) | |
| tree | e36a72a8be1a16565a658f2e0331aecf27b0b2e2 /Biz/PodcastItLater/Core.py | |
| parent | 7ea6ef1b4ebccedeba52d670565741fb1b3e8202 (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.py | 57 |
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.""" |
