1. вернул обратно в код создание учетки из базы, и прогон парсеров через базу
This commit is contained in:
149
app.py
149
app.py
@@ -1,5 +1,5 @@
|
||||
from fastapi import FastAPI, Form, Request, Query, Body, HTTPException, WebSocket, WebSocketDisconnect
|
||||
from datetime import datetime, timezone
|
||||
from fastapi import FastAPI, Form, Request, Query, HTTPException, WebSocket, WebSocketDisconnect
|
||||
from datetime import datetime
|
||||
from fastapi.responses import (
|
||||
HTMLResponse,
|
||||
RedirectResponse,
|
||||
@@ -10,15 +10,21 @@ from fastapi.responses import (
|
||||
from fastapi.templating import Jinja2Templates
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from pydantic import BaseModel, Field
|
||||
from collections import defaultdict
|
||||
from typing import List, Optional, Dict, Any
|
||||
import json
|
||||
from typing import List, Dict
|
||||
from pathlib import Path
|
||||
import io
|
||||
import asyncio
|
||||
import time
|
||||
from urllib.parse import quote
|
||||
import traceback
|
||||
import contextlib
|
||||
from parsers.parser_game import run_parser_game
|
||||
from parsers.parser_players import run_parser_players
|
||||
from parsers.parser_schedule import run_parser_schedule
|
||||
from parsers.parser_standings import run_parser_standings
|
||||
|
||||
|
||||
from db import get_connection
|
||||
from repositories.match_formation_repository import (
|
||||
get_match_formations,
|
||||
replace_match_formations,
|
||||
@@ -85,6 +91,7 @@ from repositories.match_event_repository import (
|
||||
from repositories.auth_repository import get_user_by_username
|
||||
from services.auth_service import (
|
||||
create_auth_session,
|
||||
hash_password,
|
||||
verify_password,
|
||||
get_current_user_from_request,
|
||||
build_not_authenticated_response,
|
||||
@@ -1660,4 +1667,134 @@ def info_page(request: Request):
|
||||
name="info.html",
|
||||
request=request,
|
||||
context={}
|
||||
)
|
||||
)
|
||||
|
||||
def render_admin_db_index(request: Request, parser_output: str | None = None, parser_name: str | None = None, parser_success: bool | None = None):
|
||||
return templates.TemplateResponse(
|
||||
name="admin_db_index.html",
|
||||
request=request,
|
||||
context={
|
||||
"current_user": getattr(request.state, "current_user", None),
|
||||
"parser_output": parser_output,
|
||||
"parser_name": parser_name,
|
||||
"parser_success": parser_success,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@app.get("/admin/db", response_class=HTMLResponse)
|
||||
def admin_db_index(request: Request):
|
||||
return render_admin_db_index(request)
|
||||
|
||||
|
||||
@app.post("/admin/db/run-parser", response_class=HTMLResponse)
|
||||
def admin_db_run_parser(request: Request, parser_name: str = Form(...)):
|
||||
current_user = getattr(request.state, "current_user", None)
|
||||
if not current_user or current_user.get("role") != "admin":
|
||||
return RedirectResponse(url="/login", status_code=303)
|
||||
|
||||
parser_map = {
|
||||
"players": ("Игроки", run_parser_players),
|
||||
"schedule": ("Расписание", run_parser_schedule),
|
||||
"standings": ("Турнирка", run_parser_standings),
|
||||
}
|
||||
|
||||
parser_meta = parser_map.get(parser_name)
|
||||
if not parser_meta:
|
||||
return render_admin_db_index(
|
||||
request,
|
||||
parser_output="Неизвестный парсер.",
|
||||
parser_name=parser_name,
|
||||
parser_success=False,
|
||||
)
|
||||
|
||||
title, parser_func = parser_meta
|
||||
buffer = io.StringIO()
|
||||
success = True
|
||||
|
||||
with contextlib.redirect_stdout(buffer), contextlib.redirect_stderr(buffer):
|
||||
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Запуск парсера: {title}")
|
||||
try:
|
||||
parser_func()
|
||||
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Парсер завершён успешно")
|
||||
except Exception:
|
||||
success = False
|
||||
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Ошибка при выполнении парсера")
|
||||
print(traceback.format_exc())
|
||||
|
||||
output = buffer.getvalue().strip() or "Парсер не вернул сообщений."
|
||||
return render_admin_db_index(
|
||||
request,
|
||||
parser_output=output,
|
||||
parser_name=title,
|
||||
parser_success=success,
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
@app.post("/admin/db/create-account", response_class=HTMLResponse)
|
||||
def admin_db_create_account(
|
||||
request: Request,
|
||||
username: str = Form(...),
|
||||
password: str = Form(...),
|
||||
role: str = Form(default="operator"),
|
||||
):
|
||||
current_user = getattr(request.state, "current_user", None)
|
||||
if not current_user or current_user.get("role") != "admin":
|
||||
return RedirectResponse(url="/login", status_code=303)
|
||||
|
||||
username = username.strip()
|
||||
role = (role or "operator").strip().lower()
|
||||
|
||||
if not username:
|
||||
return render_admin_db_index(request, account_output="Логин обязателен.", account_success=False)
|
||||
|
||||
if not password:
|
||||
return render_admin_db_index(request, account_output="Пароль обязателен.", account_success=False)
|
||||
|
||||
if len(password) < 6:
|
||||
return render_admin_db_index(request, account_output="Пароль должен быть не короче 6 символов.", account_success=False)
|
||||
|
||||
if role not in {"admin", "operator"}:
|
||||
return render_admin_db_index(request, account_output="Роль должна быть admin или operator.", account_success=False)
|
||||
|
||||
password_hash = hash_password(password)
|
||||
conn = get_connection()
|
||||
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
"""
|
||||
INSERT INTO admin_users (username, password_hash, role, is_active)
|
||||
VALUES (%s, %s, %s, TRUE)
|
||||
ON CONFLICT (username) DO NOTHING
|
||||
RETURNING id;
|
||||
""",
|
||||
(username, password_hash, role),
|
||||
)
|
||||
row = cur.fetchone()
|
||||
conn.commit()
|
||||
|
||||
if row:
|
||||
return render_admin_db_index(
|
||||
request,
|
||||
account_output=f"Пользователь создан: {username} (id={row[0]})\nРоль: {role}",
|
||||
account_success=True,
|
||||
)
|
||||
|
||||
return render_admin_db_index(
|
||||
request,
|
||||
account_output=f"Пользователь '{username}' уже существует.",
|
||||
account_success=False,
|
||||
)
|
||||
|
||||
except Exception:
|
||||
conn.rollback()
|
||||
return render_admin_db_index(
|
||||
request,
|
||||
account_output="Ошибка при создании аккаунта:\n" + traceback.format_exc(),
|
||||
account_success=False,
|
||||
)
|
||||
finally:
|
||||
conn.close()
|
||||
Reference in New Issue
Block a user