Security hardening: env SECRET_KEY, rate limiting, input validation, ownership checks

- SECRET_KEY desde variable de entorno (warn si no configurado)
- login: rate limiting (10 intentos / 15 min) + validación next param (open redirect fix)
- update_status: allowlist de estados válidos antes de ejecutar SQL
- purchase_update_status: allowlist contra PURCHASE_STATUSES
- save/clear_signature: allowlist _SIG_COLS para col derivado del request
- upload_invoice: validación de extensión contra ALLOWED_DOCS
- update_fields, update_labor, upload_photo, add_part_to_order: ownership check (empresa)
- update_status, save/clear_signature: ownership check en WO mutations
- auth.py: contraseña admin inicial desde ADMIN_PASSWORD env var

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-05 02:14:04 -04:00
parent 67a0e674ca
commit ab4c9c81b0
2 changed files with 96 additions and 10 deletions
+12 -2
View File
@@ -112,7 +112,13 @@ def verify_password(password, hashed):
return check_password_hash(hashed, password)
# ── Crear superadmin inicial ──────────────────────────────────────────────────
def create_initial_superadmin(username='admin', password='admin123', email='admin@marine.local'):
def create_initial_superadmin(username='admin', password=None, email='admin@marine.local'):
"""Crea el superadmin solo si no existe ninguno.
Password: variable de entorno ADMIN_PASSWORD, o 'admin123' como último recurso.
"""
import os
if password is None:
password = os.environ.get('ADMIN_PASSWORD', 'admin123')
conn = get_db()
existing = conn.execute("SELECT id FROM users WHERE role='superadmin'").fetchone()
if not existing:
@@ -121,5 +127,9 @@ def create_initial_superadmin(username='admin', password='admin123', email='admi
VALUES (NULL, ?, ?, ?, 'Super Administrator', 'superadmin')
""", (username, email, hash_password(password)))
conn.commit()
print(f"[AUTH] Superadmin creado: {username} / {password}")
if password == 'admin123':
print(f"[AUTH] ⚠️ Superadmin creado con contraseña por defecto. "
f"Configura ADMIN_PASSWORD en tu .env y reinicia.")
else:
print(f"[AUTH] Superadmin creado: {username}")
conn.close()