From f062f7201706848ade7f7b950ed15b5a6e724acc Mon Sep 17 00:00:00 2001 From: Stefano Date: Mon, 5 May 2025 16:56:03 -0500 Subject: [PATCH] Replaced env variable DATABASE_PATH with DATA_PATH and DATABASE_FILENAME --- Dockerfile | 4 +++- README.md | 31 ++++++++++++++++++++++++++----- src/config.py | 20 ++++++++++++-------- src/utils/auth.py | 15 +++++++++++---- src/utils/database.py | 12 +++++++++--- 5 files changed, 61 insertions(+), 21 deletions(-) diff --git a/Dockerfile b/Dockerfile index 56de3d0..cab5e3c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,7 +9,9 @@ COPY . . ENV SUPER_ADMIN_USER=admin ENV SUPER_ADMIN_PASSWORD=adminpassword -ENV DATABASE_PATH=/data/users.db +ENV DATABASE_FILENAME=users.db +ENV DATA_PATH=/data +ENV CONTENT_PATH=/content VOLUME ["/data", "/Content"] diff --git a/README.md b/README.md index 4d82bbd..76514e9 100644 --- a/README.md +++ b/README.md @@ -54,10 +54,13 @@ You can install and run the project either manually or using Docker. ```env SUPER_ADMIN_USER=your_super_admin_username SUPER_ADMIN_PASSWORD=your_super_admin_password - DATABASE_PATH=data/users.db + DATABASE_FILENAME=users.db + DATA_PATH=/data + CONTENT_PATH=/content ``` - Note: The `DATABASE_PATH` uses a relative path. For persistence and consistency, it's recommended to use an absolute path or ensure the volume mount covers this path if using Docker. The `utils/database.py` script will attempt to create the directory `data` if it doesn't exist relative to where the script is run. + **Important Notes:** + * For Docker deployments, paths should match volume mounts from the `docker run` command ### Docker Installation @@ -82,7 +85,7 @@ You can install and run the project either manually or using Docker. ### Running Manually 1. Ensure you have activated the virtual environment (if installed manually). -2. Ensure your environment variables (`SUPER_ADMIN_USER`, `SUPER_ADMIN_PASSWORD`, `DATABASE_PATH`) are set. +2. Ensure your environment variables (`SUPER_ADMIN_USER`, `SUPER_ADMIN_PASSWORD`, `DATABASE_FILENAME`, `DATA_PATH`, `CONTENT_PATH`) are set. 3. Run the application using uvicorn: ```bash @@ -103,15 +106,33 @@ You can install and run the project either manually or using Docker. --name user-service \ -p 8000:8000 \ -v user-service-data:/data \ + -v user-service-content:/content \ -e SUPER_ADMIN_USER=your_super_admin_username \ -e SUPER_ADMIN_PASSWORD=your_super_admin_password \ - user-registration-service + iptv-server ``` - Replace `your_super_admin_username` and `your_super_admin_password` with your desired credentials. The `-v user-service-data:/data` maps a Docker volume for persistent storage of the SQLite database defined by `DATABASE_PATH=/data/users.db` in the Dockerfile. + Replace `your_super_admin_username` and `your_super_admin_password` with your desired credentials. + + Key components: + * `-v user-service-data:/data` creates/manages a Docker volume for persistent database storage + * `-v user-service-content:/content` ensures content directory persistence + * Environment variables match those expected by the application (defined in Dockerfile) The application will be available at `http://localhost:8000` (or your Docker host's IP). +**For bind mounts instead of named volumes** (useful for development): + +```bash +docker run -d \ + --name user-service \ + -p 8000:8000 \ + -v ./local/data:/data \ + -v ./local/content:/content \ + -e SUPER_ADMIN_USER=admin \ + -e SUPER_ADMIN_PASSWORD=securepassword \ + user-registration-service + ## Usage The API documentation will be available at `http://localhost:8000/docs` (Swagger UI) or `http://localhost:8000/redoc` (ReDoc) once the server is running. diff --git a/src/config.py b/src/config.py index 7bd3aaa..57a7321 100644 --- a/src/config.py +++ b/src/config.py @@ -19,12 +19,16 @@ if content_path and not os.path.exists(content_path): print(f"Creating directory for serving content: {CONTENT_PATH}") os.makedirs(content_path, exist_ok=True) -# Database file path -# Reads from environment variable DATABASE_PATH or defaults to '/data/users.db' -DATABASE_PATH = os.getenv("DATABASE_PATH", "/data/users.db") +# Database file name +# Reads from environment variable DATABASE_FILENAME or defaults to 'users.db' +DATABASE_FILENAME= os.getenv("DATABASE_FILENAME", "users.db") -# Ensure the directory for the database exists -db_dir = os.path.dirname(DATABASE_PATH) -if db_dir and not os.path.exists(db_dir): - print(f"Creating directory for database: {DATABASE_PATH}") - os.makedirs(db_dir, exist_ok=True) +# Define the directory where data files are stored +# Reads from environment variable DATA_PATH or defaults to '/data' +DATA_PATH = os.getenv("DATA_PATH", "/data") + +# Ensure the directory for the data files +data_dir = os.path.dirname(DATA_PATH) +if data_dir and not os.path.exists(data_dir): + print(f"Creating directory for data files: {DATA_PATH}") + os.makedirs(data_dir, exist_ok=True) diff --git a/src/utils/auth.py b/src/utils/auth.py index 4875b70..bd5b270 100644 --- a/src/utils/auth.py +++ b/src/utils/auth.py @@ -1,18 +1,25 @@ +from pathlib import Path import aiosqlite from fastapi import Depends, HTTPException, status, Query from fastapi.security import HTTPBasicCredentials, HTTPBasic from passlib.context import CryptContext -from config import SUPER_ADMIN_USER, SUPER_ADMIN_PASSWORD, DATABASE_PATH +from config import SUPER_ADMIN_USER, SUPER_ADMIN_PASSWORD, DATABASE_FILENAME, DATA_PATH pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") security = HTTPBasic() admin_security = HTTPBasic() async def get_user(username: str): - # Use the dependency pattern even for internal calls for consistency - async with aiosqlite.connect(DATABASE_PATH) as db: + # Build proper database path + db_path = Path(DATA_PATH) / DATABASE_FILENAME + + # Ensure directory exists (security measure) + db_path.parent.mkdir(parents=True, exist_ok=True) + + async with aiosqlite.connect(db_path) as db: cursor = await db.execute( - "SELECT * FROM users WHERE username = ?", (username,) + "SELECT username, hashed_password FROM users WHERE username = ?", + (username,) ) return await cursor.fetchone() diff --git a/src/utils/database.py b/src/utils/database.py index c2535c7..3e5084b 100644 --- a/src/utils/database.py +++ b/src/utils/database.py @@ -1,9 +1,15 @@ import aiosqlite -from dotenv import load_dotenv -from config import DATABASE_PATH +from pathlib import Path +from config import DATABASE_FILENAME, DATA_PATH async def get_db(): - async with aiosqlite.connect(DATABASE_PATH) as db: + # Build the full database path + db_path = Path(DATA_PATH) / DATABASE_FILENAME + + # Ensure the directory exists + db_path.parent.mkdir(parents=True, exist_ok=True) + + async with aiosqlite.connect(db_path) as db: # Enable WAL mode for better concurrency await db.execute("PRAGMA journal_mode=WAL;") await db.execute("""