From fb85cb60a0ffc75b2b16083ebf46111a8082e46e Mon Sep 17 00:00:00 2001 From: Kevin Morris Date: Sat, 9 Oct 2021 15:02:49 -0700 Subject: [PATCH] feat(FastAPI): add /packages (post) action: 'unflag' Signed-off-by: Kevin Morris --- aurweb/routers/packages.py | 42 +++++++++++++++++++++++++++----- test/test_packages_routes.py | 46 ++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 6 deletions(-) diff --git a/aurweb/routers/packages.py b/aurweb/routers/packages.py index 20d34c86..d65cc344 100644 --- a/aurweb/routers/packages.py +++ b/aurweb/routers/packages.py @@ -827,11 +827,7 @@ async def pkgbase_flag_comment(request: Request, name: str): return render_template(request, "packages/flag-comment.html", context) -@router.post("/pkgbase/{name}/unflag") -@auth_required(True, redirect="/pkgbase/{name}") -async def pkgbase_unflag(request: Request, name: str): - pkgbase = get_pkg_or_base(name, models.PackageBase) - +def pkgbase_unflag_instance(request: Request, pkgbase: models.PackageBase): has_cred = request.user.has_credential( "CRED_PKGBASE_UNFLAG", approved=[pkgbase.Flagger, pkgbase.Maintainer]) if has_cred: @@ -840,6 +836,12 @@ async def pkgbase_unflag(request: Request, name: str): pkgbase.Flagger = None pkgbase.FlaggerComment = str() + +@router.post("/pkgbase/{name}/unflag") +@auth_required(True, redirect="/pkgbase/{name}") +async def pkgbase_unflag(request: Request, name: str): + pkgbase = get_pkg_or_base(name, models.PackageBase) + pkgbase_unflag_instance(request, pkgbase) return RedirectResponse(f"/pkgbase/{name}", status_code=HTTPStatus.SEE_OTHER) @@ -1042,10 +1044,38 @@ async def pkgbase_delete_post(request: Request, name: str, return RedirectResponse("/packages", status_code=HTTPStatus.SEE_OTHER) + +async def packages_unflag(request: Request, package_ids: List[int] = [], + **kwargs): + if not package_ids: + return (False, ["You did not select any packages to unflag."]) + + # Holds the set of package bases we're looking to unflag. + # Constructed below via looping through the packages query. + bases = set() + + package_ids = set(package_ids) # Convert this to a set for O(1). + packages = db.query(models.Package).filter( + models.Package.ID.in_(package_ids)).all() + for pkg in packages: + has_cred = request.user.has_credential( + "CRED_PKGBASE_UNFLAG", approved=[pkg.PackageBase.Flagger]) + if not has_cred: + return (False, ["You did not select any packages to unflag."]) + + if pkg.PackageBase not in bases: + bases.update({pkg.PackageBase}) + + for pkgbase in bases: + pkgbase_unflag_instance(request, pkgbase) + return (True, ["The selected packages have been unflagged."]) + # A mapping of action string -> callback functions used within the # `packages_post` route below. We expect any action callback to # return a tuple in the format: (succeeded: bool, message: List[str]). -PACKAGE_ACTIONS = {} +PACKAGE_ACTIONS = { + "unflag": packages_unflag, +} @router.post("/packages") diff --git a/test/test_packages_routes.py b/test/test_packages_routes.py index 93d994a2..b35cb377 100644 --- a/test/test_packages_routes.py +++ b/test/test_packages_routes.py @@ -2067,3 +2067,49 @@ def test_pkgbase_merge(client: TestClient, tu_user: User, package: Package): resp = request.get(endpoint, cookies=cookies) assert resp.status_code == int(HTTPStatus.OK) assert not get_errors(resp.text) + + +def test_packages_post_unflag(client: TestClient, user: User, + maintainer: User, package: Package): + # Flag `package` as `user`. + now = int(datetime.utcnow().timestamp()) + with db.begin(): + package.PackageBase.Flagger = user + package.PackageBase.OutOfDateTS = now + + cookies = {"AURSID": user.login(Request(), "testPassword")} + + # Don't supply any packages. + post_data = {"action": "unflag", "IDs": []} + with client as request: + resp = request.post("/packages", data=post_data, cookies=cookies) + assert resp.status_code == int(HTTPStatus.BAD_REQUEST) + errors = get_errors(resp.text) + expected = "You did not select any packages to unflag." + assert errors[0].text.strip() == expected + + # Unflag the package as `user`. + post_data = {"action": "unflag", "IDs": [package.ID]} + with client as request: + resp = request.post("/packages", data=post_data, cookies=cookies) + assert resp.status_code == int(HTTPStatus.OK) + assert package.PackageBase.Flagger is None + successes = get_successes(resp.text) + expected = "The selected packages have been unflagged." + assert successes[0].text.strip() == expected + + # Re-flag `package` as `user`. + now = int(datetime.utcnow().timestamp()) + with db.begin(): + package.PackageBase.Flagger = user + package.PackageBase.OutOfDateTS = now + + # Try to unflag the package as `maintainer`, which is not allowed. + maint_cookies = {"AURSID": maintainer.login(Request(), "testPassword")} + post_data = {"action": "unflag", "IDs": [package.ID]} + with client as request: + resp = request.post("/packages", data=post_data, cookies=maint_cookies) + assert resp.status_code == int(HTTPStatus.BAD_REQUEST) + errors = get_errors(resp.text) + expected = "You did not select any packages to unflag." + assert errors[0].text.strip() == expected