Загрузка данных


# Dozor/modules/administrator/user_logic.py
import os
import sqlite3
import hashlib
import secrets

class UserLogic:
    def __init__(self, db_path="db/users.db"):
        self.db_path = db_path
        if not os.path.exists(os.path.dirname(db_path)):
            os.makedirs(os.path.dirname(db_path))
        self._ensure_schema()

    def _hash_password(self, password: str, salt: str) -> str:
        return hashlib.sha256((salt + password).encode()).hexdigest()

    def _generate_salt(self) -> str:
        return secrets.token_hex(16)

    def _ensure_schema(self):
        with sqlite3.connect(self.db_path) as conn:
            cursor = conn.cursor()
            
            # Проверяем структуру. Если колонки login нет — таблица старая.
            cursor.execute("PRAGMA table_info(users)")
            columns = [col[1] for col in cursor.fetchall()]
            
            if "login" not in columns or len(columns) < 4:
                print("[INFO] Структура users.db некорректна. Пересоздаем...")
                cursor.execute("DROP TABLE IF EXISTS users")
            
            cursor.execute('''
                CREATE TABLE IF NOT EXISTS users (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    login TEXT UNIQUE NOT NULL,
                    password_hash TEXT NOT NULL,
                    salt TEXT NOT NULL,
                    role TEXT NOT NULL
                )
            ''')
            
            # Создаем дефолтного админа ТОЛЬКО если таблицы пуста
            cursor.execute("SELECT COUNT(*) FROM users")
            if cursor.fetchone()[0] == 0:
                salt = secrets.token_hex(16)
                pwd_hash = hashlib.sha256((salt + "admin").encode()).hexdigest()
                cursor.execute(
                    "INSERT INTO users (login, password_hash, salt, role) VALUES (?, ?, ?, ?)",
                    ("admin", pwd_hash, salt, "Администратор")
                )
                print("[INFO] Создан пользователь 'admin' с паролем 'admin'")
                
            conn.commit()

    def get_all_users(self):
        try:
            with sqlite3.connect(self.db_path) as conn:
                return conn.execute("SELECT id, login, role FROM users ORDER BY id ASC").fetchall()
        except Exception:
            self._ensure_schema()
            return [(1, "admin", "Администратор")]

    def add_user(self, login: str, role: str, password: str):
        valid_roles = ["Администратор", "Эксперт", "Пользователь"]
        if role not in valid_roles:
            raise ValueError(f"Недопустимая роль: {role}")
            
        salt = self._generate_salt()
        pwd_hash = self._hash_password(password, salt)
        with sqlite3.connect(self.db_path) as conn:
            conn.execute(
                "INSERT INTO users (login, password_hash, salt, role) VALUES (?, ?, ?, ?)",
                (login, pwd_hash, salt, role)
            )
            conn.commit()

    def delete_user(self, user_id: int):
        with sqlite3.connect(self.db_path) as conn:
            cursor = conn.cursor()
            cursor.execute("DELETE FROM users WHERE id=?", (user_id,))
            cursor.execute("UPDATE users SET id = id - 1 WHERE id > ?", (user_id,))
            max_id = cursor.execute("SELECT MAX(id) FROM users").fetchone()[0] or 0
            cursor.execute("UPDATE sqlite_sequence SET seq=? WHERE name='users'", (max_id,))
            conn.commit()

    def validate_credentials(self, login: str, password: str) -> bool:
        """
        Проверяет пару логин/пароль по базе данных.
        Возвращает True при успехе, False при неудаче.
        """
        try:
            with sqlite3.connect(self.db_path) as conn:
                cursor = conn.cursor()
                # Ищем пользователя по логину
                row = cursor.execute(
                    "SELECT password_hash, salt FROM users WHERE login=?", (login,)
                ).fetchone()
                
                if not row:
                    return False  # Пользователь не найден

                stored_hash, salt = row
                
                # Хэшируем введенный пароль с той же солью из базы
                test_hash = hashlib.sha256((salt + password).encode()).hexdigest()
                
                # Сравниваем хэши
                return stored_hash == test_hash
        except Exception as e:
            print(f"[DB ERROR] Ошибка проверки пароля: {e}")
            return False