From a6ac5f0dbf5b2e8d0d0c55a58e7a41ee7d5ad5dc Mon Sep 17 00:00:00 2001
From: Kevin Morris
Date: Mon, 29 Nov 2021 19:44:18 -0800
Subject: [PATCH 1/6] fix(rpc): fix ordering of related records
They were being ordered by IDs; they should be ordered by Names.
Signed-off-by: Kevin Morris
---
aurweb/rpc.py | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/aurweb/rpc.py b/aurweb/rpc.py
index c70ddf1a..7bdae638 100644
--- a/aurweb/rpc.py
+++ b/aurweb/rpc.py
@@ -193,7 +193,7 @@ class RPC:
models.DependencyType.Name.label("Type"),
models.PackageDependency.DepName.label("Name"),
models.PackageDependency.DepCondition.label("Cond")
- ).distinct().order_by("ID"),
+ ).distinct().order_by("Name"),
# PackageRelation
db.query(
@@ -205,7 +205,7 @@ class RPC:
models.RelationType.Name.label("Type"),
models.PackageRelation.RelName.label("Name"),
models.PackageRelation.RelCondition.label("Cond")
- ).distinct().order_by("ID"),
+ ).distinct().order_by("Name"),
# Groups
db.query(models.PackageGroup).join(
@@ -217,7 +217,7 @@ class RPC:
literal("Groups").label("Type"),
models.Group.Name.label("Name"),
literal(str()).label("Cond")
- ).distinct().order_by("ID"),
+ ).distinct().order_by("Name"),
# Licenses
db.query(models.PackageLicense).join(
@@ -230,7 +230,7 @@ class RPC:
literal("License").label("Type"),
models.License.Name.label("Name"),
literal(str()).label("Cond")
- ).distinct().order_by("ID"),
+ ).distinct().order_by("Name"),
# Keywords
db.query(models.PackageKeyword).join(
@@ -242,7 +242,7 @@ class RPC:
literal("Keywords").label("Type"),
models.PackageKeyword.Keyword.label("Name"),
literal(str()).label("Cond")
- ).distinct().order_by("ID")
+ ).distinct().order_by("Name")
]
# Union all subqueries together.
From ecbab8546b68574c939b269dac1ac2d77e53766b Mon Sep 17 00:00:00 2001
From: Steven Guikal
Date: Thu, 21 Oct 2021 17:48:29 -0400
Subject: [PATCH 2/6] fix(FastAPI): access AccountType ID directly
Signed-off-by: Steven Guikal
---
aurweb/auth.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/aurweb/auth.py b/aurweb/auth.py
index 4d6dafc6..1527f0a3 100644
--- a/aurweb/auth.py
+++ b/aurweb/auth.py
@@ -244,7 +244,7 @@ def account_type_required(one_of: set):
def decorator(func):
@functools.wraps(func)
async def wrapper(request: fastapi.Request, *args, **kwargs):
- if request.user.AccountType.ID not in one_of:
+ if request.user.AccountTypeID not in one_of:
return RedirectResponse("/",
status_code=int(HTTPStatus.SEE_OTHER))
return await func(request, *args, **kwargs)
From 125b244f4478146ae293f76ca4a53a77160feda3 Mon Sep 17 00:00:00 2001
From: Steven Guikal
Date: Thu, 21 Oct 2021 17:49:10 -0400
Subject: [PATCH 3/6] fix(FastAPI): use account type vars instead of strings
Signed-off-by: Steven Guikal
---
aurweb/routers/trusted_user.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/aurweb/routers/trusted_user.py b/aurweb/routers/trusted_user.py
index 7c0a0404..f0cea61e 100644
--- a/aurweb/routers/trusted_user.py
+++ b/aurweb/routers/trusted_user.py
@@ -228,7 +228,7 @@ async def trusted_user_proposal_post(request: Request,
@router.get("/addvote")
@auth_required(True, redirect="/addvote")
-@account_type_required({"Trusted User", "Trusted User & Developer"})
+@account_type_required({TRUSTED_USER, TRUSTED_USER_AND_DEV})
async def trusted_user_addvote(request: Request,
user: str = str(),
type: str = "add_tu",
From a10f8663fd9bc4ddb990f1dfba31cb3331f4c9e9 Mon Sep 17 00:00:00 2001
From: Steven Guikal
Date: Tue, 30 Nov 2021 15:44:18 -0500
Subject: [PATCH 4/6] fix(FastAPI): reorganize credential checkin into
dedicated file
Signed-off-by: Steven Guikal
---
aurweb/{auth.py => auth/__init__.py} | 98 ------------------------
aurweb/auth/creds.py | 76 ++++++++++++++++++
aurweb/models/user.py | 9 ++-
aurweb/routers/accounts.py | 6 +-
aurweb/routers/packages.py | 56 +++++++-------
aurweb/templates.py | 3 +-
templates/partials/account/comment.html | 2 +-
templates/partials/account_form.html | 2 +-
templates/partials/archdev-navbar.html | 4 +-
templates/partials/comment_actions.html | 8 +-
templates/partials/packages/actions.html | 8 +-
templates/partials/packages/comment.html | 2 +-
templates/partials/packages/details.html | 4 +-
test/test_auth.py | 12 +--
test/test_user.py | 25 +++---
15 files changed, 143 insertions(+), 172 deletions(-)
rename aurweb/{auth.py => auth/__init__.py} (75%)
create mode 100644 aurweb/auth/creds.py
diff --git a/aurweb/auth.py b/aurweb/auth/__init__.py
similarity index 75%
rename from aurweb/auth.py
rename to aurweb/auth/__init__.py
index 1527f0a3..82192cc2 100644
--- a/aurweb/auth.py
+++ b/aurweb/auth/__init__.py
@@ -250,101 +250,3 @@ def account_type_required(one_of: set):
return await func(request, *args, **kwargs)
return wrapper
return decorator
-
-
-CRED_ACCOUNT_CHANGE_TYPE = 1
-CRED_ACCOUNT_EDIT = 2
-CRED_ACCOUNT_EDIT_DEV = 3
-CRED_ACCOUNT_LAST_LOGIN = 4
-CRED_ACCOUNT_SEARCH = 5
-CRED_ACCOUNT_LIST_COMMENTS = 28
-CRED_COMMENT_DELETE = 6
-CRED_COMMENT_UNDELETE = 27
-CRED_COMMENT_VIEW_DELETED = 22
-CRED_COMMENT_EDIT = 25
-CRED_COMMENT_PIN = 26
-CRED_PKGBASE_ADOPT = 7
-CRED_PKGBASE_SET_KEYWORDS = 8
-CRED_PKGBASE_DELETE = 9
-CRED_PKGBASE_DISOWN = 10
-CRED_PKGBASE_EDIT_COMAINTAINERS = 24
-CRED_PKGBASE_FLAG = 11
-CRED_PKGBASE_LIST_VOTERS = 12
-CRED_PKGBASE_NOTIFY = 13
-CRED_PKGBASE_UNFLAG = 15
-CRED_PKGBASE_VOTE = 16
-CRED_PKGREQ_FILE = 23
-CRED_PKGREQ_CLOSE = 17
-CRED_PKGREQ_LIST = 18
-CRED_TU_ADD_VOTE = 19
-CRED_TU_LIST_VOTES = 20
-CRED_TU_VOTE = 21
-CRED_PKGBASE_MERGE = 29
-
-
-def has_any(user, *account_types):
- return str(user.AccountType) in set(account_types)
-
-
-def user_developer_or_trusted_user(user):
- return True
-
-
-def trusted_user(user):
- return has_any(user, "Trusted User", "Trusted User & Developer")
-
-
-def developer(user):
- return has_any(user, "Developer", "Trusted User & Developer")
-
-
-def trusted_user_or_dev(user):
- return has_any(user, "Trusted User", "Developer",
- "Trusted User & Developer")
-
-
-# A mapping of functions that users must pass to have credentials.
-cred_filters = {
- CRED_PKGBASE_FLAG: user_developer_or_trusted_user,
- CRED_PKGBASE_NOTIFY: user_developer_or_trusted_user,
- CRED_PKGBASE_VOTE: user_developer_or_trusted_user,
- CRED_PKGREQ_FILE: user_developer_or_trusted_user,
- CRED_ACCOUNT_CHANGE_TYPE: trusted_user_or_dev,
- CRED_ACCOUNT_EDIT: trusted_user_or_dev,
- CRED_ACCOUNT_LAST_LOGIN: trusted_user_or_dev,
- CRED_ACCOUNT_LIST_COMMENTS: trusted_user_or_dev,
- CRED_ACCOUNT_SEARCH: trusted_user_or_dev,
- CRED_COMMENT_DELETE: trusted_user_or_dev,
- CRED_COMMENT_UNDELETE: trusted_user_or_dev,
- CRED_COMMENT_VIEW_DELETED: trusted_user_or_dev,
- CRED_COMMENT_EDIT: trusted_user_or_dev,
- CRED_COMMENT_PIN: trusted_user_or_dev,
- CRED_PKGBASE_ADOPT: trusted_user_or_dev,
- CRED_PKGBASE_SET_KEYWORDS: trusted_user_or_dev,
- CRED_PKGBASE_DELETE: trusted_user_or_dev,
- CRED_PKGBASE_EDIT_COMAINTAINERS: trusted_user_or_dev,
- CRED_PKGBASE_DISOWN: trusted_user_or_dev,
- CRED_PKGBASE_LIST_VOTERS: trusted_user_or_dev,
- CRED_PKGBASE_UNFLAG: trusted_user_or_dev,
- CRED_PKGREQ_CLOSE: trusted_user_or_dev,
- CRED_PKGREQ_LIST: trusted_user_or_dev,
- CRED_TU_ADD_VOTE: trusted_user,
- CRED_TU_LIST_VOTES: trusted_user_or_dev,
- CRED_TU_VOTE: trusted_user,
- CRED_ACCOUNT_EDIT_DEV: developer,
- CRED_PKGBASE_MERGE: trusted_user_or_dev,
-}
-
-
-def has_credential(user: User,
- credential: int,
- approved_users: list = tuple()):
-
- if user in approved_users:
- return True
-
- if credential in cred_filters:
- cred_filter = cred_filters.get(credential)
- return cred_filter(user)
-
- return False
diff --git a/aurweb/auth/creds.py b/aurweb/auth/creds.py
new file mode 100644
index 00000000..100aad8c
--- /dev/null
+++ b/aurweb/auth/creds.py
@@ -0,0 +1,76 @@
+from aurweb.models.account_type import DEVELOPER_ID, TRUSTED_USER_AND_DEV_ID, TRUSTED_USER_ID, USER_ID
+from aurweb.models.user import User
+
+ACCOUNT_CHANGE_TYPE = 1
+ACCOUNT_EDIT = 2
+ACCOUNT_EDIT_DEV = 3
+ACCOUNT_LAST_LOGIN = 4
+ACCOUNT_SEARCH = 5
+ACCOUNT_LIST_COMMENTS = 28
+COMMENT_DELETE = 6
+COMMENT_UNDELETE = 27
+COMMENT_VIEW_DELETED = 22
+COMMENT_EDIT = 25
+COMMENT_PIN = 26
+PKGBASE_ADOPT = 7
+PKGBASE_SET_KEYWORDS = 8
+PKGBASE_DELETE = 9
+PKGBASE_DISOWN = 10
+PKGBASE_EDIT_COMAINTAINERS = 24
+PKGBASE_FLAG = 11
+PKGBASE_LIST_VOTERS = 12
+PKGBASE_NOTIFY = 13
+PKGBASE_UNFLAG = 15
+PKGBASE_VOTE = 16
+PKGREQ_FILE = 23
+PKGREQ_CLOSE = 17
+PKGREQ_LIST = 18
+TU_ADD_VOTE = 19
+TU_LIST_VOTES = 20
+TU_VOTE = 21
+PKGBASE_MERGE = 29
+
+user_developer_or_trusted_user = set([USER_ID, TRUSTED_USER_ID, DEVELOPER_ID, TRUSTED_USER_AND_DEV_ID])
+trusted_user_or_dev = set([TRUSTED_USER_ID, DEVELOPER_ID, TRUSTED_USER_AND_DEV_ID])
+developer = set([DEVELOPER_ID, TRUSTED_USER_AND_DEV_ID])
+trusted_user = set([TRUSTED_USER_ID, TRUSTED_USER_AND_DEV_ID])
+
+cred_filters = {
+ PKGBASE_FLAG: user_developer_or_trusted_user,
+ PKGBASE_NOTIFY: user_developer_or_trusted_user,
+ PKGBASE_VOTE: user_developer_or_trusted_user,
+ PKGREQ_FILE: user_developer_or_trusted_user,
+ ACCOUNT_CHANGE_TYPE: trusted_user_or_dev,
+ ACCOUNT_EDIT: trusted_user_or_dev,
+ ACCOUNT_LAST_LOGIN: trusted_user_or_dev,
+ ACCOUNT_LIST_COMMENTS: trusted_user_or_dev,
+ ACCOUNT_SEARCH: trusted_user_or_dev,
+ COMMENT_DELETE: trusted_user_or_dev,
+ COMMENT_UNDELETE: trusted_user_or_dev,
+ COMMENT_VIEW_DELETED: trusted_user_or_dev,
+ COMMENT_EDIT: trusted_user_or_dev,
+ COMMENT_PIN: trusted_user_or_dev,
+ PKGBASE_ADOPT: trusted_user_or_dev,
+ PKGBASE_SET_KEYWORDS: trusted_user_or_dev,
+ PKGBASE_DELETE: trusted_user_or_dev,
+ PKGBASE_EDIT_COMAINTAINERS: trusted_user_or_dev,
+ PKGBASE_DISOWN: trusted_user_or_dev,
+ PKGBASE_LIST_VOTERS: trusted_user_or_dev,
+ PKGBASE_UNFLAG: trusted_user_or_dev,
+ PKGREQ_CLOSE: trusted_user_or_dev,
+ PKGREQ_LIST: trusted_user_or_dev,
+ TU_ADD_VOTE: trusted_user,
+ TU_LIST_VOTES: trusted_user_or_dev,
+ TU_VOTE: trusted_user,
+ ACCOUNT_EDIT_DEV: developer,
+ PKGBASE_MERGE: trusted_user_or_dev,
+}
+
+
+def has_credential(user: User,
+ credential: int,
+ approved_users: list = tuple()):
+
+ if user in approved_users:
+ return True
+ return user.AccountTypeID in cred_filters[credential]
diff --git a/aurweb/models/user.py b/aurweb/models/user.py
index 03634a36..f0724202 100644
--- a/aurweb/models/user.py
+++ b/aurweb/models/user.py
@@ -1,6 +1,7 @@
import hashlib
from datetime import datetime
+from typing import List, Set
import bcrypt
@@ -136,10 +137,10 @@ class User(Base):
request.cookies["AURSID"] = self.session.SessionID
return self.session.SessionID
- def has_credential(self, credential: str, approved: list = tuple()):
- import aurweb.auth
- cred = getattr(aurweb.auth, credential)
- return aurweb.auth.has_credential(self, cred, approved)
+ def has_credential(self, credential: Set[int],
+ approved: List["User"] = list()):
+ from aurweb.auth.creds import has_credential
+ return has_credential(self, credential, approved)
def logout(self, request):
del request.cookies["AURSID"]
diff --git a/aurweb/routers/accounts.py b/aurweb/routers/accounts.py
index 545811f0..360857e8 100644
--- a/aurweb/routers/accounts.py
+++ b/aurweb/routers/accounts.py
@@ -10,7 +10,7 @@ from sqlalchemy import and_, or_
import aurweb.config
from aurweb import cookies, db, l10n, logging, models, util
-from aurweb.auth import account_type_required, auth_required
+from aurweb.auth import account_type_required, auth_required, creds
from aurweb.captcha import get_captcha_salts
from aurweb.exceptions import ValidationError
from aurweb.l10n import get_translator_for_request
@@ -176,7 +176,7 @@ def make_account_form_context(context: dict,
user_account_type_id = context.get("account_types")[0][0]
- if request.user.has_credential("CRED_ACCOUNT_EDIT_DEV"):
+ if request.user.has_credential(creds.ACCOUNT_EDIT_DEV):
context["account_types"].append((at.DEVELOPER_ID, at.DEVELOPER))
context["account_types"].append((at.TRUSTED_USER_AND_DEV_ID,
at.TRUSTED_USER_AND_DEV))
@@ -332,7 +332,7 @@ async def account_register_post(request: Request,
def cannot_edit(request, user):
""" Return a 401 HTMLResponse if the request user doesn't
have authorization, otherwise None. """
- has_dev_cred = request.user.has_credential("CRED_ACCOUNT_EDIT_DEV",
+ has_dev_cred = request.user.has_credential(creds.ACCOUNT_EDIT_DEV,
approved=[user])
if not has_dev_cred:
return HTMLResponse(status_code=HTTPStatus.UNAUTHORIZED)
diff --git a/aurweb/routers/packages.py b/aurweb/routers/packages.py
index b5f8478e..2bf04949 100644
--- a/aurweb/routers/packages.py
+++ b/aurweb/routers/packages.py
@@ -10,7 +10,7 @@ import aurweb.filters
import aurweb.packages.util
from aurweb import db, defaults, l10n, logging, models, util
-from aurweb.auth import auth_required
+from aurweb.auth import auth_required, creds
from aurweb.exceptions import ValidationError
from aurweb.models.package_request import ACCEPTED_ID, PENDING_ID, REJECTED_ID
from aurweb.models.relation_type import CONFLICTS_ID, PROVIDES_ID, REPLACES_ID
@@ -413,7 +413,7 @@ async def pkgbase_comment_delete(request: Request, name: str, id: int,
pkgbase = get_pkg_or_base(name, models.PackageBase)
comment = get_pkgbase_comment(pkgbase, id)
- authorized = request.user.has_credential("CRED_COMMENT_DELETE",
+ authorized = request.user.has_credential(creds.COMMENT_DELETE,
[comment.User])
if not authorized:
_ = l10n.get_translator_for_request(request)
@@ -439,7 +439,7 @@ async def pkgbase_comment_undelete(request: Request, name: str, id: int,
pkgbase = get_pkg_or_base(name, models.PackageBase)
comment = get_pkgbase_comment(pkgbase, id)
- has_cred = request.user.has_credential("CRED_COMMENT_UNDELETE",
+ has_cred = request.user.has_credential(creds.COMMENT_UNDELETE,
approved=[comment.User])
if not has_cred:
_ = l10n.get_translator_for_request(request)
@@ -464,7 +464,7 @@ async def pkgbase_comment_pin(request: Request, name: str, id: int,
pkgbase = get_pkg_or_base(name, models.PackageBase)
comment = get_pkgbase_comment(pkgbase, id)
- has_cred = request.user.has_credential("CRED_COMMENT_PIN",
+ has_cred = request.user.has_credential(creds.COMMENT_PIN,
approved=[pkgbase.Maintainer])
if not has_cred:
_ = l10n.get_translator_for_request(request)
@@ -489,7 +489,7 @@ async def pkgbase_comment_unpin(request: Request, name: str, id: int,
pkgbase = get_pkg_or_base(name, models.PackageBase)
comment = get_pkgbase_comment(pkgbase, id)
- has_cred = request.user.has_credential("CRED_COMMENT_PIN",
+ has_cred = request.user.has_credential(creds.COMMENT_PIN,
approved=[pkgbase.Maintainer])
if not has_cred:
_ = l10n.get_translator_for_request(request)
@@ -514,7 +514,7 @@ async def package_base_comaintainers(request: Request, name: str) -> Response:
# Unauthorized users (Non-TU/Dev and not the pkgbase maintainer)
# get redirected to the package base's page.
- has_creds = request.user.has_credential("CRED_PKGBASE_EDIT_COMAINTAINERS",
+ has_creds = request.user.has_credential(creds.PKGBASE_EDIT_COMAINTAINERS,
approved=[pkgbase.Maintainer])
if not has_creds:
return RedirectResponse(f"/pkgbase/{name}",
@@ -541,7 +541,7 @@ async def package_base_comaintainers_post(
# Unauthorized users (Non-TU/Dev and not the pkgbase maintainer)
# get redirected to the package base's page.
- has_creds = request.user.has_credential("CRED_PKGBASE_EDIT_COMAINTAINERS",
+ has_creds = request.user.has_credential(creds.PKGBASE_EDIT_COMAINTAINERS,
approved=[pkgbase.Maintainer])
if not has_creds:
return RedirectResponse(f"/pkgbase/{name}",
@@ -779,7 +779,7 @@ async def pkgbase_keywords(request: Request, name: str,
async def pkgbase_flag_get(request: Request, name: str):
pkgbase = get_pkg_or_base(name, models.PackageBase)
- has_cred = request.user.has_credential("CRED_PKGBASE_FLAG")
+ has_cred = request.user.has_credential(creds.PKGBASE_FLAG)
if not has_cred or pkgbase.Flagger is not None:
return RedirectResponse(f"/pkgbase/{name}",
status_code=HTTPStatus.SEE_OTHER)
@@ -803,7 +803,7 @@ async def pkgbase_flag_post(request: Request, name: str,
return render_template(request, "packages/flag.html", context,
status_code=HTTPStatus.BAD_REQUEST)
- has_cred = request.user.has_credential("CRED_PKGBASE_FLAG")
+ has_cred = request.user.has_credential(creds.PKGBASE_FLAG)
if has_cred and not pkgbase.Flagger:
now = int(datetime.utcnow().timestamp())
with db.begin():
@@ -830,7 +830,7 @@ async def pkgbase_flag_comment(request: Request, name: str):
def pkgbase_unflag_instance(request: Request, pkgbase: models.PackageBase):
has_cred = request.user.has_credential(
- "CRED_PKGBASE_UNFLAG", approved=[pkgbase.Flagger, pkgbase.Maintainer])
+ creds.PKGBASE_UNFLAG, approved=[pkgbase.Flagger, pkgbase.Maintainer])
if has_cred:
with db.begin():
pkgbase.OutOfDateTS = None
@@ -851,7 +851,7 @@ def pkgbase_notify_instance(request: Request, pkgbase: models.PackageBase):
notif = db.query(pkgbase.notifications.filter(
models.PackageNotification.UserID == request.user.ID
).exists()).scalar()
- has_cred = request.user.has_credential("CRED_PKGBASE_NOTIFY")
+ has_cred = request.user.has_credential(creds.PKGBASE_NOTIFY)
if has_cred and not notif:
with db.begin():
db.create(models.PackageNotification,
@@ -872,7 +872,7 @@ def pkgbase_unnotify_instance(request: Request, pkgbase: models.PackageBase):
notif = pkgbase.notifications.filter(
models.PackageNotification.UserID == request.user.ID
).first()
- has_cred = request.user.has_credential("CRED_PKGBASE_NOTIFY")
+ has_cred = request.user.has_credential(creds.PKGBASE_NOTIFY)
if has_cred and notif:
with db.begin():
db.delete(notif)
@@ -895,7 +895,7 @@ async def pkgbase_vote(request: Request, name: str):
vote = pkgbase.package_votes.filter(
models.PackageVote.UsersID == request.user.ID
).first()
- has_cred = request.user.has_credential("CRED_PKGBASE_VOTE")
+ has_cred = request.user.has_credential(creds.PKGBASE_VOTE)
if has_cred and not vote:
now = int(datetime.utcnow().timestamp())
with db.begin():
@@ -919,7 +919,7 @@ async def pkgbase_unvote(request: Request, name: str):
vote = pkgbase.package_votes.filter(
models.PackageVote.UsersID == request.user.ID
).first()
- has_cred = request.user.has_credential("CRED_PKGBASE_VOTE")
+ has_cred = request.user.has_credential(creds.PKGBASE_VOTE)
if has_cred and vote:
with db.begin():
db.delete(vote)
@@ -958,7 +958,7 @@ def pkgbase_disown_instance(request: Request, pkgbase: models.PackageBase):
async def pkgbase_disown_get(request: Request, name: str):
pkgbase = get_pkg_or_base(name, models.PackageBase)
- has_cred = request.user.has_credential("CRED_PKGBASE_DISOWN",
+ has_cred = request.user.has_credential(creds.PKGBASE_DISOWN,
approved=[pkgbase.Maintainer])
if not has_cred:
return RedirectResponse(f"/pkgbase/{name}",
@@ -975,7 +975,7 @@ async def pkgbase_disown_post(request: Request, name: str,
confirm: bool = Form(default=False)):
pkgbase = get_pkg_or_base(name, models.PackageBase)
- has_cred = request.user.has_credential("CRED_PKGBASE_DISOWN",
+ has_cred = request.user.has_credential(creds.PKGBASE_DISOWN,
approved=[pkgbase.Maintainer])
if not has_cred:
return RedirectResponse(f"/pkgbase/{name}",
@@ -1007,7 +1007,7 @@ def pkgbase_adopt_instance(request: Request, pkgbase: models.PackageBase):
async def pkgbase_adopt_post(request: Request, name: str):
pkgbase = get_pkg_or_base(name, models.PackageBase)
- has_cred = request.user.has_credential("CRED_PKGBASE_ADOPT")
+ has_cred = request.user.has_credential(creds.PKGBASE_ADOPT)
if has_cred or not pkgbase.Maintainer:
# If the user has credentials, they'll adopt the package regardless
# of maintainership. Otherwise, we'll promote the user to maintainer
@@ -1021,7 +1021,7 @@ async def pkgbase_adopt_post(request: Request, name: str):
@router.get("/pkgbase/{name}/delete")
@auth_required(True, redirect="/pkgbase/{name}/delete")
async def pkgbase_delete_get(request: Request, name: str):
- if not request.user.has_credential("CRED_PKGBASE_DELETE"):
+ if not request.user.has_credential(creds.PKGBASE_DELETE):
return RedirectResponse(f"/pkgbase/{name}",
status_code=HTTPStatus.SEE_OTHER)
@@ -1036,7 +1036,7 @@ async def pkgbase_delete_post(request: Request, name: str,
confirm: bool = Form(default=False)):
pkgbase = get_pkg_or_base(name, models.PackageBase)
- if not request.user.has_credential("CRED_PKGBASE_DELETE"):
+ if not request.user.has_credential(creds.PKGBASE_DELETE):
return RedirectResponse(f"/pkgbase/{name}",
status_code=HTTPStatus.SEE_OTHER)
@@ -1070,7 +1070,7 @@ async def packages_unflag(request: Request, package_ids: List[int] = [],
models.Package.ID.in_(package_ids)).all()
for pkg in packages:
has_cred = request.user.has_credential(
- "CRED_PKGBASE_UNFLAG", approved=[pkg.PackageBase.Flagger])
+ creds.PKGBASE_UNFLAG, approved=[pkg.PackageBase.Flagger])
if not has_cred:
return (False, ["You did not select any packages to unflag."])
@@ -1106,7 +1106,7 @@ async def packages_notify(request: Request, package_ids: List[int] = [],
notif = db.query(pkgbase.notifications.filter(
models.PackageNotification.UserID == request.user.ID
).exists()).scalar()
- has_cred = request.user.has_credential("CRED_PKGBASE_NOTIFY")
+ has_cred = request.user.has_credential(creds.PKGBASE_NOTIFY)
# If the request user either does not have credentials
# or the notification already exists:
@@ -1178,7 +1178,7 @@ async def packages_adopt(request: Request, package_ids: List[int] = [],
# Check that the user has credentials for every package they selected.
for pkgbase in bases:
- has_cred = request.user.has_credential("CRED_PKGBASE_ADOPT")
+ has_cred = request.user.has_credential(creds.PKGBASE_ADOPT)
if not (has_cred or not pkgbase.Maintainer):
# TODO: This error needs to be translated.
return (False, ["You are not allowed to adopt one of the "
@@ -1211,7 +1211,7 @@ async def packages_disown(request: Request, package_ids: List[int] = [],
# Check that the user has credentials for every package they selected.
for pkgbase in bases:
- has_cred = request.user.has_credential("CRED_PKGBASE_DISOWN",
+ has_cred = request.user.has_credential(creds.PKGBASE_DISOWN,
approved=[pkgbase.Maintainer])
if not has_cred:
# TODO: This error needs to be translated.
@@ -1235,7 +1235,7 @@ async def packages_delete(request: Request, package_ids: List[int] = [],
return (False, ["The selected packages have not been deleted, "
"check the confirmation checkbox."])
- if not request.user.has_credential("CRED_PKGBASE_DELETE"):
+ if not request.user.has_credential(creds.PKGBASE_DELETE):
return (False, ["You do not have permission to delete packages."])
# A "memo" used to store names of packages that we delete.
@@ -1329,10 +1329,10 @@ async def pkgbase_merge_get(request: Request, name: str,
status_code = HTTPStatus.OK
# TODO: Lookup errors from credential instead of hardcoding them.
- # Idea: Something like credential_errors("CRED_PKGBASE_MERGE").
- # Perhaps additionally: bad_credential_status_code("CRED_PKGBASE_MERGE").
+ # Idea: Something like credential_errors(creds.PKGBASE_MERGE).
+ # Perhaps additionally: bad_credential_status_code(creds.PKGBASE_MERGE).
# Don't take these examples verbatim. We should find good naming.
- if not request.user.has_credential("CRED_PKGBASE_MERGE"):
+ if not request.user.has_credential(creds.PKGBASE_MERGE):
context["errors"] = [
"Only Trusted Users and Developers can merge packages."]
status_code = HTTPStatus.UNAUTHORIZED
@@ -1434,7 +1434,7 @@ async def pkgbase_merge_post(request: Request, name: str,
context["pkgbase"] = pkgbase
# TODO: Lookup errors from credential instead of hardcoding them.
- if not request.user.has_credential("CRED_PKGBASE_MERGE"):
+ if not request.user.has_credential(creds.PKGBASE_MERGE):
context["errors"] = [
"Only Trusted Users and Developers can merge packages."]
return render_template(request, "pkgbase/merge.html", context,
diff --git a/aurweb/templates.py b/aurweb/templates.py
index a7102ae1..635b22b4 100644
--- a/aurweb/templates.py
+++ b/aurweb/templates.py
@@ -16,7 +16,7 @@ from fastapi.responses import HTMLResponse
import aurweb.config
-from aurweb import captcha, cookies, l10n, time, util
+from aurweb import auth, captcha, cookies, l10n, time, util
# Prepare jinja2 objects.
_loader = jinja2.FileSystemLoader(os.path.join(
@@ -107,6 +107,7 @@ def make_context(request: Request, title: str, next: str = None):
"now": datetime.now(tz=zoneinfo.ZoneInfo(timezone)),
"utcnow": int(datetime.utcnow().timestamp()),
"config": aurweb.config,
+ "creds": auth.creds,
"next": next if next else request.url.path
}
diff --git a/templates/partials/account/comment.html b/templates/partials/account/comment.html
index bc167cf7..8c310738 100644
--- a/templates/partials/account/comment.html
+++ b/templates/partials/account/comment.html
@@ -3,7 +3,7 @@
{% set header_cls = "%s %s" | format(header_cls, "comment-deleted") %}
{% endif %}
-{% if not comment.Deleter or request.user.has_credential("CRED_COMMENT_VIEW_DELETED", approved=[comment.Deleter]) %}
+{% if not comment.Deleter or request.user.has_credential(creds.COMMENT_VIEW_DELETED, approved=[comment.Deleter]) %}
{% set commented_at = comment.CommentTS | dt | as_timezone(timezone) %}
{% endif %}
- {% if request.user.has_credential("CRED_ACCOUNT_CHANGE_TYPE") %}
+ {% if request.user.has_credential(creds.ACCOUNT_CHANGE_TYPE) %}