aurweb/aurweb/routers/auth.py
moson-mo 638ca7b1d0
chore: remove setting AURLANG and AURTZ on login
We don't need to set these cookies when logging in.
These settings are saved to the DB anyways.
(and they are picked up from there as well for any web requests,
when no cookies are given)

Signed-off-by: moson-mo <mo-son@mailbox.org>
2023-05-26 22:57:46 +02:00

115 lines
3.6 KiB
Python

from http import HTTPStatus
from fastapi import APIRouter, Form, HTTPException, Request
from fastapi.responses import HTMLResponse, RedirectResponse
from sqlalchemy import or_
import aurweb.config
from aurweb import cookies, db
from aurweb.auth import requires_auth, requires_guest
from aurweb.exceptions import handle_form_exceptions
from aurweb.l10n import get_translator_for_request
from aurweb.models import User
from aurweb.templates import make_variable_context, render_template
router = APIRouter()
async def login_template(request: Request, next: str, errors: list = None):
"""Provide login-specific template context to render_template."""
context = await make_variable_context(request, "Login", next)
context["errors"] = errors
context["url_base"] = f"{request.url.scheme}://{request.url.netloc}"
return render_template(request, "login.html", context)
@router.get("/login", response_class=HTMLResponse)
async def login_get(request: Request, next: str = "/"):
return await login_template(request, next)
@db.retry_deadlock
def _retry_login(request: Request, user: User, passwd: str, cookie_timeout: int) -> str:
return user.login(request, passwd, cookie_timeout)
@router.post("/login", response_class=HTMLResponse)
@handle_form_exceptions
@requires_guest
async def login_post(
request: Request,
next: str = Form(...),
user: str = Form(default=str()),
passwd: str = Form(default=str()),
remember_me: bool = Form(default=False),
):
# TODO: Once the Origin header gets broader adoption, this code can be
# slightly simplified to use it.
login_path = aurweb.config.get("options", "aur_location") + "/login"
referer = request.headers.get("Referer")
if not referer or not referer.startswith(login_path):
_ = get_translator_for_request(request)
raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST, detail=_("Bad Referer header.")
)
user = (
db.query(User)
.filter(
or_(
User.Username == user,
User.Email == user,
)
)
.first()
)
if not user:
return await login_template(request, next, errors=["Bad username or password."])
if user.Suspended:
return await login_template(request, next, errors=["Account Suspended"])
cookie_timeout = cookies.timeout(remember_me)
sid = _retry_login(request, user, passwd, cookie_timeout)
if not sid:
return await login_template(request, next, errors=["Bad username or password."])
response = RedirectResponse(url=next, status_code=HTTPStatus.SEE_OTHER)
secure = aurweb.config.getboolean("options", "disable_http_login")
response.set_cookie(
"AURSID",
sid,
max_age=cookie_timeout,
secure=secure,
httponly=secure,
samesite=cookies.samesite(),
)
response.set_cookie(
"AURREMEMBER",
remember_me,
secure=secure,
httponly=secure,
samesite=cookies.samesite(),
)
return response
@db.retry_deadlock
def _retry_logout(request: Request) -> None:
request.user.logout(request)
@router.post("/logout")
@handle_form_exceptions
@requires_auth
async def logout(request: Request, next: str = Form(default="/")):
if request.user.is_authenticated():
_retry_logout(request)
# Use 303 since we may be handling a post request, that'll get it
# to redirect to a get request.
response = RedirectResponse(url=next, status_code=HTTPStatus.SEE_OTHER)
response.delete_cookie("AURSID")
response.delete_cookie("AURREMEMBER")
return response