morozovka-portal/app/main.py

102 lines
3.5 KiB
Python

from flask import Flask, render_template, jsonify, redirect, url_for, request, session
from .db import init_db, engine
from . import config, auth
from sqlmodel import Session, select
from .models import User
app = Flask(__name__)
app.secret_key = config.WEB_SECRET # Для подписи куки-сессий
# Инициализация БД
with app.app_context():
init_db()
@app.route("/healthz")
def healthz():
return jsonify({"status": "ok", "service": "morozovka-portal"})
@app.route("/")
def index():
# Если юзер уже в сессии, показываем имя
current_user = session.get("username")
return render_template("index.html", username=current_user)
# 1. Редирект на Gitea для авторизации
@app.route("/login")
def login():
gitea_auth_url = (
f"{config.GITEA_PUBLIC_URL}/login/oauth/authorize"
f"?client_id={config.GITEA_CLIENT_ID}&response_type=code"
f"&redirect_uri=https://portal.morozovka.space/auth/callback"
f"&scope=read:user"
)
return redirect(gitea_auth_url)
# 2. Колбэк от Gitea
@app.route("/auth/callback")
def auth_callback():
code = request.args.get("code")
if not code:
return "Ошибка: Gitea не передала код авторизации.", 400
# Меняем код на токен
token = auth.get_gitea_token(code)
if not token:
return "Ошибка: не удалось получить токен от Gitea.", 400
# Получаем юзера из Gitea
gitea_user = auth.get_gitea_user(token)
if not gitea_user:
return "Ошибка: не удалось получить профиль пользователя.", 400
# Сохраняем или обновляем в БД
with Session(engine) as db_session:
user = db_session.exec(select(User).where(User.gitea_id == gitea_user["id"])).first()
if not user:
# Создаем нового
new_user = User(
gitea_id=gitea_user["id"],
username=gitea_user["login"],
full_name=gitea_user.get("full_name"),
email=gitea_user.get("email"),
role="admin" if gitea_user["login"] == "git_admin" else "student" # Первому дадим админа
)
db_session.add(new_user)
db_session.commit()
user = new_user
else:
# Обновляем данные, если изменились в Gitea
user.username = gitea_user["login"]
user.full_name = gitea_user.get("full_name")
user.email = gitea_user.get("email")
db_session.add(user)
db_session.commit()
# Пишем в сессию Flask
session["user_id"] = user.id
session["username"] = user.username
return redirect(url_for("profile"))
# 3. Страница профиля (только для авторизованных)
@app.route("/profile")
def profile():
user_id = session.get("user_id")
if not user_id:
return redirect(url_for("login"))
with Session(engine) as db_session:
user = db_session.get(User, user_id)
if not user:
session.clear()
return redirect(url_for("login"))
return render_template("profile.html", user=user)
# 4. Выход
@app.route("/logout")
def logout():
session.clear()
return redirect(url_for("index"))