diff --git a/app.py b/app.py index 1c487f7..f6038b2 100644 --- a/app.py +++ b/app.py @@ -9,6 +9,8 @@ from __future__ import annotations import sys import site +from utils.database import get_db + # Ensure user site-packages is available (may be disabled when running as root/sudo) if not site.ENABLE_USER_SITE: user_site = site.getusersitepackages() @@ -24,7 +26,7 @@ import subprocess from typing import Any from flask import Flask, render_template, jsonify, send_file, Response, request,redirect, url_for, flash, session - +from werkzeug.security import check_password_hash from config import VERSION from utils.dependencies import check_tool, check_all_dependencies, TOOL_DEPENDENCIES from utils.process import cleanup_stale_processes @@ -36,11 +38,11 @@ from utils.constants import ( MAX_BT_DEVICE_AGE_SECONDS, QUEUE_MAX_SIZE, ) - +import logging # Track application start time for uptime calculation import time as _time _app_start_time = _time.time() - +logger = logging.getLogger('intercept.database') # Create Flask app app = Flask(__name__) @@ -162,10 +164,25 @@ def login(): username = request.form.get('username') password = request.form.get('password') - if username == "admin" and password == "intercept2026": + # 1. Conectar a la DB y buscar al usuario + with get_db() as conn: + cursor = conn.execute( + 'SELECT password_hash, role FROM users WHERE username = ?', + (username,) + ) + user = cursor.fetchone() + + # 2. Verificar si el usuario existe y la contraseña es correcta + if user and check_password_hash(user['password_hash'], password): + # Guardamos datos en la sesión session['logged_in'] = True + session['username'] = username + session['role'] = user['role'] + + logger.info(f"User '{username}' logged in successfully.") return redirect(url_for('index')) else: + logger.warning(f"Failed login attempt for username: {username}") flash("ACCESS DENIED: INVALID CREDENTIALS", "error") return render_template('login.html', version=VERSION) diff --git a/config.py b/config.py index 5bd4ec8..93d3eaa 100644 --- a/config.py +++ b/config.py @@ -81,6 +81,9 @@ SATELLITE_UPDATE_INTERVAL = _get_env_int('SATELLITE_UPDATE_INTERVAL', 30) SATELLITE_TRAJECTORY_POINTS = _get_env_int('SATELLITE_TRAJECTORY_POINTS', 30) SATELLITE_ORBIT_MINUTES = _get_env_int('SATELLITE_ORBIT_MINUTES', 45) +# Admin credentials +ADMIN_USERNAME = _get_env('ADMIN_USERNAME', 'admin') +ADMIN_PASSWORD = _get_env('ADMIN_PASSWORD', 'intercept') def configure_logging() -> None: """Configure application logging.""" diff --git a/instance/intercept.db b/instance/intercept.db index 15137ad..5462404 100644 Binary files a/instance/intercept.db and b/instance/intercept.db differ diff --git a/pyproject.toml b/pyproject.toml index 9ea365b..05c8d65 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,6 +29,7 @@ dependencies = [ "flask>=2.0.0", "skyfield>=1.45", "pyserial>=3.5", + "Werkzeug>=3.1.5", ] [project.urls] diff --git a/utils/database.py b/utils/database.py index 1534849..2d52109 100644 --- a/utils/database.py +++ b/utils/database.py @@ -12,6 +12,8 @@ from contextlib import contextmanager from datetime import datetime from pathlib import Path from typing import Any +from werkzeug.security import generate_password_hash +from config import ADMIN_USERNAME, ADMIN_PASSWORD logger = logging.getLogger('intercept.database') @@ -100,6 +102,31 @@ def init_db() -> None: ) ''') + # Users table for authentication + conn.execute(''' + CREATE TABLE IF NOT EXISTS users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + username TEXT UNIQUE NOT NULL, + password_hash TEXT NOT NULL, + role TEXT NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ) + ''') + + cursor = conn.execute('SELECT COUNT(*) FROM users') + if cursor.fetchone()[0] == 0: + from config import ADMIN_USERNAME, ADMIN_PASSWORD + + logger.info(f"Creating default admin user: {ADMIN_USERNAME}") + + # Password hashing + hashed_pw = generate_password_hash(ADMIN_PASSWORD) + + conn.execute(''' + INSERT INTO users (username, password_hash, role) + VALUES (?, ?, ?) + ''', (ADMIN_USERNAME, hashed_pw, 'admin')) + logger.info("Database initialized successfully")