mirror of
https://gitlab.archlinux.org/archlinux/aurweb.git
synced 2025-02-03 10:43:03 +01:00
feat(FastAPI): add /pkgbase/{name}/delete (get, post)
In addition, we've had to add cascade arguments to backref so sqlalchemy treats the relationships as proper cascades. Furthermore, our pkgbase actions template was not rendering actions properly based on TU credentials. Signed-off-by: Kevin Morris <kevr@0cost.org>
This commit is contained in:
parent
4e7d2295da
commit
d38abd7832
3 changed files with 139 additions and 0 deletions
|
@ -940,3 +940,40 @@ async def pkgbase_disown_post(request: Request, name: str,
|
|||
disown_pkgbase(pkgbase, request.user)
|
||||
return RedirectResponse(f"/pkgbase/{name}",
|
||||
status_code=int(HTTPStatus.SEE_OTHER))
|
||||
|
||||
|
||||
@router.get("/pkgbase/{name}/delete")
|
||||
@auth_required(True)
|
||||
async def pkgbase_delete_get(request: Request, name: str):
|
||||
if not request.user.has_credential("CRED_PKGBASE_DELETE"):
|
||||
return RedirectResponse(f"/pkgbase/{name}",
|
||||
status_code=int(HTTPStatus.SEE_OTHER))
|
||||
|
||||
context = make_context(request, "Package Deletion")
|
||||
context["pkgbase"] = get_pkg_or_base(name, PackageBase)
|
||||
return render_template(request, "packages/delete.html", context)
|
||||
|
||||
|
||||
@router.post("/pkgbase/{name}/delete")
|
||||
@auth_required(True)
|
||||
async def pkgbase_delete_post(request: Request, name: str,
|
||||
confirm: bool = Form(default=False)):
|
||||
pkgbase = get_pkg_or_base(name, PackageBase)
|
||||
|
||||
if not request.user.has_credential("CRED_PKGBASE_DELETE"):
|
||||
return RedirectResponse(f"/pkgbase/{name}",
|
||||
status_code=int(HTTPStatus.SEE_OTHER))
|
||||
|
||||
if not confirm:
|
||||
context = make_context(request, "Package Deletion")
|
||||
context["pkgbase"] = pkgbase
|
||||
context["errors"] = [("The selected packages have not been deleted, "
|
||||
"check the confirmation checkbox.")]
|
||||
return render_template(request, "packages/delete.html", context,
|
||||
status_code=int(HTTPStatus.EXPECTATION_FAILED))
|
||||
|
||||
packages = pkgbase.packages.all()
|
||||
for package in packages:
|
||||
delete_package(request.user, package)
|
||||
|
||||
return RedirectResponse("/packages", status_code=int(HTTPStatus.SEE_OTHER))
|
||||
|
|
56
templates/packages/delete.html
Normal file
56
templates/packages/delete.html
Normal file
|
@ -0,0 +1,56 @@
|
|||
{% extends "partials/layout.html" %}
|
||||
|
||||
{% block pageContent %}
|
||||
|
||||
{% if errors %}
|
||||
<ul class="errorlist">
|
||||
{% for error in errors %}
|
||||
<li>{{ error | tr }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
<div class="box">
|
||||
<h2>{{ "Delete Package" | tr }}: {{ pkgbase.Name }}</h2>
|
||||
|
||||
<p>
|
||||
{{
|
||||
"Use this form to delete the package base %s%s%s and "
|
||||
"the following packages from the AUR: "
|
||||
| tr | format("<strong>", pkgbase.Name, "</strong>") | safe
|
||||
}}
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
{% for package in pkgbase.packages.all() %}
|
||||
<li>{{ package.Name }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
{{
|
||||
"Deletion of a package is permanent. "
|
||||
"Select the checkbox to confirm action." | tr
|
||||
}}
|
||||
</p>
|
||||
|
||||
<form action="/pkgbase/{{ pkgbase.Name }}/delete" method="post">
|
||||
<fieldset>
|
||||
<p>
|
||||
<label class="confirmation">
|
||||
<input type="checkbox" name="confirm" value="1" />
|
||||
{{ "Confirm package deletion" | tr }}
|
||||
</label>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<input class="button"
|
||||
type="submit"
|
||||
value="{{ 'Delete' | tr }}"
|
||||
/>
|
||||
</p>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -1845,3 +1845,49 @@ def test_pkgbase_disown(client: TestClient, user: User, maintainer: User,
|
|||
with client as request:
|
||||
resp = request.post(endpoint, data={"confirm": True}, cookies=cookies)
|
||||
assert resp.status_code == int(HTTPStatus.SEE_OTHER)
|
||||
|
||||
|
||||
def test_pkgbase_delete_unauthorized(client: TestClient, user: User,
|
||||
package: Package):
|
||||
pkgbase = package.PackageBase
|
||||
cookies = {"AURSID": user.login(Request(), "testPassword")}
|
||||
endpoint = f"/pkgbase/{pkgbase.Name}/delete"
|
||||
|
||||
# Test GET.
|
||||
with client as request:
|
||||
resp = request.get(endpoint, cookies=cookies, allow_redirects=False)
|
||||
assert resp.status_code == int(HTTPStatus.SEE_OTHER)
|
||||
assert resp.headers.get("location") == f"/pkgbase/{pkgbase.Name}"
|
||||
|
||||
# Test POST.
|
||||
with client as request:
|
||||
resp = request.post(endpoint, cookies=cookies)
|
||||
assert resp.status_code == int(HTTPStatus.SEE_OTHER)
|
||||
assert resp.headers.get("location") == f"/pkgbase/{pkgbase.Name}"
|
||||
|
||||
|
||||
def test_pkgbase_delete(client: TestClient, tu_user: User, package: Package):
|
||||
pkgbase = package.PackageBase
|
||||
|
||||
# Test that the GET request works.
|
||||
cookies = {"AURSID": tu_user.login(Request(), "testPassword")}
|
||||
endpoint = f"/pkgbase/{pkgbase.Name}/delete"
|
||||
with client as request:
|
||||
resp = request.get(endpoint, cookies=cookies)
|
||||
assert resp.status_code == int(HTTPStatus.OK)
|
||||
|
||||
# Test that POST works and denies us because we haven't confirmed.
|
||||
with client as request:
|
||||
resp = request.post(endpoint, cookies=cookies)
|
||||
assert resp.status_code == int(HTTPStatus.EXPECTATION_FAILED)
|
||||
|
||||
# Test that we can actually delete the pkgbase.
|
||||
with client as request:
|
||||
resp = request.post(endpoint, data={"confirm": True}, cookies=cookies)
|
||||
assert resp.status_code == int(HTTPStatus.SEE_OTHER)
|
||||
|
||||
# Let's assert that the package base record got removed.
|
||||
record = db.query(PackageBase).filter(
|
||||
PackageBase.Name == pkgbase.Name
|
||||
).first()
|
||||
assert record is None
|
||||
|
|
Loading…
Add table
Reference in a new issue