diff --git a/aurweb/auth/__init__.py b/aurweb/auth/__init__.py index 7aa4b526..8ceb136c 100644 --- a/aurweb/auth/__init__.py +++ b/aurweb/auth/__init__.py @@ -5,6 +5,7 @@ from http import HTTPStatus import fastapi +from fastapi import HTTPException from fastapi.responses import RedirectResponse from sqlalchemy import and_ from starlette.authentication import AuthCredentials, AuthenticationBackend @@ -15,7 +16,6 @@ import aurweb.config from aurweb import db, l10n, util from aurweb.models import Session, User from aurweb.models.account_type import ACCOUNT_TYPE_ID -from aurweb.templates import make_variable_context, render_template class StubQuery: @@ -125,29 +125,7 @@ def auth_required(is_required: bool = True, status_code: HTTPStatus = HTTPStatus.UNAUTHORIZED): """ Authentication route decorator. - If template is given, it will be rendered with Unauthorized if - is_required does not match. - - A precondition of this function is that, if template is provided, - it **must** match the following format: - - template=("template.html", ["Some Template For", "{}"], ["username"]) - - Where `username` is a FastAPI request path parameter, fitting - a route like: `/some_route/{username}`. - - If you wish to supply a non-formatted template, just omit any Python - format strings (with the '{}' substring). The third tuple element - will not be used, and so anything can be supplied. - - template=("template.html", ["Some Page"], None) - - All title shards and format parameters will be translated before - applying any format operations. - :param is_required: A boolean indicating whether the function requires auth - :param template: A three-element template tuple: - (path, title_iterable, variable_iterable) :param status_code: An optional status_code for template render. Redirects are always SEE_OTHER. """ @@ -164,45 +142,12 @@ def auth_required(is_required: bool = True, elif request.method == "POST" and (referer := request.headers.get("Referer")): aur = aurweb.config.get("options", "aur_location") + "/" if not referer.startswith(aur): + _ = l10n.get_translator_for_request(request) raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail=_("Bad Referer header.")) url = referer[len(aur) - 1:] url = "/login?" + util.urlencode({"next": url}) - - if template: - # template=("template.html", - # ["Some Title", "someFormatted {}"], - # ["variable"]) - # => render template.html with title: - # "Some Title someFormatted variables" - path, title_parts, variables = template - _ = l10n.get_translator_for_request(request) - - # Step through title_parts; for each part which contains - # a '{}' in it, apply .format(var) where var = the current - # iteration of variables. - # - # This implies that len(variables) is equal to - # len([part for part in title_parts if '{}' in part]) - # and this must always be true. - # - sanitized = [] - _variables = iter(variables) - for part in title_parts: - if "{}" in part: # If this part is formattable. - key = next(_variables) - var = request.path_params.get(key) - sanitized.append(_(part.format(var))) - else: # Otherwise, just add the translated part. - sanitized.append(_(part)) - - # Glue all title parts together, separated by spaces. - title = " ".join(sanitized) - - context = await make_variable_context(request, title) - return render_template(request, path, context, - status_code=status_code) return RedirectResponse(url, status_code=int(HTTPStatus.SEE_OTHER)) return await func(request, *args, **kwargs) diff --git a/aurweb/routers/accounts.py b/aurweb/routers/accounts.py index dade92bb..388daf84 100644 --- a/aurweb/routers/accounts.py +++ b/aurweb/routers/accounts.py @@ -340,7 +340,7 @@ def cannot_edit(request, user): @router.get("/account/{username}/edit", response_class=HTMLResponse) -@auth_required(True) +@auth_required() async def account_edit(request: Request, username: str): user = db.query(models.User, models.User.Username == username).first() @@ -356,7 +356,7 @@ async def account_edit(request: Request, username: str): @router.post("/account/{username}/edit", response_class=HTMLResponse) -@auth_required(True) +@auth_required() async def account_edit_post(request: Request, username: str, U: str = Form(default=str()), # Username @@ -424,20 +424,14 @@ async def account_edit_post(request: Request, aurtz=TZ, aurlang=L) -account_template = ( - "account/show.html", - ["Account", "{}"], - ["username"] # Query parameters to replace in the title string. -) - - @router.get("/account/{username}") -@auth_required(True, template=account_template, - status_code=HTTPStatus.UNAUTHORIZED) async def account(request: Request, username: str): _ = l10n.get_translator_for_request(request) context = await make_variable_context( request, _("Account") + " " + username) + if not request.user.is_authenticated(): + return render_template(request, "account/show.html", context, + status_code=HTTPStatus.UNAUTHORIZED) context["user"] = get_user_by_name(username) return render_template(request, "account/show.html", context) @@ -454,7 +448,7 @@ async def account_comments(request: Request, username: str): @router.get("/accounts") -@auth_required(True) +@auth_required() @account_type_required({at.TRUSTED_USER, at.DEVELOPER, at.TRUSTED_USER_AND_DEV}) @@ -464,7 +458,7 @@ async def accounts(request: Request): @router.post("/accounts") -@auth_required(True) +@auth_required() @account_type_required({at.TRUSTED_USER, at.DEVELOPER, at.TRUSTED_USER_AND_DEV}) @@ -548,7 +542,7 @@ def render_terms_of_service(request: Request, @router.get("/tos") -@auth_required(True) +@auth_required() async def terms_of_service(request: Request): # Query the database for terms that were previously accepted, # but now have a bumped Revision that needs to be accepted. @@ -572,7 +566,7 @@ async def terms_of_service(request: Request): @router.post("/tos") -@auth_required(True) +@auth_required() async def terms_of_service_post(request: Request, accept: bool = Form(default=False)): # Query the database for terms that were previously accepted, diff --git a/aurweb/routers/packages.py b/aurweb/routers/packages.py index 4a2cdce3..c06ec51f 100644 --- a/aurweb/routers/packages.py +++ b/aurweb/routers/packages.py @@ -295,7 +295,7 @@ async def package_base_voters(request: Request, name: str) -> Response: @router.post("/pkgbase/{name}/comments") -@auth_required(True) +@auth_required() async def pkgbase_comments_post( request: Request, name: str, comment: str = Form(default=str()), @@ -327,7 +327,7 @@ async def pkgbase_comments_post( @router.get("/pkgbase/{name}/comments/{id}/form") -@auth_required(True) +@auth_required() async def pkgbase_comment_form(request: Request, name: str, id: int, next: str = Query(default=None)): """ Produce a comment form for comment {id}. """ @@ -353,7 +353,7 @@ async def pkgbase_comment_form(request: Request, name: str, id: int, @router.post("/pkgbase/{name}/comments/{id}") -@auth_required(True) +@auth_required() async def pkgbase_comment_post( request: Request, name: str, id: int, comment: str = Form(default=str()), @@ -392,7 +392,7 @@ async def pkgbase_comment_post( @router.get("/pkgbase/{name}/comments/{id}/edit") -@auth_required(True) +@auth_required() async def pkgbase_comment_edit(request: Request, name: str, id: int, next: str = Form(default=None)): pkgbase = get_pkg_or_base(name, models.PackageBase) @@ -407,7 +407,7 @@ async def pkgbase_comment_edit(request: Request, name: str, id: int, @router.post("/pkgbase/{name}/comments/{id}/delete") -@auth_required(True) +@auth_required() async def pkgbase_comment_delete(request: Request, name: str, id: int, next: str = Form(default=None)): pkgbase = get_pkg_or_base(name, models.PackageBase) @@ -433,7 +433,7 @@ async def pkgbase_comment_delete(request: Request, name: str, id: int, @router.post("/pkgbase/{name}/comments/{id}/undelete") -@auth_required(True) +@auth_required() async def pkgbase_comment_undelete(request: Request, name: str, id: int, next: str = Form(default=None)): pkgbase = get_pkg_or_base(name, models.PackageBase) @@ -458,7 +458,7 @@ async def pkgbase_comment_undelete(request: Request, name: str, id: int, @router.post("/pkgbase/{name}/comments/{id}/pin") -@auth_required(True) +@auth_required() async def pkgbase_comment_pin(request: Request, name: str, id: int, next: str = Form(default=None)): pkgbase = get_pkg_or_base(name, models.PackageBase) @@ -483,7 +483,7 @@ async def pkgbase_comment_pin(request: Request, name: str, id: int, @router.post("/pkgbase/{name}/comments/{id}/unpin") -@auth_required(True) +@auth_required() async def pkgbase_comment_unpin(request: Request, name: str, id: int, next: str = Form(default=None)): pkgbase = get_pkg_or_base(name, models.PackageBase) @@ -507,7 +507,7 @@ async def pkgbase_comment_unpin(request: Request, name: str, id: int, @router.get("/pkgbase/{name}/comaintainers") -@auth_required(True) +@auth_required() async def package_base_comaintainers(request: Request, name: str) -> Response: # Get the PackageBase. pkgbase = get_pkg_or_base(name, models.PackageBase) @@ -532,7 +532,7 @@ async def package_base_comaintainers(request: Request, name: str) -> Response: @router.post("/pkgbase/{name}/comaintainers") -@auth_required(True) +@auth_required() async def package_base_comaintainers_post( request: Request, name: str, users: str = Form(default=str())) -> Response: @@ -584,7 +584,7 @@ async def package_base_comaintainers_post( @router.get("/requests") -@auth_required(True) +@auth_required() async def requests(request: Request, O: int = Query(default=defaults.O), PP: int = Query(default=defaults.PP)): @@ -618,7 +618,7 @@ async def requests(request: Request, @router.get("/pkgbase/{name}/request") -@auth_required(True) +@auth_required() async def package_request(request: Request, name: str): pkgbase = get_pkg_or_base(name, models.PackageBase) context = await make_variable_context(request, "Submit Request") @@ -627,7 +627,7 @@ async def package_request(request: Request, name: str): @router.post("/pkgbase/{name}/request") -@auth_required(True) +@auth_required() async def pkgbase_request_post(request: Request, name: str, type: str = Form(...), merge_into: str = Form(default=None), @@ -699,7 +699,7 @@ async def pkgbase_request_post(request: Request, name: str, @router.get("/requests/{id}/close") -@auth_required(True) +@auth_required() async def requests_close(request: Request, id: int): pkgreq = get_pkgreq_by_id(id) if not request.user.is_elevated() and request.user != pkgreq.User: @@ -712,7 +712,7 @@ async def requests_close(request: Request, id: int): @router.post("/requests/{id}/close") -@auth_required(True) +@auth_required() async def requests_close_post(request: Request, id: int, reason: int = Form(default=0), comments: str = Form(default=str())): @@ -775,7 +775,7 @@ async def pkgbase_keywords(request: Request, name: str, @router.get("/pkgbase/{name}/flag") -@auth_required(True) +@auth_required() async def pkgbase_flag_get(request: Request, name: str): pkgbase = get_pkg_or_base(name, models.PackageBase) @@ -790,7 +790,7 @@ async def pkgbase_flag_get(request: Request, name: str): @router.post("/pkgbase/{name}/flag") -@auth_required(True) +@auth_required() async def pkgbase_flag_post(request: Request, name: str, comments: str = Form(default=str())): pkgbase = get_pkg_or_base(name, models.PackageBase) @@ -839,7 +839,7 @@ def pkgbase_unflag_instance(request: Request, pkgbase: models.PackageBase): @router.post("/pkgbase/{name}/unflag") -@auth_required(True) +@auth_required() async def pkgbase_unflag(request: Request, name: str): pkgbase = get_pkg_or_base(name, models.PackageBase) pkgbase_unflag_instance(request, pkgbase) @@ -860,7 +860,7 @@ def pkgbase_notify_instance(request: Request, pkgbase: models.PackageBase): @router.post("/pkgbase/{name}/notify") -@auth_required(True) +@auth_required() async def pkgbase_notify(request: Request, name: str): pkgbase = get_pkg_or_base(name, models.PackageBase) pkgbase_notify_instance(request, pkgbase) @@ -879,7 +879,7 @@ def pkgbase_unnotify_instance(request: Request, pkgbase: models.PackageBase): @router.post("/pkgbase/{name}/unnotify") -@auth_required(True) +@auth_required() async def pkgbase_unnotify(request: Request, name: str): pkgbase = get_pkg_or_base(name, models.PackageBase) pkgbase_unnotify_instance(request, pkgbase) @@ -888,7 +888,7 @@ async def pkgbase_unnotify(request: Request, name: str): @router.post("/pkgbase/{name}/vote") -@auth_required(True) +@auth_required() async def pkgbase_vote(request: Request, name: str): pkgbase = get_pkg_or_base(name, models.PackageBase) @@ -912,7 +912,7 @@ async def pkgbase_vote(request: Request, name: str): @router.post("/pkgbase/{name}/unvote") -@auth_required(True) +@auth_required() async def pkgbase_unvote(request: Request, name: str): pkgbase = get_pkg_or_base(name, models.PackageBase) @@ -954,7 +954,7 @@ def pkgbase_disown_instance(request: Request, pkgbase: models.PackageBase): @router.get("/pkgbase/{name}/disown") -@auth_required(True) +@auth_required() async def pkgbase_disown_get(request: Request, name: str): pkgbase = get_pkg_or_base(name, models.PackageBase) @@ -970,7 +970,7 @@ async def pkgbase_disown_get(request: Request, name: str): @router.post("/pkgbase/{name}/disown") -@auth_required(True) +@auth_required() async def pkgbase_disown_post(request: Request, name: str, confirm: bool = Form(default=False)): pkgbase = get_pkg_or_base(name, models.PackageBase) @@ -1003,7 +1003,7 @@ def pkgbase_adopt_instance(request: Request, pkgbase: models.PackageBase): @router.post("/pkgbase/{name}/adopt") -@auth_required(True) +@auth_required() async def pkgbase_adopt_post(request: Request, name: str): pkgbase = get_pkg_or_base(name, models.PackageBase) @@ -1019,7 +1019,7 @@ async def pkgbase_adopt_post(request: Request, name: str): @router.get("/pkgbase/{name}/delete") -@auth_required(True) +@auth_required() async def pkgbase_delete_get(request: Request, name: str): if not request.user.has_credential(creds.PKGBASE_DELETE): return RedirectResponse(f"/pkgbase/{name}", @@ -1031,7 +1031,7 @@ async def pkgbase_delete_get(request: Request, name: str): @router.post("/pkgbase/{name}/delete") -@auth_required(True) +@auth_required() async def pkgbase_delete_post(request: Request, name: str, confirm: bool = Form(default=False)): pkgbase = get_pkg_or_base(name, models.PackageBase) diff --git a/aurweb/routers/trusted_user.py b/aurweb/routers/trusted_user.py index 09de58fe..fac68f04 100644 --- a/aurweb/routers/trusted_user.py +++ b/aurweb/routers/trusted_user.py @@ -41,7 +41,7 @@ ADDVOTE_SPECIFICS = { @router.get("/tu") -@auth_required(True) +@auth_required() @account_type_required(REQUIRED_TYPES) async def trusted_user(request: Request, coff: int = 0, # current offset @@ -147,7 +147,7 @@ def render_proposal(request: Request, @router.get("/tu/{proposal}") -@auth_required(True) +@auth_required() @account_type_required(REQUIRED_TYPES) async def trusted_user_proposal(request: Request, proposal: int): context = await make_variable_context(request, "Trusted User") @@ -176,7 +176,7 @@ async def trusted_user_proposal(request: Request, proposal: int): @router.post("/tu/{proposal}") -@auth_required(True) +@auth_required() @account_type_required(REQUIRED_TYPES) async def trusted_user_proposal_post(request: Request, proposal: int, @@ -227,7 +227,7 @@ async def trusted_user_proposal_post(request: Request, @router.get("/addvote") -@auth_required(True) +@auth_required() @account_type_required({TRUSTED_USER, TRUSTED_USER_AND_DEV}) async def trusted_user_addvote(request: Request, user: str = str(), @@ -247,7 +247,7 @@ async def trusted_user_addvote(request: Request, @router.post("/addvote") -@auth_required(True) +@auth_required() @account_type_required({TRUSTED_USER, TRUSTED_USER_AND_DEV}) async def trusted_user_addvote_post(request: Request, user: str = Form(default=str()),