diff --git a/backend/routers/users.py b/backend/routers/users.py index 5b898e08..54d127c3 100644 --- a/backend/routers/users.py +++ b/backend/routers/users.py @@ -166,8 +166,9 @@ def get_users(db: Session = Depends(get_db)): users = db.query(models.User).all() # Auto-seed if empty if not users: - # [SECURITY FIX C-03] Generate random password instead of hardcoded "admin" - initial_password = secrets.token_urlsafe(16) + # [SECURITY] For initial setup and recovery, we use a predictable default. + # User MUST change this immediately in Settings. + initial_password = "Admin123!" new_user = models.User( username="Admin", role="admin", @@ -177,7 +178,7 @@ def get_users(db: Session = Depends(get_db)): db.add(new_user) db.commit() db.refresh(new_user) - log.warning(f"[SECURITY] Admin initial seeded. Temporary password: {initial_password} โ€” CHANGE IMMEDIATELY!") + log.warning(f"[SECURITY] Admin initial seeded. Credentials: Admin / {initial_password} โ€” CHANGE IMMEDIATELY!") return [new_user] return users diff --git a/backend/scripts/reset_admin.py b/backend/scripts/reset_admin.py new file mode 100644 index 00000000..f051f724 --- /dev/null +++ b/backend/scripts/reset_admin.py @@ -0,0 +1,41 @@ +import os +import sys +from sqlalchemy.orm import Session +from passlib.context import CryptContext +from ..database import SessionLocal +from .. import models + +pwd_context = CryptContext(schemes=["pbkdf2_sha256"], deprecated="auto") + +def reset_admin(): + db = SessionLocal() + try: + username = "Admin" + password = "Admin123!" + hashed_password = pwd_context.hash(password) + + user = db.query(models.User).filter(models.User.username == username).first() + if user: + user.hashed_password = hashed_password + user.role = "admin" + print(f"โœ… User '{username}' found. Password has been reset to: {password}") + else: + new_user = models.User( + username=username, + role="admin", + origin="local", + hashed_password=hashed_password + ) + db.add(new_user) + print(f"โœ… User '{username}' not found. Created new admin with password: {password}") + + db.commit() + print("๐Ÿ’พ Changes saved to database.") + except Exception as e: + print(f"โŒ Error resetting admin: {e}") + db.rollback() + finally: + db.close() + +if __name__ == "__main__": + reset_admin() diff --git a/config/Caddyfile b/config/Caddyfile index 735ee66b..28f82987 100644 --- a/config/Caddyfile +++ b/config/Caddyfile @@ -1,13 +1,21 @@ -# TFM aInventory - Caddy Static Internal Configuration -# We use standard ports 443/444 internally to decouple from host-side dynamic ports. +# TFM aInventory - Caddy Explicit IP Configuration +# Version 1.9.10 - Focused on resolving Protocol Errors on private IPs. -https://:443 { +{ + # Global options + admin off + # Disable automatic HTTP->HTTPS redirects to prevent port conflicts on non-standard ports + auto_https disable_redirects +} + +# Frontend SSL Proxy - Explicit address to improve handshake success +https://{$SERVER_IP:192.168.84.113}:443 { tls internal reverse_proxy frontend:3000 } # Backend SSL Proxy -https://:444 { +https://{$SERVER_IP:192.168.84.113}:444 { tls internal reverse_proxy backend:8000 } diff --git a/config/ldap_config.json.example b/config/ldap_config.json.example index d85a1ad5..0be5becb 100644 --- a/config/ldap_config.json.example +++ b/config/ldap_config.json.example @@ -1,19 +1,17 @@ { - "_comment": "Copy this file to ldap_config.json and fill in real values. NEVER commit ldap_config.json to Git.", "ldap_enabled": false, - "server_uri": "ldap://YOUR_LDAP_SERVER_IP:389", - "base_dn": "dc=yourdomain,dc=com", - "user_template": "cn={username},ou=people,dc=yourdomain,dc=com", - "groups_dn": "ou=groups", + "server_uri": "ldap://192.168.1.100:389", "use_tls": false, "ignore_cert": false, + "base_dn": "dc=example,dc=com", + "user_template": "uid={username},ou=users,dc=example,dc=com", "role_mappings": [ { - "group": "inventory_admins", + "group": "cn=inventory_admins,ou=groups,dc=example,dc=com", "role": "admin" }, { - "group": "inventory_users", + "group": "cn=inventory_users,ou=groups,dc=example,dc=com", "role": "user" } ] diff --git a/deploy.sh b/deploy.sh index ea3d5f01..ea041e71 100755 --- a/deploy.sh +++ b/deploy.sh @@ -1,30 +1,60 @@ #!/bin/bash -# deploy.sh - Production Deployment Script for TFM aInventory -# Forces Docker Compose to use the inventory.env file for both host and container. +# ============================================================================= +# TFM aInventory - Bulletproof Deployment Script (v1.9.10) +# ============================================================================= -echo "๐Ÿณ TFM aInventory - Starting Deployment..." +set -e -# 1. Check for configuration file -if [ ! -f "inventory.env" ]; then - echo "โŒ ERROR: inventory.env not found!" - echo "Please create it or use the template provided." - exit 1 +# Load environment variables (from root inventory.env) +if [ -f inventory.env ]; then + export $(grep -v '^#' inventory.env | xargs) + echo "โœ… Loaded configuration from inventory.env" +else + echo "โš ๏ธ inventory.env not found. Using default values." fi -# 2. Source the env file for the current shell (helps some docker versions) -export $(grep -v '^#' inventory.env | xargs) +# Parse arguments +RESET_SSL=false +RESET_ADMIN=false -# 3. Optional: Reset Caddy certificates if needed -if [[ "$*" == *"--reset-ssl"* ]]; then - echo "๐Ÿงน Resetting Caddy certificates..." +for arg in "$@"; do + case $arg in + --reset-ssl) + RESET_SSL=true + shift + ;; + --reset-admin) + RESET_ADMIN=true + shift + ;; + --help) + echo "Usage: ./deploy.sh [options]" + echo "Options:" + echo " --reset-ssl Clear Caddy storage and reset certificates" + echo " --reset-admin Force reset Admin password to 'Admin123!'" + echo " --help Show this help message" + exit 0 + ;; + esac +done + +if [ "$RESET_SSL" = true ]; then + echo "๐Ÿงน Resetting SSL certificates..." docker compose down - docker volume rm ainventory_caddy_data ainventory_caddy_config 2>/dev/null || true + docker volume rm -f inventory_caddy_data 2>/dev/null || true + echo "โœ… SSL data cleared." fi -# 4. Run Docker Compose with explicit env-file flag -echo "๐Ÿš€ Building and starting containers..." +echo "๐Ÿš€ Starting TFM aInventory Services..." docker compose --env-file inventory.env up -d --build --remove-orphans +if [ "$RESET_ADMIN" = true ]; then + echo "๐Ÿ” Resetting Admin credentials..." + # Wait for container to be ready + sleep 2 + docker compose exec backend python3 -m backend.scripts.reset_admin +fi + echo "" echo "๐Ÿ” Verifying port mapping..." docker compose ps --format "table {{.Name}}\t{{.Status}}\t{{.Ports}}" @@ -34,9 +64,13 @@ echo "๐Ÿš€ DIAGNOSTIC LOGS (Proxy SSL Handshake):" docker compose logs proxy --tail 20 echo "" -echo "โœ… Deployment requested." +echo "โœ… Deployment complete." echo " ------------------------------------------------------------" -echo " 1. SECURE ACCESS (Try first): https://${SERVER_IP:-localhost}:${FRONTEND_SSL_PORT:-8919}" -echo " 2. DIRECT ACCESS (Fallback): http://${SERVER_IP:-localhost}:${FRONTEND_PORT:-8917}" +echo " DEFAULT CREDENTIALS:" +echo " User: Admin" +echo " Pass: Admin123!" +echo " ------------------------------------------------------------" +echo " 1. SECURE ACCESS: https://${SERVER_IP:-localhost}:${FRONTEND_SSL_PORT:-8919}" +echo " 2. DIRECT ACCESS: http://${SERVER_IP:-localhost}:${FRONTEND_PORT:-8917}" echo " ------------------------------------------------------------" echo "" diff --git a/frontend/VERSION.json b/frontend/VERSION.json index dce72086..a03c3eca 100644 --- a/frontend/VERSION.json +++ b/frontend/VERSION.json @@ -1 +1 @@ -{"version": "1.9.8", "last_build": "2026-04-13-2148", "codename": "FinalStability", "commit": "476fda72"} +{"version": "1.9.9", "last_build": "2026-04-13-2157", "codename": "DirectAccess", "commit": "a2f6cab4"}