feat: allow filtering requests from maintainers

These are usually easy to handle from TUs so allow to filter for them

Signed-off-by: Leonidas Spyropoulos <artafinde@archlinux.org>
This commit is contained in:
Leonidas Spyropoulos 2022-11-10 21:28:16 +00:00
parent 500d6b403b
commit bce5b81acd
No known key found for this signature in database
GPG key ID: 59E43E106B247368
4 changed files with 69 additions and 19 deletions

View file

@ -2,12 +2,12 @@ from http import HTTPStatus
from fastapi import APIRouter, Form, Query, Request from fastapi import APIRouter, Form, Query, Request
from fastapi.responses import RedirectResponse from fastapi.responses import RedirectResponse
from sqlalchemy import case from sqlalchemy import case, orm
from aurweb import db, defaults, time, util from aurweb import db, defaults, time, util
from aurweb.auth import creds, requires_auth from aurweb.auth import creds, requires_auth
from aurweb.exceptions import handle_form_exceptions from aurweb.exceptions import handle_form_exceptions
from aurweb.models import PackageRequest from aurweb.models import PackageBase, PackageRequest, User
from aurweb.models.package_request import ( from aurweb.models.package_request import (
ACCEPTED_ID, ACCEPTED_ID,
CLOSED_ID, CLOSED_ID,
@ -23,6 +23,7 @@ FILTER_PARAMS = {
"filter_closed", "filter_closed",
"filter_accepted", "filter_accepted",
"filter_rejected", "filter_rejected",
"filter_maintainers_requests",
} }
router = APIRouter() router = APIRouter()
@ -38,6 +39,7 @@ async def requests(
filter_closed: bool = False, filter_closed: bool = False,
filter_accepted: bool = False, filter_accepted: bool = False,
filter_rejected: bool = False, filter_rejected: bool = False,
filter_maintainer_requests: bool = False,
): ):
context = make_context(request, "Requests") context = make_context(request, "Requests")
@ -53,9 +55,17 @@ async def requests(
context["filter_closed"] = filter_closed context["filter_closed"] = filter_closed
context["filter_accepted"] = filter_accepted context["filter_accepted"] = filter_accepted
context["filter_rejected"] = filter_rejected context["filter_rejected"] = filter_rejected
context["filter_maintainer_requests"] = filter_maintainer_requests
Maintainer = orm.aliased(User)
# A PackageRequest query # A PackageRequest query
query = db.query(PackageRequest) query = (
db.query(PackageRequest)
.join(PackageBase)
.join(User, PackageRequest.UsersID == User.ID, isouter=True)
.join(Maintainer, PackageBase.MaintainerUID == Maintainer.ID, isouter=True)
)
# query = db.query(PackageRequest).join(User)
# Requests statistics # Requests statistics
context["total_requests"] = query.count() context["total_requests"] = query.count()
@ -79,6 +89,9 @@ async def requests(
if filter_rejected: if filter_rejected:
in_filters.append(REJECTED_ID) in_filters.append(REJECTED_ID)
filtered = query.filter(PackageRequest.Status.in_(in_filters)) filtered = query.filter(PackageRequest.Status.in_(in_filters))
# Additionally filter for requests made from package maintainer
if filter_maintainer_requests:
filtered = filtered.filter(PackageRequest.UsersID == PackageBase.MaintainerUID)
# If the request user is not elevated (TU or Dev), then # If the request user is not elevated (TU or Dev), then
# filter PackageRequests which are owned by the request user. # filter PackageRequests which are owned by the request user.
if not request.user.is_elevated(): if not request.user.is_elevated():

View file

@ -1,13 +1,8 @@
[pytest] [pytest]
# Ignore the following DeprecationWarning(s):
# - asyncio.base_events
# - DeprecationWarning speaking about internal asyncio
# using the loop= argument being deprecated starting
# with python 3.8, before python 3.10.
# - Note: This is a bug in upstream filed at
# https://bugs.python.org/issue45097
filterwarnings = filterwarnings =
ignore::DeprecationWarning:asyncio.base_events # This is coming from https://github.com/pytest-dev/pytest-xdist/issues/825 and it's caused from pytest-cov
# Remove once fixed: https://github.com/pytest-dev/pytest-cov/issues/557
ignore:The --rsyncdir command line argument and rsyncdirs config variable are deprecated.:DeprecationWarning
# Build in coverage and pytest-xdist multiproc testing. # Build in coverage and pytest-xdist multiproc testing.
addopts = --cov=aurweb --cov-append --dist load --dist loadfile -n auto addopts = --cov=aurweb --cov-append --dist load --dist loadfile -n auto

View file

@ -56,6 +56,11 @@
<input type="checkbox" name="filter_rejected" id="id_filter_rejected" value="True" {{ "checked" if <input type="checkbox" name="filter_rejected" id="id_filter_rejected" value="True" {{ "checked" if
filter_rejected == true }}/> filter_rejected == true }}/>
</div> </div>
<div>
<label for="id_filter_maintainer_requests" title="Maintainer's requests">{{ "Maintainer's requests" | tr }}</label>
<input type="checkbox" name="filter_maintainer_requests" id="id_filter_maintainer_requests"
value="True" {{ "checked" if filter_maintainer_requests == true }}/>
</div>
<div> <div>
<button type='submit' class='button' name='submit' value='Filter'>{{ "Filter" | tr }}</button> <button type='submit' class='button' name='submit' value='Filter'>{{ "Filter" | tr }}</button>
</div> </div>

View file

@ -96,7 +96,21 @@ def maintainer() -> User:
@pytest.fixture @pytest.fixture
def packages(maintainer: User) -> list[Package]: def maintainer2() -> User:
"""Yield a specific User used to maintain packages."""
with db.begin():
maintainer = db.create(
User,
Username="test_maintainer2",
Email="test_maintainer2@example.org",
Passwd="testPassword",
AccountTypeID=USER_ID,
)
yield maintainer
@pytest.fixture
def packages(maintainer: User, maintainer2: User) -> list[Package]:
"""Yield 55 packages named pkg_0 .. pkg_54.""" """Yield 55 packages named pkg_0 .. pkg_54."""
packages_ = [] packages_ = []
now = time.utcnow() now = time.utcnow()
@ -105,7 +119,7 @@ def packages(maintainer: User) -> list[Package]:
pkgbase = db.create( pkgbase = db.create(
PackageBase, PackageBase,
Name=f"pkg_{i}", Name=f"pkg_{i}",
Maintainer=maintainer, Maintainer=maintainer2 if i > 52 else maintainer,
Packager=maintainer, Packager=maintainer,
Submitter=maintainer, Submitter=maintainer,
ModifiedTS=now, ModifiedTS=now,
@ -117,14 +131,18 @@ def packages(maintainer: User) -> list[Package]:
@pytest.fixture @pytest.fixture
def requests(user: User, packages: list[Package]) -> list[PackageRequest]: def requests(
user: User, maintainer2: User, packages: list[Package]
) -> list[PackageRequest]:
pkgreqs = [] pkgreqs = []
with db.begin(): with db.begin():
for i in range(55): for i in range(55):
pkgreq = db.create( pkgreq = db.create(
PackageRequest, PackageRequest,
ReqTypeID=DELETION_ID, ReqTypeID=DELETION_ID,
User=user, User=maintainer2
if packages[i].PackageBase.Maintainer.Username == "test_maintainer2"
else user,
PackageBase=packages[i].PackageBase, PackageBase=packages[i].PackageBase,
PackageBaseName=packages[i].Name, PackageBaseName=packages[i].Name,
Comments=f"Deletion request for pkg_{i}", Comments=f"Deletion request for pkg_{i}",
@ -717,10 +735,6 @@ def test_requests(
"O": 0, # Page 1 "O": 0, # Page 1
"SeB": "nd", "SeB": "nd",
"SB": "n", "SB": "n",
"filter_pending": True,
"filter_closed": True,
"filter_accepted": True,
"filter_rejected": True,
}, },
cookies=cookies, cookies=cookies,
) )
@ -767,6 +781,7 @@ def test_requests_with_filters(
"filter_closed": True, "filter_closed": True,
"filter_accepted": True, "filter_accepted": True,
"filter_rejected": True, "filter_rejected": True,
"filter_maintainer_requests": False,
}, },
cookies=cookies, cookies=cookies,
) )
@ -790,6 +805,7 @@ def test_requests_with_filters(
"filter_closed": True, "filter_closed": True,
"filter_accepted": True, "filter_accepted": True,
"filter_rejected": True, "filter_rejected": True,
"filter_maintainer_requests": False,
}, },
cookies=cookies, cookies=cookies,
) # Page 2 ) # Page 2
@ -803,6 +819,27 @@ def test_requests_with_filters(
assert len(rows) == 5 # There are five records left on the second page. assert len(rows) == 5 # There are five records left on the second page.
def test_requests_for_maintainer_requests(
client: TestClient,
tu_user: User,
packages: list[Package],
requests: list[PackageRequest],
):
cookies = {"AURSID": tu_user.login(Request(), "testPassword")}
with client as request:
resp = request.get(
"/requests",
params={"filter_maintainer_requests": True},
cookies=cookies,
)
assert resp.status_code == int(HTTPStatus.OK)
root = parse_root(resp.text)
rows = root.xpath('//table[@class="results"]/tbody/tr')
# We only expect 2 requests since we are looking for requests from the maintainers
assert len(rows) == 2
def test_requests_by_deleted_users( def test_requests_by_deleted_users(
client: TestClient, user: User, tu_user: User, pkgreq: PackageRequest client: TestClient, user: User, tu_user: User, pkgreq: PackageRequest
): ):