Загрузка данных
# 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