Implement user authentication with hashed passwords

Replaces hardcoded admin credentials with a users table in the database, storing hashed passwords and user roles. Updates the login logic in app.py to authenticate against the database using Werkzeug's password hashing utilities. Adds admin credential configuration to config.py and ensures a default admin user is created during database initialization.
This commit is contained in:
Jon Ander Oribe
2026-01-11 17:54:43 +01:00
parent 03ce847196
commit dd56617c4c
5 changed files with 52 additions and 4 deletions
+21 -4
View File
@@ -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)
+3
View File
@@ -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."""
Binary file not shown.
+1
View File
@@ -29,6 +29,7 @@ dependencies = [
"flask>=2.0.0",
"skyfield>=1.45",
"pyserial>=3.5",
"Werkzeug>=3.1.5",
]
[project.urls]
+27
View File
@@ -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")