feat: Add default admin user creation and root route redirects

- Auto-create admin user on first startup (admin@example.com/admin)
- Add redirects from /, /dashboard, /login to /web/ for better UX
- Enhanced startup logging with login credentials
- Improved config documentation for admin_emails

Fixes initial setup UX issues with web UI access and authentication.
This commit is contained in:
wjbeckett
2025-07-18 16:04:01 +10:00
parent df7d00ad99
commit 4177409b59
4 changed files with 96 additions and 2 deletions

View File

@@ -43,10 +43,28 @@ volumes:
3. If `config.toml` doesn't exist in the config directory, the example config is copied
4. Application-managed directories (like images) are created automatically
5. Database migrations run
6. Application starts successfully
6. **Default admin user is created if no users exist** (see Login Information below)
7. Application starts successfully
Note: Media directories are NOT created by the application - they should be mounted from your host system.
## Login Information
### Default Admin User
- If no users exist in the database, a default admin user is automatically created
- **Email**: First email from `admin_emails` in config.toml (default: `admin@example.com`)
- **Password**: `admin`
- **⚠️ IMPORTANT**: Change this password immediately after first login!
### Creating Additional Admin Users
- Register a new user with an email address listed in the `admin_emails` array in your config.toml
- Users with admin emails automatically become administrators upon registration
### Manual User Registration
- Access the web UI at `http://localhost:8000/`
- Look for registration/signup options in the interface
- Or use the API directly at `/api/v1/auth/register`
## User Experience Improvements
- **No pre-setup required**: Users can now run `docker-compose up` immediately

View File

@@ -36,6 +36,9 @@ email_password_resets = false # if true, you also need to set up SMTP (notificat
token_secret = "CHANGE_ME_GENERATE_RANDOM_STRING" # generate a random string with "openssl rand -hex 32", e.g. here https://www.cryptool.org/en/cto/openssl/
session_lifetime = 86400 # this is how long you will be logged in after loggin in, in seconds
# Admin users: Users who register with these email addresses will automatically become administrators
# If no users exist in the database, a default admin user will be created with the first email in this list
admin_emails = ["admin@example.com", "admin2@example.com"]
# OpenID Connect settings

View File

@@ -85,7 +85,7 @@ from media_manager.exceptions import ( # noqa: E402
)
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore # noqa: E402
from starlette.responses import FileResponse # noqa: E402
from starlette.responses import FileResponse, RedirectResponse # noqa: E402
import media_manager.database # noqa: E402
import shutil # noqa: E402
@@ -147,10 +147,62 @@ scheduler.start()
@asynccontextmanager
async def lifespan(app: FastAPI):
# Startup: Create default admin user if needed
await create_default_admin_user()
yield
# Shutdown
scheduler.shutdown()
async def create_default_admin_user():
"""Create a default admin user if no users exist in the database"""
try:
from media_manager.auth.db import get_user_db
from media_manager.auth.users import get_user_manager
from media_manager.auth.schemas import UserCreate
from media_manager.database import get_session
from sqlalchemy import select, func
from media_manager.auth.db import User
async for session in get_session():
async for user_db in get_user_db(session):
async for user_manager in get_user_manager(user_db):
# Check if any users exist
result = await session.execute(select(func.count(User.id)))
user_count = result.scalar()
if user_count == 0:
log.info("No users found in database. Creating default admin user...")
# Use the first admin email from config, or default
admin_email = config.auth.admin_emails[0] if config.auth.admin_emails else "admin@mediamanager.local"
default_password = "admin" # Simple default password
user_create = UserCreate(
email=admin_email,
password=default_password,
is_superuser=True,
is_verified=True
)
user = await user_manager.create(user_create)
log.info("=" * 60)
log.info("✅ DEFAULT ADMIN USER CREATED!")
log.info(f" 📧 Email: {admin_email}")
log.info(f" 🔑 Password: {default_password}")
log.info(" ⚠️ IMPORTANT: Please change this password after first login!")
log.info("=" * 60)
else:
log.info(f"Found {user_count} existing users. Skipping default user creation.")
break
break
break
except Exception as e:
log.error(f"Failed to create default admin user: {e}")
log.info("You can create an admin user manually by registering with an email from the admin_emails list in your config.")
BASE_PATH = os.getenv("BASE_PATH", "")
FRONTEND_FILES_DIR = os.getenv("FRONTEND_FILES_DIR")
@@ -262,6 +314,20 @@ app.mount(
app.include_router(api_app)
app.mount("/web", StaticFiles(directory=FRONTEND_FILES_DIR, html=True), name="frontend")
# Add root route to redirect to web UI
@app.get("/")
async def root():
return RedirectResponse(url="/web/")
# Add common routes that users might try
@app.get("/dashboard")
async def dashboard():
return RedirectResponse(url="/web/")
@app.get("/login")
async def login():
return RedirectResponse(url="/web/")
# ----------------------------
# Custom Exception Handlers
# ----------------------------

View File

@@ -47,4 +47,11 @@ echo "Running DB migrations..."
uv run alembic upgrade head
echo "Starting MediaManager backend service..."
echo ""
echo "🔐 LOGIN INFORMATION:"
echo " If this is a fresh installation, a default admin user will be created automatically."
echo " Check the application logs for the login credentials."
echo " You can also register a new user and it will become admin if the email"
echo " matches one of the admin_emails in your config.toml"
echo ""
uv run fastapi run /app/media_manager/main.py --port 8000