From 51c599e04008721afec1fe98e25c84424d473c2d Mon Sep 17 00:00:00 2001 From: hienp Date: Thu, 2 Apr 2026 11:04:40 +0700 Subject: [PATCH] =?UTF-8?q?update=20account=20admin=20lu=C3=B4n=20t?= =?UTF-8?q?=E1=BB=93n=20t=E1=BA=A1i?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 5 +++++ backend/app/main.py | 30 ++++++++++++++++++++++++++++++ docker-compose.yml | 3 +++ 3 files changed, 38 insertions(+) diff --git a/.env.example b/.env.example index 2ba9c36..fef30b1 100644 --- a/.env.example +++ b/.env.example @@ -18,6 +18,11 @@ ACCESS_TOKEN_EXPIRE_MINUTES=60 # Port exposed on the host for the Next.js frontend FRONTEND_PORT=3011 +# ── Default admin account (created automatically on first start) ───────────── +ADMIN_USERNAME=admin +ADMIN_PASSWORD=Admin@12345 +ADMIN_EMAIL=admin@lms.local + # ── Docker Hub images (optional — leave blank to build locally) ─────────────── # Set these on the target machine so docker compose pull works without building # BACKEND_IMAGE=your_dockerhub_username/lms-backend:latest diff --git a/backend/app/main.py b/backend/app/main.py index b3e65ca..2134b1f 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -1,15 +1,45 @@ from contextlib import asynccontextmanager +import os from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from .routers import admin, annotations, auth, backup, pdfs, ws +from .database import SessionLocal +from .models import User, UserRole, UserStatus +from .security import hash_password + + +def _seed_admin() -> None: + """Create the default admin account if it does not exist yet.""" + username = os.getenv("ADMIN_USERNAME", "admin") + password = os.getenv("ADMIN_PASSWORD", "Admin@12345") + email = os.getenv("ADMIN_EMAIL", "admin@lms.local") + + db = SessionLocal() + try: + exists = db.query(User).filter(User.username == username).first() + if not exists: + db.add(User( + username = username, + email = email, + password_hash = hash_password(password), + role = UserRole.admin, + status = UserStatus.approved, + )) + db.commit() + print(f"[seed] Admin account '{username}' created.") + else: + print(f"[seed] Admin account '{username}' already exists — skipped.") + finally: + db.close() @asynccontextmanager async def lifespan(app: FastAPI): # Tables are managed by Alembic migrations. # Run: alembic upgrade head (done by docker-compose entrypoint) + _seed_admin() yield diff --git a/docker-compose.yml b/docker-compose.yml index 7375241..99ef852 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -50,6 +50,9 @@ services: ACCESS_TOKEN_EXPIRE_MINUTES: ${ACCESS_TOKEN_EXPIRE_MINUTES:-60} UPLOAD_DIR: /uploads REDIS_URL: redis://redis:6379/0 + ADMIN_USERNAME: ${ADMIN_USERNAME:-admin} + ADMIN_PASSWORD: ${ADMIN_PASSWORD:-Admin@12345} + ADMIN_EMAIL: ${ADMIN_EMAIL:-admin@lms.local} volumes: - pdf_uploads:/uploads expose: