Version: see VERSION
A security-focused Dash application with an AdminLTE 4-compatible UI, SQLite persistence, server-side RBAC, offline CAPTCHA, per-user session policy, and theming.
🔗 Live Demo: https://individualized-coffee-marmoset-a0542f36.plotly.app/
- Username: superadmin
- Password: CloudDemo1a
The app ships with separate LTR and RTL font catalogs under assets/fonts/.
| Direction | Families |
|---|---|
| LTR | Inter, Roboto, IBM Plex Sans, Source Sans 3, System |
| RTL | Vazirmatn, Shabnam, Samim, Sahel, BYekan, System |
Sections you can configure (button Aa next to the theme dropdown):
- Body text
- Headings / titles
- Sidebar / tabs
- Header / brand
- Cards / form labels
Preferences are saved per user in the database (font_prefs JSON) and also in localStorage so they survive refresh.
The available catalog follows APP_DIRECTION (derived from the active LTR/RTL stylesheet block in app.py).
- Local authentication with scrypt password hashing
- Roles:
superadmin>admin>user>guest(enforced on the server) - Superadmin User Manager (create/edit users, roles, expiry, timeouts)
- Offline CAPTCHA (Pillow; no external provider)
- Per-user session inactivity timeout and session-watchdog interval
- Per-user UI theme preference (persisted in the database)
- Change-password page (own password; superadmin can reset any user)
- Login rate limiting (per account and per IP)
- Security audit log
- Docker support (Compose or plain
Dockerfile)
- Python 3.11+ recommended (3.10+ should work)
- Dependencies: see
requirements.txt
python -m venv .venv
# Windows: .\.venv\Scripts\Activate.ps1
# Linux/macOS: source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .envSet a strong SECRET_KEY in .env (required for stable sessions in any real deployment):
python -c "import secrets; print(secrets.token_urlsafe(48))"Run:
python app.pyOpen http://127.0.0.1:1998.
If the database has no superadmin, one is created on startup. Check the terminal for:
- Username:
superadmin - A generated temporary password (unless
BOOTSTRAP_ADMIN_PASSWORDwas set)
Change that password after first login.
.
├── app.py # Application entry point
├── core/ # Core package (numbered by dependency / load order)
│ ├── 00_config.py
│ ├── 01_database.py
│ ├── 02_security.py
│ ├── 03_audit.py
│ ├── 04_captcha.py
│ ├── 05_themes.py
│ ├── 06_auth.py
│ ├── 07_user_repository.py
│ ├── 08_ui_components.py
│ ├── 09_user_manager.py
│ └── 10_change_password.py
├── pages/ # Dashboard tabs (auto-discovered)
│ ├── _page_widgets.py # Shared Bootstrap grid helpers
│ ├── tab_01.py
│ └── tab_role_*.py # RBAC demo pages
├── assets/
│ ├── themes/ # Light & dark theme CSS
│ ├── css/ # Bootstrap, Font Awesome, fonts, custom.css
│ └── adminlte/ # Optional local AdminLTE static files
├── scripts/
│ ├── 00_setup_project.py
│ └── 01_analyze_requirements.py
├── tests/
├── docker/
│ ├── Dockerfile
│ ├── docker-compose.yml
│ └── README.md # Compose and plain Docker instructions
├── data/ # SQLite at runtime (not committed)
├── .env.example
├── requirements.txt
├── SECURITY.md
├── VERSION
├── LICENSE
└── README.md
Friendly imports such as from core.auth import … are provided via aliases in core/__init__.py.
Copy .env.example to .env. Important variables:
| Variable | Default | Purpose |
|---|---|---|
SECRET_KEY |
(required in production) | Signs session cookies and CAPTCHA digests |
APP_NAME |
Dash AdminLTE |
Browser title / product name |
HOST / PORT |
0.0.0.0 / 1998 |
Bind address |
DATABASE_PATH |
data/app.db |
SQLite file |
DEFAULT_SESSION_TIMEOUT |
1800 |
Default inactivity timeout (seconds) |
DEFAULT_WATCHDOG_INTERVAL |
300 |
Default session-watchdog poll (seconds) |
SESSION_COOKIE_SECURE |
false |
Set true behind HTTPS |
BOOTSTRAP_ADMIN_PASSWORD |
(empty) | Optional initial superadmin password |
Details on SECRET_KEY and related hardening: SECURITY.md.
| Role | Access |
|---|---|
guest |
Lowest privilege authenticated role |
user |
Standard user pages |
admin |
Admin-level pages |
superadmin |
Full access, including User Manager |
Sidebar visibility is not authorization. Every page navigation is checked on the server using each page’s required_role (and hierarchical has_role()).
New tabs: add a module under pages/ with sidebar_item and layout(). Modules are loaded automatically.
Twelve built-in themes (six light, six dark) live under assets/themes/.
While logged in, the selected theme is stored on the user record (theme_id) and restored on the next login.
Full instructions (Compose and plain Docker): docker/README.md.
Summary:
cp .env.example .env # set SECRET_KEY
# Compose
docker compose -f docker/docker-compose.yml --env-file .env up --build
# Or Dockerfile only
docker build -f docker/Dockerfile -t dash-adminlte:latest .
docker run --rm -p 1998:1998 -e SECRET_KEY='...' -v dashboard-data:/app/data dash-adminlte:latestpython scripts/00_setup_project.py # ensure data/ exists, clean caches
python scripts/01_analyze_requirements.py # refresh requirements.txt from importsSee SECURITY.md for authentication, CAPTCHA, RBAC, session timeout, rate limiting, and secrets handling.
Do not commit .env, production databases under data/, or real secrets.
This project is licensed under the MIT License.

