feat: add hardened HTTP Basic Auth for admin interface

This commit is contained in:
2026-03-10 10:07:09 -06:00
parent 047f1a8c8b
commit b2e7eeb570
2 changed files with 24 additions and 4 deletions
+19 -2
View File
@@ -96,13 +96,30 @@ Once deployed, open your browser and navigate to http://<your-server-ip>:8000 (o
`docker-compose logs -f` `docker-compose logs -f`
## Admin Interface
A password-protected admin panel is available at `/admin`. It displays all guest entries in a paginated table and allows individual entries to be deleted.
Access requires `ADMIN_USER` and `ADMIN_PASSWORD` to be set in your `.env`. If either variable is missing, the admin interface will return a 503 error rather than allowing access with blank credentials.
## API Access ## API Access
Access the API endpoint to export guest entries by navigating to: Access the API endpoint to export guest entries by navigating to:
`http://your-server-ip:8000/guests/api` `http://your-server-ip:8000/api/guests`
This endpoint can be integrated with on-prem automation tools like n8n. Set the `API_KEY` variable in your `.env` and pass it in requests as the `X-API-Key` header. This endpoint can be integrated with on-prem automation tools like n8n.
## Upgrading
When upgrading from a previous version, compare your `.env` against `example.env` to check for newly required variables. As of v2.1.0, the following variables are required if you want to use the admin interface:
```env
ADMIN_USER=admin
ADMIN_PASSWORD=changeme
```
Replace the placeholder values with your own credentials before deploying.
## Additional Notes ## Additional Notes
+5 -2
View File
@@ -181,9 +181,12 @@ def index():
def require_admin_auth(f): def require_admin_auth(f):
@wraps(f) @wraps(f)
def decorated(*args, **kwargs): def decorated(*args, **kwargs):
admin_user = os.environ.get('ADMIN_USER')
admin_password = os.environ.get('ADMIN_PASSWORD')
if not admin_user or not admin_password:
logger.error("ADMIN_USER and ADMIN_PASSWORD must be set to enable the admin interface.")
abort(503)
auth = request.authorization auth = request.authorization
admin_user = os.environ.get('ADMIN_USER', '')
admin_password = os.environ.get('ADMIN_PASSWORD', '')
if not auth or auth.username != admin_user or auth.password != admin_password: if not auth or auth.username != admin_user or auth.password != admin_password:
return Response( return Response(
'Authentication required.', 'Authentication required.',