From 6986d1bb1e7435f6ab0b7cc3f377dd2e54829b95 Mon Sep 17 00:00:00 2001
From: Kevin Morris
Date: Fri, 4 Feb 2022 21:27:01 -0800
Subject: [PATCH 001/481] fix: update rpc documentation
- we no longer prefer the use of trailing slashes on the AUR
website.
Signed-off-by: Kevin Morris
---
doc/rpc.txt | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/doc/rpc.txt b/doc/rpc.txt
index b0f5c4e1..f75289e5 100644
--- a/doc/rpc.txt
+++ b/doc/rpc.txt
@@ -5,7 +5,7 @@ Package Search
--------------
Package searches can be performed by issuing HTTP GET requests of the form
-+/rpc/?v=5&type=search&by=_field_&arg=_keywords_+ where _keywords_ is the
++/rpc?v=5&type=search&by=_field_&arg=_keywords_+ where _keywords_ is the
search argument and _field_ is one of the following values:
* `name` (search by package name only)
@@ -25,25 +25,25 @@ Package Details
---------------
Package information can be obtained by issuing HTTP GET requests of the form
-+/rpc/?v=5&type=info&arg[]=_pkg1_&arg[]=_pkg2_&...+ where _pkg1_, _pkg2_, ...
++/rpc?v=5&type=info&arg[]=_pkg1_&arg[]=_pkg2_&...+ where _pkg1_, _pkg2_, ...
are the names of packages to retrieve package details for.
Examples
--------
`search`::
- `/rpc/?v=5&type=search&arg=foobar`
+ `/rpc?v=5&type=search&arg=foobar`
`search` by maintainer::
- `/rpc/?v=5&type=search&by=maintainer&arg=john`
+ `/rpc?v=5&type=search&by=maintainer&arg=john`
`search` packages that have _boost_ as `makedepends`::
- `/rpc/?v=5&type=search&by=makedepends&arg=boost`
+ `/rpc?v=5&type=search&by=makedepends&arg=boost`
`search` with callback::
- `/rpc/?v=5&type=search&arg=foobar&callback=jsonp1192244621103`
+ `/rpc?v=5&type=search&arg=foobar&callback=jsonp1192244621103`
`search` with API Version 6 for packages containing `cookie` AND `milk`::
- `/rpc/?v=6&type=search&arg=cookie%20milk`
+ `/rpc?v=6&type=search&arg=cookie%20milk`
`search` with API Version 6 for packages containing `cookie milk`::
- `/rpc/?v=6&type=search&arg="cookie milk"`
+ `/rpc?v=6&type=search&arg="cookie milk"`
`info`::
- `/rpc/?v=5&type=info&arg[]=foobar`
+ `/rpc?v=5&type=info&arg[]=foobar`
`info` with multiple packages::
- `/rpc/?v=5&type=info&arg[]=foo&arg[]=bar`
+ `/rpc?v=5&type=info&arg[]=foo&arg[]=bar`
From ac68f74c69dfbe6f1319a33fefc6baa1e4f0299d Mon Sep 17 00:00:00 2001
From: Kevin Morris
Date: Sat, 5 Feb 2022 01:34:30 -0800
Subject: [PATCH 002/481] fix: Hide Email Address checkbox markup
also:
- support empty strings in util.strtobool
Signed-off-by: Kevin Morris
---
aurweb/util.py | 6 +++---
templates/partials/account_form.html | 6 +++++-
2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/aurweb/util.py b/aurweb/util.py
index 1f75ac22..cb8e4b5b 100644
--- a/aurweb/util.py
+++ b/aurweb/util.py
@@ -7,7 +7,7 @@ import string
from datetime import datetime
from distutils.util import strtobool as _strtobool
from http import HTTPStatus
-from typing import Callable, Iterable, Tuple
+from typing import Callable, Iterable, Tuple, Union
from urllib.parse import urlparse
import fastapi
@@ -133,9 +133,9 @@ def sanitize_params(offset: str, per_page: str) -> Tuple[int, int]:
return (offset, per_page)
-def strtobool(value: str) -> bool:
+def strtobool(value: Union[str, bool]) -> bool:
if isinstance(value, str):
- return _strtobool(value)
+ return _strtobool(value or "False")
return value
diff --git a/templates/partials/account_form.html b/templates/partials/account_form.html
index f6a24c66..9136ee7a 100644
--- a/templates/partials/account_form.html
+++ b/templates/partials/account_form.html
@@ -105,7 +105,11 @@
{% trans %}Hide Email Address{% endtrans %}:
-
+
{{ "If you do not hide your email address, it is "
From f3360d12491791745d89a943d7fb1ecd06de933f Mon Sep 17 00:00:00 2001
From: Kevin Morris
Date: Sat, 5 Feb 2022 02:06:02 -0800
Subject: [PATCH 003/481] fix: eradicate spaces from pgp key fingerprint input
Signed-off-by: Kevin Morris
---
aurweb/routers/accounts.py | 6 +++++-
aurweb/util.py | 1 -
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/aurweb/routers/accounts.py b/aurweb/routers/accounts.py
index d296a9b9..7cd25c49 100644
--- a/aurweb/routers/accounts.py
+++ b/aurweb/routers/accounts.py
@@ -265,7 +265,7 @@ async def account_register_post(request: Request,
"options", "default_lang")),
TZ: str = Form(default=aurweb.config.get(
"options", "default_timezone")),
- PK: str = Form(default=None), # SSH PubKey
+ PK: str = Form(default=str()), # SSH PubKey
CN: bool = Form(default=False),
UN: bool = Form(default=False),
ON: bool = Form(default=False),
@@ -273,6 +273,8 @@ async def account_register_post(request: Request,
captcha_salt: str = Form(...)):
context = await make_variable_context(request, "Register")
args = dict(await request.form())
+ args["K"] = args.get("K", str()).replace(" ", "")
+ K = args.get("K")
context = make_account_form_context(context, request, None, args)
ok, errors = process_account_form(request, request.user, args)
@@ -399,6 +401,8 @@ async def account_edit_post(request: Request,
context["user"] = db.refresh(user)
args = dict(await request.form())
+ args["K"] = args.get("K", str()).replace(" ", "")
+
context = make_account_form_context(context, request, user, args)
ok, errors = process_account_form(request, user, args)
diff --git a/aurweb/util.py b/aurweb/util.py
index cb8e4b5b..7ed4d1d3 100644
--- a/aurweb/util.py
+++ b/aurweb/util.py
@@ -71,7 +71,6 @@ def valid_password(password):
def valid_pgp_fingerprint(fp):
- fp = fp.replace(" ", "")
try:
# Attempt to convert the fingerprint to an int via base16.
# If it can't, it's not a hex string.
From c80a16c25415deed962490dcf7661c6c20485050 Mon Sep 17 00:00:00 2001
From: Kevin Morris
Date: Sat, 5 Feb 2022 02:29:41 -0800
Subject: [PATCH 004/481] fix: allow users to login using their email
Signed-off-by: Kevin Morris
---
aurweb/routers/auth.py | 5 ++++-
test/test_auth_routes.py | 14 ++++++++++++++
2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/aurweb/routers/auth.py b/aurweb/routers/auth.py
index bae9a599..5d88ed48 100644
--- a/aurweb/routers/auth.py
+++ b/aurweb/routers/auth.py
@@ -2,6 +2,7 @@ from http import HTTPStatus
from fastapi import APIRouter, Form, HTTPException, Request
from fastapi.responses import HTMLResponse, RedirectResponse
+from sqlalchemy import or_
import aurweb.config
@@ -43,7 +44,9 @@ async def login_post(request: Request,
raise HTTPException(status_code=HTTPStatus.BAD_REQUEST,
detail=_("Bad Referer header."))
- user = db.query(User).filter(User.Username == user).first()
+ user = db.query(User).filter(
+ or_(User.Username == user, User.Email == user)
+ ).first()
if not user:
return await login_template(request, next,
errors=["Bad username or password."])
diff --git a/test/test_auth_routes.py b/test/test_auth_routes.py
index 4136a18e..79b34b6b 100644
--- a/test/test_auth_routes.py
+++ b/test/test_auth_routes.py
@@ -79,6 +79,20 @@ def test_login_logout(client: TestClient, user: User):
assert "AURSID" not in response.cookies
+def test_login_email(client: TestClient, user: user):
+ post_data = {
+ "user": user.Email,
+ "passwd": "testPassword",
+ "next": "/"
+ }
+
+ with client as request:
+ resp = request.post("/login", data=post_data,
+ allow_redirects=False)
+ assert resp.status_code == int(HTTPStatus.SEE_OTHER)
+ assert "AURSID" in resp.cookies
+
+
def mock_getboolean(a, b):
if a == "options" and b == "disable_http_login":
return True
From 28549b47bbebf6ff8d9a62a3d3745cb9e04d5f3d Mon Sep 17 00:00:00 2001
From: Kevin Morris
Date: Sat, 5 Feb 2022 02:40:19 -0800
Subject: [PATCH 005/481] fix: /packages search by co-maintainer
Signed-off-by: Kevin Morris
---
aurweb/packages/search.py | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/aurweb/packages/search.py b/aurweb/packages/search.py
index b4af5aab..60a5547e 100644
--- a/aurweb/packages/search.py
+++ b/aurweb/packages/search.py
@@ -120,11 +120,12 @@ class PackageSearch:
def _search_by_comaintainer(self, keywords: str) -> orm.Query:
self._join_user()
- exists_subq = db.query(PackageComaintainer).join(User).filter(
- and_(PackageComaintainer.PackageBaseID == PackageBase.ID,
- User.Username == keywords)
- ).exists()
- self.query = self.query.filter(db.query(exists_subq).scalar_subquery())
+ user = db.query(User).filter(User.Username == keywords).first()
+ uid = 0 if not user else user.ID
+ self.query = self.query.join(
+ PackageComaintainer,
+ PackageComaintainer.PackageBaseID == PackageBase.ID
+ ).filter(PackageComaintainer.UsersID == uid)
return self
def _search_by_co_or_maintainer(self, keywords: str) -> orm.Query:
From c1420b52fb4fd39f1f8a576276101ded2100bc79 Mon Sep 17 00:00:00 2001
From: Kevin Morris
Date: Sat, 5 Feb 2022 02:56:53 -0800
Subject: [PATCH 006/481] fix: rpc doc should not have v=6 information
Signed-off-by: Kevin Morris
---
doc/rpc.txt | 4 ----
1 file changed, 4 deletions(-)
diff --git a/doc/rpc.txt b/doc/rpc.txt
index f75289e5..f0a28183 100644
--- a/doc/rpc.txt
+++ b/doc/rpc.txt
@@ -39,10 +39,6 @@ Examples
`/rpc?v=5&type=search&by=makedepends&arg=boost`
`search` with callback::
`/rpc?v=5&type=search&arg=foobar&callback=jsonp1192244621103`
-`search` with API Version 6 for packages containing `cookie` AND `milk`::
- `/rpc?v=6&type=search&arg=cookie%20milk`
-`search` with API Version 6 for packages containing `cookie milk`::
- `/rpc?v=6&type=search&arg="cookie milk"`
`info`::
`/rpc?v=5&type=info&arg[]=foobar`
`info` with multiple packages::
From a445a40bead694798cbe604a25e85bdb16e0b488 Mon Sep 17 00:00:00 2001
From: Kevin Morris
Date: Sat, 5 Feb 2022 02:58:16 -0800
Subject: [PATCH 007/481] fix: Maintainer's comaintainer annotation display
Signed-off-by: Kevin Morris
---
templates/partials/packages/details.html | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/templates/partials/packages/details.html b/templates/partials/packages/details.html
index 1c4d01d6..b5193314 100644
--- a/templates/partials/packages/details.html
+++ b/templates/partials/packages/details.html
@@ -112,8 +112,9 @@
{{ pkgbase.Maintainer.Username }}
+ {% set len = comaintainers | length %}
{% if comaintainers %}
- ({% for co in comaintainers %}{{ co.User }}{% endfor %})
+ ({% for co in comaintainers %}{{ co.User }}{% if loop.index < len %}, {% endif %}{% endfor %})
{% endif %}
{% else %}
{{ pkgbase.Maintainer.Username | default("None" | tr) }}
From 7618101b1b26edfea174e32e80716246ddef754d Mon Sep 17 00:00:00 2001
From: Kevin Morris
Date: Sat, 5 Feb 2022 03:21:46 -0800
Subject: [PATCH 008/481] fix: depend on OutOfDateTS for flag state
It was found in the aur.al database that some records have
a non-null flagger, but are not flagged. Using the flagger
relationship, we were false redirecting away from the flag
page.
Signed-off-by: Kevin Morris
---
aurweb/routers/pkgbase.py | 6 +++---
test/test_pkgbase_routes.py | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/aurweb/routers/pkgbase.py b/aurweb/routers/pkgbase.py
index 3aa73a02..b014ddc5 100644
--- a/aurweb/routers/pkgbase.py
+++ b/aurweb/routers/pkgbase.py
@@ -78,7 +78,7 @@ async def pkgbase_voters(request: Request, name: str) -> Response:
async def pkgbase_flag_comment(request: Request, name: str):
pkgbase = get_pkg_or_base(name, PackageBase)
- if pkgbase.Flagger is None:
+ if pkgbase.OutOfDateTS is None:
return RedirectResponse(f"/pkgbase/{name}",
status_code=HTTPStatus.SEE_OTHER)
@@ -120,7 +120,7 @@ async def pkgbase_flag_get(request: Request, name: str):
pkgbase = get_pkg_or_base(name, PackageBase)
has_cred = request.user.has_credential(creds.PKGBASE_FLAG)
- if not has_cred or pkgbase.Flagger is not None:
+ if not has_cred or pkgbase.OutOfDateTS is not None:
return RedirectResponse(f"/pkgbase/{name}",
status_code=HTTPStatus.SEE_OTHER)
@@ -144,7 +144,7 @@ async def pkgbase_flag_post(request: Request, name: str,
status_code=HTTPStatus.BAD_REQUEST)
has_cred = request.user.has_credential(creds.PKGBASE_FLAG)
- if has_cred and not pkgbase.Flagger:
+ if has_cred and not pkgbase.OutOfDateTS:
now = time.utcnow()
with db.begin():
pkgbase.OutOfDateTS = now
diff --git a/test/test_pkgbase_routes.py b/test/test_pkgbase_routes.py
index 3f5a791a..0287a026 100644
--- a/test/test_pkgbase_routes.py
+++ b/test/test_pkgbase_routes.py
@@ -804,7 +804,7 @@ def test_pkgbase_flag(client: TestClient, user: User, maintainer: User,
pkgbase = package.PackageBase
# We shouldn't have flagged the package yet; assert so.
- assert pkgbase.Flagger is None
+ assert pkgbase.OutOfDateTS is None
cookies = {"AURSID": user.login(Request(), "testPassword")}
endpoint = f"/pkgbase/{pkgbase.Name}/flag"
From 39d6f927e6c2db7dca8c33d0bff1d768ce024b16 Mon Sep 17 00:00:00 2001
From: Kevin Morris
Date: Sat, 5 Feb 2022 03:42:43 -0800
Subject: [PATCH 009/481] fix: Maintainer, Co-maintainer /package search
Signed-off-by: Kevin Morris
---
aurweb/packages/search.py | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/aurweb/packages/search.py b/aurweb/packages/search.py
index 60a5547e..01b0e154 100644
--- a/aurweb/packages/search.py
+++ b/aurweb/packages/search.py
@@ -130,15 +130,15 @@ class PackageSearch:
def _search_by_co_or_maintainer(self, keywords: str) -> orm.Query:
self._join_user()
- exists_subq = db.query(PackageComaintainer).join(User).filter(
- and_(PackageComaintainer.PackageBaseID == PackageBase.ID,
- User.Username == keywords)
- ).exists()
- self.query = self.query.filter(
- or_(and_(User.Username == keywords,
- User.ID == PackageBase.MaintainerUID),
- db.query(exists_subq).scalar_subquery())
- )
+
+ user = db.query(User).filter(User.Username == keywords).first()
+ uid = 0 if not user else user.ID
+ self.query = self.query.join(
+ PackageComaintainer,
+ PackageComaintainer.PackageBaseID == PackageBase.ID,
+ isouter=True
+ ).filter(or_(PackageComaintainer.UsersID == uid, User.ID == uid))
+
return self
def _search_by_submitter(self, keywords: str) -> orm.Query:
From d5a1c1645880c1330299d38cc7d6c73d09883070 Mon Sep 17 00:00:00 2001
From: Kevin Morris
Date: Sat, 5 Feb 2022 03:48:58 -0800
Subject: [PATCH 010/481] upgrade: bump to v6.0.7
Signed-off-by: Kevin Morris
---
aurweb/config.py | 2 +-
pyproject.toml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/aurweb/config.py b/aurweb/config.py
index 1a9b0719..b154fe30 100644
--- a/aurweb/config.py
+++ b/aurweb/config.py
@@ -6,7 +6,7 @@ from typing import Any
# Publicly visible version of aurweb. This is used to display
# aurweb versioning in the footer and must be maintained.
# Todo: Make this dynamic/automated.
-AURWEB_VERSION = "v6.0.6"
+AURWEB_VERSION = "v6.0.7"
_parser = None
diff --git a/pyproject.toml b/pyproject.toml
index f2f5847d..9e14b8e3 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -8,7 +8,7 @@
#
[tool.poetry]
name = "aurweb"
-version = "v6.0.6"
+version = "v6.0.7"
license = "GPL-2.0-only"
description = "Source code for the Arch User Repository's website"
homepage = "https://aur.archlinux.org"
From 2d6c09bec536dc40aa47ac834d1ac191242889e4 Mon Sep 17 00:00:00 2001
From: Kevin Morris
Date: Sat, 5 Feb 2022 04:28:50 -0800
Subject: [PATCH 011/481] fix: handling of user registration HideEmail
Signed-off-by: Kevin Morris
---
aurweb/routers/accounts.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/aurweb/routers/accounts.py b/aurweb/routers/accounts.py
index 7cd25c49..d1b9d428 100644
--- a/aurweb/routers/accounts.py
+++ b/aurweb/routers/accounts.py
@@ -276,6 +276,9 @@ async def account_register_post(request: Request,
args["K"] = args.get("K", str()).replace(" ", "")
K = args.get("K")
+ # Force "H" into a boolean.
+ args["H"] = H = (args.get("H", str()) == "on")
+
context = make_account_form_context(context, request, None, args)
ok, errors = process_account_form(request, request.user, args)
if not ok:
From e777b7052e3648467f1185cf4782ed8b7d672ad5 Mon Sep 17 00:00:00 2001
From: Kevin Morris
Date: Sat, 5 Feb 2022 04:40:25 -0800
Subject: [PATCH 012/481] fix: send out a FlagNotification when a package is
flagged
Signed-off-by: Kevin Morris
---
aurweb/routers/pkgbase.py | 2 ++
test/test_pkgbase_routes.py | 3 +++
2 files changed, 5 insertions(+)
diff --git a/aurweb/routers/pkgbase.py b/aurweb/routers/pkgbase.py
index b014ddc5..3ec009e5 100644
--- a/aurweb/routers/pkgbase.py
+++ b/aurweb/routers/pkgbase.py
@@ -145,11 +145,13 @@ async def pkgbase_flag_post(request: Request, name: str,
has_cred = request.user.has_credential(creds.PKGBASE_FLAG)
if has_cred and not pkgbase.OutOfDateTS:
+ notif = notify.FlagNotification(request.user.ID, pkgbase.ID)
now = time.utcnow()
with db.begin():
pkgbase.OutOfDateTS = now
pkgbase.Flagger = request.user
pkgbase.FlaggerComment = comments
+ notif.send()
return RedirectResponse(f"/pkgbase/{name}",
status_code=HTTPStatus.SEE_OTHER)
diff --git a/test/test_pkgbase_routes.py b/test/test_pkgbase_routes.py
index 0287a026..1bd3e524 100644
--- a/test/test_pkgbase_routes.py
+++ b/test/test_pkgbase_routes.py
@@ -836,6 +836,9 @@ def test_pkgbase_flag(client: TestClient, user: User, maintainer: User,
assert pkgbase.Flagger == user
assert pkgbase.FlaggerComment == "Test"
+ # Should've gotten a FlagNotification.
+ assert Email.count() == 1
+
# Now, let's check the /pkgbase/{name}/flag-comment route.
flag_comment_endpoint = f"/pkgbase/{pkgbase.Name}/flag-comment"
with client as request:
From 1545eab81d05fbeb87d7c9a9221c250a2b5b7fa5 Mon Sep 17 00:00:00 2001
From: Kevin Morris
Date: Sat, 5 Feb 2022 18:35:50 -0800
Subject: [PATCH 013/481] feat: add timezone to datetime display across the
board
- the "Flagged Out-of-date on ..." link in the package action panel does
not contain a timezone specifier.
Signed-off-by: Kevin Morris
---
aurweb/filters.py | 24 ++++++++++++++++++++-
templates/account/show.html | 7 +++---
templates/partials/account/comment.html | 4 ++--
templates/partials/packages/actions.html | 3 +--
templates/partials/packages/comment.html | 6 +++---
templates/partials/packages/details.html | 6 ++----
templates/partials/packages/requests.html | 2 +-
templates/partials/packages/updates.html | 3 +--
templates/partials/tu/proposal/details.html | 6 ++----
templates/partials/tu/proposals.html | 11 ++--------
templates/pkgbase/flag-comment.html | 2 +-
templates/pkgbase/voters.html | 3 +--
templates/requests.html | 3 +--
test/test_templates.py | 2 +-
test/test_trusted_user_routes.py | 6 +++---
15 files changed, 47 insertions(+), 41 deletions(-)
diff --git a/aurweb/filters.py b/aurweb/filters.py
index 9b731501..45cb6d83 100644
--- a/aurweb/filters.py
+++ b/aurweb/filters.py
@@ -2,7 +2,7 @@ import copy
import math
from datetime import datetime
-from typing import Any, Dict
+from typing import Any, Dict, Union
from urllib.parse import quote_plus, urlencode
from zoneinfo import ZoneInfo
@@ -148,3 +148,25 @@ def _quote_plus(*args, **kwargs) -> str:
@register_filter("ceil")
def ceil(*args, **kwargs) -> int:
return math.ceil(*args, **kwargs)
+
+
+@register_function("date_strftime")
+@pass_context
+def date_strftime(context: Dict[str, Any], dt: Union[int, datetime], fmt: str) \
+ -> str:
+ if isinstance(dt, int):
+ dt = timestamp_to_datetime(dt)
+ tz = context.get("timezone")
+ return as_timezone(dt, tz).strftime(fmt)
+
+
+@register_function("date_display")
+@pass_context
+def date_display(context: Dict[str, Any], dt: Union[int, datetime]) -> str:
+ return date_strftime(context, dt, "%Y-%m-%d (%Z)")
+
+
+@register_function("datetime_display")
+@pass_context
+def datetime_display(context: Dict[str, Any], dt: Union[int, datetime]) -> str:
+ return date_strftime(context, dt, "%Y-%m-%d %H:%M (%Z)")
diff --git a/templates/account/show.html b/templates/account/show.html
index 34549ff0..a9bb3c30 100644
--- a/templates/account/show.html
+++ b/templates/account/show.html
@@ -57,7 +57,7 @@
{# Status #}
diff --git a/test/test_templates.py b/test/test_templates.py
index 0d36d0b9..7d6b585c 100644
--- a/test/test_templates.py
+++ b/test/test_templates.py
@@ -258,7 +258,7 @@ def check_package_details(content: str, pkg: Package) -> None:
assert pop.text.strip() == number_format(0, 6)
# Check First Submitted
- date_fmt = "%Y-%m-%d %H:%M"
+ date_fmt = "%Y-%m-%d %H:%M (%Z)"
i += 1
first_submitted = rows[i].xpath("./td")[0]
converted_dt = as_timezone(to_dt(pkg.PackageBase.SubmittedTS), "UTC")
diff --git a/test/test_trusted_user_routes.py b/test/test_trusted_user_routes.py
index 0ea44d10..a448c043 100644
--- a/test/test_trusted_user_routes.py
+++ b/test/test_trusted_user_routes.py
@@ -16,7 +16,7 @@ from aurweb.models.tu_voteinfo import TUVoteInfo
from aurweb.models.user import User
from aurweb.testing.requests import Request
-DATETIME_REGEX = r'^[0-9]{4}-[0-9]{2}-[0-9]{2}$'
+DATETIME_REGEX = r'^[0-9]{4}-[0-9]{2}-[0-9]{2} \(.+\)$'
PARTICIPATION_REGEX = r'^1?[0-9]{2}[%]$' # 0% - 100%
@@ -523,7 +523,7 @@ def test_tu_running_proposal(client: TestClient,
submitted = details.xpath(
'./div[contains(@class, "submitted")]/text()')[0]
- assert re.match(r'^Submitted: \d{4}-\d{2}-\d{2} \d{2}:\d{2} by$',
+ assert re.match(r'^Submitted: \d{4}-\d{2}-\d{2} \d{2}:\d{2} \(.+\) by$',
submitted.strip()) is not None
submitter = details.xpath('./div[contains(@class, "submitted")]/a')[0]
assert submitter.text.strip() == tu_user.Username
@@ -534,7 +534,7 @@ def test_tu_running_proposal(client: TestClient,
assert end_label.strip() == "End:"
end_datetime = end.xpath("./strong/text()")[0]
- assert re.match(r'^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$',
+ assert re.match(r'^\d{4}-\d{2}-\d{2} \d{2}:\d{2} \(.+\)$',
end_datetime.strip()) is not None
# We have not voted yet. Assert that our voting form is shown.
From 750653361f3c4fa8312082e72657f970a244ebe7 Mon Sep 17 00:00:00 2001
From: Kevin Morris
Date: Sun, 6 Feb 2022 16:11:54 -0800
Subject: [PATCH 014/481] fix: remove /packages search count limit
...took this opportunity to use the new options.max_search_results
tunable for a PP upper-bound.
Signed-off-by: Kevin Morris
---
aurweb/packages/search.py | 11 +++--------
aurweb/routers/packages.py | 8 +++++---
2 files changed, 8 insertions(+), 11 deletions(-)
diff --git a/aurweb/packages/search.py b/aurweb/packages/search.py
index 01b0e154..b6b36c79 100644
--- a/aurweb/packages/search.py
+++ b/aurweb/packages/search.py
@@ -222,14 +222,9 @@ class PackageSearch:
ordering = self.FULL_SORT_ORDER.get(ordering)
return callback(ordering)
- def count(self, limit: int) -> int:
- """
- Return internal query's count up to `limit`.
-
- :param limit: Upper bound
- :return: Database count up to `limit`
- """
- return self.query.limit(limit).count()
+ def count(self) -> int:
+ """ Return internal query's count. """
+ return self.query.count()
def results(self) -> orm.Query:
""" Return internal query. """
diff --git a/aurweb/routers/packages.py b/aurweb/routers/packages.py
index 79c6a404..f6bf116d 100644
--- a/aurweb/routers/packages.py
+++ b/aurweb/routers/packages.py
@@ -31,7 +31,10 @@ async def packages_get(request: Request, context: Dict[str, Any],
request.query_params.get("O", defaults.O),
request.query_params.get("PP", defaults.PP))
context["O"] = offset
- context["PP"] = per_page
+
+ # Limit PP to options.max_search_results
+ max_search_results = aurweb.config.getint("options", "max_search_results")
+ context["PP"] = per_page = min(per_page, max_search_results)
# Query search by.
search_by = context["SeB"] = request.query_params.get("SeB", "nd")
@@ -56,8 +59,7 @@ async def packages_get(request: Request, context: Dict[str, Any],
# Collect search result count here; we've applied our keywords.
# Including more query operations below, like ordering, will
# increase the amount of time required to collect a count.
- limit = config.getint("options", "max_search_results")
- num_packages = search.count(limit)
+ num_packages = search.count()
flagged = request.query_params.get("outdated", None)
if flagged:
From 83f5d9e46049bd22a35cd52db7359358089ec7f7 Mon Sep 17 00:00:00 2001
From: Kevin Morris
Date: Sun, 6 Feb 2022 21:32:48 -0800
Subject: [PATCH 015/481] fix: RSS aurlogo.png url
Signed-off-by: Kevin Morris
---
aurweb/routers/rss.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/aurweb/routers/rss.py b/aurweb/routers/rss.py
index 454ff497..0996f3cd 100644
--- a/aurweb/routers/rss.py
+++ b/aurweb/routers/rss.py
@@ -27,7 +27,7 @@ def make_rss_feed(request: Request, packages: list,
feed.link(href=base, rel="alternate")
feed.link(href=f"{base}/rss", rel="self")
feed.image(title="AUR Newest Packages",
- url=f"{base}/css/archnavbar/aurlogo.png",
+ url=f"{base}/static/css/archnavbar/aurlogo.png",
link=base,
description="AUR Newest Packages Feed")
From 26f0b014f9eb1b27cee3623b6d7b9257a8f61925 Mon Sep 17 00:00:00 2001
From: Kevin Morris
Date: Sun, 6 Feb 2022 23:29:09 -0800
Subject: [PATCH 016/481] fix: /packages search by keywords
Signed-off-by: Kevin Morris
---
aurweb/packages/search.py | 24 +++++++++++++++++-------
aurweb/routers/packages.py | 9 +++++++--
2 files changed, 24 insertions(+), 9 deletions(-)
diff --git a/aurweb/packages/search.py b/aurweb/packages/search.py
index b6b36c79..ae739a95 100644
--- a/aurweb/packages/search.py
+++ b/aurweb/packages/search.py
@@ -1,3 +1,5 @@
+from typing import Set
+
from sqlalchemy import and_, case, or_, orm
from aurweb import db, models
@@ -59,17 +61,24 @@ class PackageSearch:
"l": self._sort_by_last_modified
}
- self._joined = False
+ self._joined_user = False
+ self._joined_keywords = False
def _join_user(self, outer: bool = True) -> orm.Query:
""" Centralized joining of a package base's maintainer. """
- if not self._joined:
+ if not self._joined_user:
self.query = self.query.join(
User,
User.ID == PackageBase.MaintainerUID,
isouter=outer
)
- self._joined = True
+ self._joined_user = True
+ return self.query
+
+ def _join_keywords(self) -> orm.Query:
+ if not self._joined_keywords:
+ self.query = self.query.join(PackageKeyword)
+ self._joined_keywords = True
return self.query
def _search_by_namedesc(self, keywords: str) -> orm.Query:
@@ -100,11 +109,12 @@ class PackageSearch:
self.query = self.query.filter(PackageBase.Name == keywords)
return self
- def _search_by_keywords(self, keywords: str) -> orm.Query:
+ def _search_by_keywords(self, keywords: Set[str]) -> orm.Query:
self._join_user()
- self.query = self.query.join(PackageKeyword).filter(
- PackageKeyword.Keyword == keywords
- )
+ self._join_keywords()
+ self.query = self.query.filter(
+ PackageKeyword.Keyword.in_(keywords)
+ ).group_by(Package.Name)
return self
def _search_by_maintainer(self, keywords: str) -> orm.Query:
diff --git a/aurweb/routers/packages.py b/aurweb/routers/packages.py
index f6bf116d..c2a4a49c 100644
--- a/aurweb/routers/packages.py
+++ b/aurweb/routers/packages.py
@@ -52,9 +52,14 @@ async def packages_get(request: Request, context: Dict[str, Any],
# This means that for any sentences separated by spaces,
# they are used as if they were ANDed.
keywords = context["K"] = request.query_params.get("K", str())
+
keywords = keywords.split(" ")
- for keyword in keywords:
- search.search_by(search_by, keyword)
+ if search_by == "k":
+ # If we're searchin by keywords, supply a set of keywords.
+ search.search_by(search_by, set(keywords))
+ else:
+ for keyword in keywords:
+ search.search_by(search_by, keyword)
# Collect search result count here; we've applied our keywords.
# Including more query operations below, like ordering, will
From 2dfa41c9a571cc838c6fe937c504d90f50636523 Mon Sep 17 00:00:00 2001
From: Kevin Morris
Date: Mon, 7 Feb 2022 00:49:34 -0800
Subject: [PATCH 017/481] feat(rpc): support POST method
Signed-off-by: Kevin Morris
---
aurweb/routers/rpc.py | 62 ++++++++++++++++++++++++++++++++-----------
doc/rpc.txt | 16 +++++++++++
test/test_rpc.py | 13 +++++++++
3 files changed, 75 insertions(+), 16 deletions(-)
diff --git a/aurweb/routers/rpc.py b/aurweb/routers/rpc.py
index aae47cfa..17eb377c 100644
--- a/aurweb/routers/rpc.py
+++ b/aurweb/routers/rpc.py
@@ -7,7 +7,7 @@ from urllib.parse import unquote
import orjson
-from fastapi import APIRouter, Query, Request, Response
+from fastapi import APIRouter, Form, Query, Request, Response
from fastapi.responses import JSONResponse
from aurweb import defaults
@@ -65,20 +65,13 @@ def parse_args(request: Request):
JSONP_EXPR = re.compile(r'^[a-zA-Z0-9()_.]{1,128}$')
-@router.get("/rpc.php/") # Temporary! Remove on 03/04
-@router.get("/rpc.php") # Temporary! Remove on 03/04
-@router.get("/rpc/")
-@router.get("/rpc")
-async def rpc(request: Request,
- v: Optional[int] = Query(default=None),
- type: Optional[str] = Query(default=None),
- by: Optional[str] = Query(default=defaults.RPC_SEARCH_BY),
- arg: Optional[str] = Query(default=None),
- args: Optional[List[str]] = Query(default=[], alias="arg[]"),
- callback: Optional[str] = Query(default=None)):
-
- if not request.url.query:
- return documentation()
+async def rpc_request(request: Request,
+ v: Optional[int] = None,
+ type: Optional[str] = None,
+ by: Optional[str] = defaults.RPC_SEARCH_BY,
+ arg: Optional[str] = None,
+ args: Optional[List[str]] = [],
+ callback: Optional[str] = None):
# Create a handle to our RPC class.
rpc = RPC(version=v, type=type)
@@ -100,7 +93,14 @@ async def rpc(request: Request,
# Prepare list of arguments for input. If 'arg' was given, it'll
# be a list with one element.
- arguments = parse_args(request)
+ arguments = []
+ if request.url.query:
+ arguments = parse_args(request)
+ else:
+ if arg:
+ arguments.append(arg)
+ arguments += args
+
data = rpc.handle(by=by, args=arguments)
# Serialize `data` into JSON in a sorted fashion. This way, our
@@ -128,3 +128,33 @@ async def rpc(request: Request,
content = f"/**/{callback}({content.decode()})"
return Response(content, headers=headers)
+
+
+@router.get("/rpc.php/") # Temporary! Remove on 03/04
+@router.get("/rpc.php") # Temporary! Remove on 03/04
+@router.get("/rpc/")
+@router.get("/rpc")
+async def rpc(request: Request,
+ v: Optional[int] = Query(default=None),
+ type: Optional[str] = Query(default=None),
+ by: Optional[str] = Query(default=defaults.RPC_SEARCH_BY),
+ arg: Optional[str] = Query(default=None),
+ args: Optional[List[str]] = Query(default=[], alias="arg[]"),
+ callback: Optional[str] = Query(default=None)):
+ if not request.url.query:
+ return documentation()
+ return await rpc_request(request, v, type, by, arg, args, callback)
+
+
+@router.get("/rpc.php/") # Temporary! Remove on 03/04
+@router.get("/rpc.php") # Temporary! Remove on 03/04
+@router.post("/rpc/")
+@router.post("/rpc")
+async def rpc_post(request: Request,
+ v: Optional[int] = Form(default=None),
+ type: Optional[str] = Form(default=None),
+ by: Optional[str] = Form(default=defaults.RPC_SEARCH_BY),
+ arg: Optional[str] = Form(default=None),
+ args: Optional[List[str]] = Form(default=[], alias="arg[]"),
+ callback: Optional[str] = Form(default=None)):
+ return await rpc_request(request, v, type, by, arg, args, callback)
diff --git a/doc/rpc.txt b/doc/rpc.txt
index f0a28183..ebd7e485 100644
--- a/doc/rpc.txt
+++ b/doc/rpc.txt
@@ -28,6 +28,22 @@ Package information can be obtained by issuing HTTP GET requests of the form
+/rpc?v=5&type=info&arg[]=_pkg1_&arg[]=_pkg2_&...+ where _pkg1_, _pkg2_, ...
are the names of packages to retrieve package details for.
+Request Types
+-------------
+
+The GET method here parses arguments in an odd way due to `v=5` historically
+supporting this ordering. Later versions will remove support for this kind
+of parsing, and the POST method is our first step toward solving it.
+
+* `GET`
+ - Search arguments are constructed using the last found argument(s).
+ If the last related argument is `arg[]`, we collect arguments from
+ end to start until we hit a non-`arg[]` argument. If the last related
+ argument is `arg`, it used as the one and only argument.
+* `POST`
+ - Search arguments are constructed using `[arg] + args` where
+ `args == arg[]`.
+
Examples
--------
diff --git a/test/test_rpc.py b/test/test_rpc.py
index 6063a26f..7847899c 100644
--- a/test/test_rpc.py
+++ b/test/test_rpc.py
@@ -782,3 +782,16 @@ def test_rpc_jsonp_callback(client: TestClient):
response = request.get("/rpc", params=params)
assert response.headers.get("content-type") == "application/json"
assert response.json().get("error") == "Invalid callback name."
+
+
+def test_rpc_post(client: TestClient, packages: List[Package]):
+ data = {
+ "v": 5,
+ "type": "info",
+ "arg": "big-chungus",
+ "arg[]": ["chungy-chungus"]
+ }
+ with client as request:
+ resp = request.post("/rpc", data=data)
+ assert resp.status_code == int(HTTPStatus.OK)
+ assert resp.json().get("resultcount") == 2
From 33cddb36ffad409674cfa35e9a76a4dcd3daad07 Mon Sep 17 00:00:00 2001
From: Kevin Morris
Date: Mon, 7 Feb 2022 01:14:17 -0800
Subject: [PATCH 018/481] fix: restore URL field in mkpkglists meta archives
Signed-off-by: Kevin Morris
---
aurweb/scripts/mkpkglists.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/aurweb/scripts/mkpkglists.py b/aurweb/scripts/mkpkglists.py
index d97bc01c..dd2e9e86 100755
--- a/aurweb/scripts/mkpkglists.py
+++ b/aurweb/scripts/mkpkglists.py
@@ -164,6 +164,7 @@ def as_dict(package: Package) -> Dict[str, Any]:
"PackageBase": package.PackageBase,
"Version": package.Version,
"Description": package.Description,
+ "URL": package.URL,
"NumVotes": package.NumVotes,
"Popularity": float(package.Popularity),
"OutOfDate": package.OutOfDate,
@@ -191,6 +192,7 @@ def _main():
PackageBase.Name.label("PackageBase"),
Package.Version,
Package.Description,
+ Package.URL,
PackageBase.NumVotes,
PackageBase.Popularity,
PackageBase.OutOfDateTS.label("OutOfDate"),
From 828847cfcdf6b3b89c0c54ec4436d2d71aa2b5f2 Mon Sep 17 00:00:00 2001
From: Kevin Morris
Date: Mon, 7 Feb 2022 12:23:35 -0800
Subject: [PATCH 019/481] fix: OutOfDateTS db fetch for pkgbase action display
Signed-off-by: Kevin Morris
---
templates/partials/packages/actions.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/templates/partials/packages/actions.html b/templates/partials/packages/actions.html
index 313495a3..427b3d0f 100644
--- a/templates/partials/packages/actions.html
+++ b/templates/partials/packages/actions.html
@@ -36,7 +36,7 @@
{{
"Flagged out-of-date (%s)"
- | tr | format(date_strftime(package.PackageBase.OutOfDateTS, "%Y-%m-%d"))
+ | tr | format(date_strftime(pkgbase.OutOfDateTS, "%Y-%m-%d"))
}}
From 957803a70b4c8b93503f8f89d762be6c8bae879e Mon Sep 17 00:00:00 2001
From: Kevin Morris
Date: Mon, 7 Feb 2022 16:12:26 -0800
Subject: [PATCH 020/481] fix: M/c search with multiple keywords
Signed-off-by: Kevin Morris
---
aurweb/packages/search.py | 41 ++++++++++++++++++++++----------------
aurweb/routers/packages.py | 2 +-
2 files changed, 25 insertions(+), 18 deletions(-)
diff --git a/aurweb/packages/search.py b/aurweb/packages/search.py
index ae739a95..b0e1e891 100644
--- a/aurweb/packages/search.py
+++ b/aurweb/packages/search.py
@@ -63,6 +63,7 @@ class PackageSearch:
self._joined_user = False
self._joined_keywords = False
+ self._joined_comaint = False
def _join_user(self, outer: bool = True) -> orm.Query:
""" Centralized joining of a package base's maintainer. """
@@ -73,13 +74,23 @@ class PackageSearch:
isouter=outer
)
self._joined_user = True
- return self.query
+ return self.query
def _join_keywords(self) -> orm.Query:
if not self._joined_keywords:
self.query = self.query.join(PackageKeyword)
self._joined_keywords = True
- return self.query
+ return self.query
+
+ def _join_comaint(self, isouter: bool = False) -> orm.Query:
+ if not self._joined_comaint:
+ self.query = self.query.join(
+ PackageComaintainer,
+ PackageComaintainer.PackageBaseID == PackageBase.ID,
+ isouter=isouter
+ )
+ self._joined_comaint = True
+ return self.query
def _search_by_namedesc(self, keywords: str) -> orm.Query:
self._join_user()
@@ -102,6 +113,7 @@ class PackageSearch:
def _search_by_pkgbase(self, keywords: str) -> orm.Query:
self._join_user()
self.query = self.query.filter(PackageBase.Name.like(f"%{keywords}%"))
+
return self
def _search_by_exact_pkgbase(self, keywords: str) -> orm.Query:
@@ -112,9 +124,7 @@ class PackageSearch:
def _search_by_keywords(self, keywords: Set[str]) -> orm.Query:
self._join_user()
self._join_keywords()
- self.query = self.query.filter(
- PackageKeyword.Keyword.in_(keywords)
- ).group_by(Package.Name)
+ self.query = self.query.filter(PackageKeyword.Keyword.in_(keywords))
return self
def _search_by_maintainer(self, keywords: str) -> orm.Query:
@@ -130,25 +140,20 @@ class PackageSearch:
def _search_by_comaintainer(self, keywords: str) -> orm.Query:
self._join_user()
+ self._join_comaint()
user = db.query(User).filter(User.Username == keywords).first()
uid = 0 if not user else user.ID
- self.query = self.query.join(
- PackageComaintainer,
- PackageComaintainer.PackageBaseID == PackageBase.ID
- ).filter(PackageComaintainer.UsersID == uid)
+ self.query = self.query.filter(PackageComaintainer.UsersID == uid)
return self
def _search_by_co_or_maintainer(self, keywords: str) -> orm.Query:
self._join_user()
-
+ self._join_comaint(True)
user = db.query(User).filter(User.Username == keywords).first()
uid = 0 if not user else user.ID
- self.query = self.query.join(
- PackageComaintainer,
- PackageComaintainer.PackageBaseID == PackageBase.ID,
- isouter=True
- ).filter(or_(PackageComaintainer.UsersID == uid, User.ID == uid))
-
+ self.query = self.query.filter(
+ or_(PackageComaintainer.UsersID == uid, User.ID == uid)
+ )
return self
def _search_by_submitter(self, keywords: str) -> orm.Query:
@@ -323,4 +328,6 @@ class RPCSearch(PackageSearch):
return result
def results(self) -> orm.Query:
- return self.query.filter(models.PackageBase.PackagerUID.isnot(None))
+ return self.query.filter(
+ models.PackageBase.PackagerUID.isnot(None)
+ )
diff --git a/aurweb/routers/packages.py b/aurweb/routers/packages.py
index c2a4a49c..95e934ea 100644
--- a/aurweb/routers/packages.py
+++ b/aurweb/routers/packages.py
@@ -113,7 +113,7 @@ async def packages_get(request: Request, context: Dict[str, Any],
models.User.Username.label("Maintainer"),
models.PackageVote.PackageBaseID.label("Voted"),
models.PackageNotification.PackageBaseID.label("Notify")
- )
+ ).group_by(models.Package.Name)
packages = results.limit(per_page).offset(offset)
context["packages"] = packages
From 660d57340ac5185b1cdfd0d34869688892aba0df Mon Sep 17 00:00:00 2001
From: Kevin Morris
Date: Mon, 7 Feb 2022 18:03:43 -0800
Subject: [PATCH 021/481] fix: TUVote inner join TUVoteInfo for "Last Votes by
TU" listing
By implicitly joining, sqlalchemy joined on
`TUVote.UsersID = TUVoteInfo.SubmitterID`. This should be joining on
`TUVote.VoteID = TUVoteInfo.ID` instead to include all TUVote instances
found in the database.
Closes #266
Signed-off-by: Kevin Morris
---
aurweb/routers/trusted_user.py | 11 ++++++-----
test/test_trusted_user_routes.py | 29 ++++++++++++++++++++++-------
2 files changed, 28 insertions(+), 12 deletions(-)
diff --git a/aurweb/routers/trusted_user.py b/aurweb/routers/trusted_user.py
index e9ad2ce2..71f0e932 100644
--- a/aurweb/routers/trusted_user.py
+++ b/aurweb/routers/trusted_user.py
@@ -81,17 +81,18 @@ async def trusted_user(request: Request,
context["past_off"] = past_off
last_vote = func.max(models.TUVote.VoteID).label("LastVote")
- last_votes_by_tu = db.query(models.TUVote).join(
- models.User
- ).join(models.TUVoteInfo).filter(
+ last_votes_by_tu = db.query(models.TUVote).join(models.User).join(
+ models.TUVoteInfo,
+ models.TUVoteInfo.ID == models.TUVote.VoteID
+ ).filter(
and_(models.TUVote.VoteID == models.TUVoteInfo.ID,
models.User.ID == models.TUVote.UserID,
- models.TUVoteInfo.End <= ts,
+ models.TUVoteInfo.End < ts,
or_(models.User.AccountTypeID == 2,
models.User.AccountTypeID == 4))
).with_entities(
models.TUVote.UserID,
- func.max(models.TUVote.VoteID).label("LastVote"),
+ last_vote,
models.User.Username
).group_by(models.TUVote.UserID).order_by(
last_vote.desc(), models.User.Username.asc())
diff --git a/test/test_trusted_user_routes.py b/test/test_trusted_user_routes.py
index a448c043..e2bf6497 100644
--- a/test/test_trusted_user_routes.py
+++ b/test/test_trusted_user_routes.py
@@ -10,7 +10,7 @@ import pytest
from fastapi.testclient import TestClient
from aurweb import config, db, filters, time
-from aurweb.models.account_type import DEVELOPER_ID, AccountType
+from aurweb.models.account_type import DEVELOPER_ID, TRUSTED_USER_ID, AccountType
from aurweb.models.tu_vote import TUVote
from aurweb.models.tu_voteinfo import TUVoteInfo
from aurweb.models.user import User
@@ -97,6 +97,16 @@ def tu_user():
yield tu_user
+@pytest.fixture
+def tu_user2():
+ with db.begin():
+ tu_user2 = db.create(User, Username="test_tu2",
+ Email="test_tu2@example.org",
+ RealName="Test TU 2", Passwd="testPassword",
+ AccountTypeID=TRUSTED_USER_ID)
+ yield tu_user2
+
+
@pytest.fixture
def user():
user_type = db.query(AccountType,
@@ -435,7 +445,8 @@ def test_tu_index_sorting(client, tu_user):
])
-def test_tu_index_last_votes(client, tu_user, user):
+def test_tu_index_last_votes(client: TestClient, tu_user: User, tu_user2: User,
+ user: User):
ts = time.utcnow()
with db.begin():
@@ -445,12 +456,14 @@ def test_tu_index_last_votes(client, tu_user, user):
Submitted=(ts - 1000),
End=(ts - 5),
Yes=1,
+ No=1,
ActiveTUs=1,
Quorum=0.0,
Submitter=tu_user)
# Create a vote on it from tu_user.
db.create(TUVote, VoteInfo=voteinfo, User=tu_user)
+ db.create(TUVote, VoteInfo=voteinfo, User=tu_user2)
# Now, check that tu_user got populated in the .last-votes table.
cookies = {"AURSID": tu_user.login(Request(), "testPassword")}
@@ -461,16 +474,18 @@ def test_tu_index_last_votes(client, tu_user, user):
root = parse_root(response.text)
table = get_table(root, "last-votes")
rows = get_table_rows(table)
- assert len(rows) == 1
+ assert len(rows) == 2
last_vote = rows[0]
- user, vote_id = last_vote.xpath("./td")
- user = user.xpath("./a")[0]
- vote_id = vote_id.xpath("./a")[0]
-
+ user, vote_id = last_vote.xpath("./td/a")
assert user.text.strip() == tu_user.Username
assert int(vote_id.text.strip()) == voteinfo.ID
+ last_vote = rows[1]
+ user, vote_id = last_vote.xpath("./td/a")
+ assert int(vote_id.text.strip()) == voteinfo.ID
+ assert user.text.strip() == tu_user2.Username
+
def test_tu_proposal_not_found(client, tu_user):
cookies = {"AURSID": tu_user.login(Request(), "testPassword")}
From 4c14a10b916635953599c6522e0da28399ba2393 Mon Sep 17 00:00:00 2001
From: Kevin Morris
Date: Tue, 8 Feb 2022 07:50:15 -0800
Subject: [PATCH 022/481] fix: support multiple SSHPubKey records per user
There was one blazing issue with the previous implementation regardless
of the multiple records: we were generating fingerprints by storing
the key into a file and reading it with ssh-keygen. This is absolutely
terrible and was not meant to be left around (it was forgotten, my bad).
Took this opportunity to clean up a few things:
- simplify pubkey validation
- centralize things a bit better
Signed-off-by: Kevin Morris
---
aurweb/models/ssh_pub_key.py | 30 ++++-----------
aurweb/routers/accounts.py | 30 ++++++++-------
aurweb/users/update.py | 56 +++++++++++++++-------------
aurweb/users/validate.py | 16 ++++----
aurweb/util.py | 49 +++++++++++++-----------
templates/partials/account_form.html | 2 +-
test/test_accounts_routes.py | 21 +++++------
test/test_adduser.py | 2 +-
test/test_ssh_pub_key.py | 10 ++++-
test/test_user.py | 4 +-
test/test_util.py | 50 +++++++++++++++++++++++++
11 files changed, 162 insertions(+), 108 deletions(-)
diff --git a/aurweb/models/ssh_pub_key.py b/aurweb/models/ssh_pub_key.py
index 789be629..53c8c3ac 100644
--- a/aurweb/models/ssh_pub_key.py
+++ b/aurweb/models/ssh_pub_key.py
@@ -1,6 +1,3 @@
-import os
-import tempfile
-
from subprocess import PIPE, Popen
from sqlalchemy.orm import backref, relationship
@@ -15,28 +12,17 @@ class SSHPubKey(Base):
__mapper_args__ = {"primary_key": [__table__.c.Fingerprint]}
User = relationship(
- "User", backref=backref("ssh_pub_key", uselist=False),
+ "User", backref=backref("ssh_pub_keys", lazy="dynamic"),
foreign_keys=[__table__.c.UserID])
def __init__(self, **kwargs):
super().__init__(**kwargs)
-def get_fingerprint(pubkey):
- with tempfile.TemporaryDirectory() as tmpdir:
- pk = os.path.join(tmpdir, "ssh.pub")
-
- with open(pk, "w") as f:
- f.write(pubkey)
-
- proc = Popen(["ssh-keygen", "-l", "-f", pk], stdout=PIPE, stderr=PIPE)
- out, err = proc.communicate()
-
- # Invalid SSH Public Key. Return None to the caller.
- if proc.returncode != 0:
- return None
-
- parts = out.decode().split()
- fp = parts[1].replace("SHA256:", "")
-
- return fp
+def get_fingerprint(pubkey: str) -> str:
+ proc = Popen(["ssh-keygen", "-l", "-f", "-"], stdin=PIPE, stdout=PIPE,
+ stderr=PIPE)
+ out, _ = proc.communicate(pubkey.encode())
+ if proc.returncode:
+ raise ValueError("The SSH public key is invalid.")
+ return out.decode().split()[1].split(":", 1)[1]
diff --git a/aurweb/routers/accounts.py b/aurweb/routers/accounts.py
index d1b9d428..36ac48d2 100644
--- a/aurweb/routers/accounts.py
+++ b/aurweb/routers/accounts.py
@@ -2,6 +2,7 @@ import copy
import typing
from http import HTTPStatus
+from typing import Any, Dict
from fastapi import APIRouter, Form, Request
from fastapi.responses import HTMLResponse, RedirectResponse
@@ -105,7 +106,8 @@ async def passreset_post(request: Request,
status_code=HTTPStatus.SEE_OTHER)
-def process_account_form(request: Request, user: models.User, args: dict):
+def process_account_form(request: Request, user: models.User,
+ args: Dict[str, Any]):
""" Process an account form. All fields are optional and only checks
requirements in the case they are present.
@@ -193,8 +195,8 @@ def make_account_form_context(context: dict,
context["pgp"] = args.get("K", user.PGPKey or str())
context["lang"] = args.get("L", user.LangPreference)
context["tz"] = args.get("TZ", user.Timezone)
- ssh_pk = user.ssh_pub_key.PubKey if user.ssh_pub_key else str()
- context["ssh_pk"] = args.get("PK", ssh_pk)
+ ssh_pks = [pk.PubKey for pk in user.ssh_pub_keys]
+ context["ssh_pks"] = args.get("PK", ssh_pks)
context["cn"] = args.get("CN", user.CommentNotify)
context["un"] = args.get("UN", user.UpdateNotify)
context["on"] = args.get("ON", user.OwnershipNotify)
@@ -212,7 +214,7 @@ def make_account_form_context(context: dict,
context["pgp"] = args.get("K", str())
context["lang"] = args.get("L", context.get("language"))
context["tz"] = args.get("TZ", context.get("timezone"))
- context["ssh_pk"] = args.get("PK", str())
+ context["ssh_pks"] = args.get("PK", str())
context["cn"] = args.get("CN", True)
context["un"] = args.get("UN", False)
context["on"] = args.get("ON", True)
@@ -314,16 +316,13 @@ async def account_register_post(request: Request,
# PK mismatches the existing user's SSHPubKey.PubKey.
if PK:
# Get the second element in the PK, which is the actual key.
- pubkey = PK.strip().rstrip()
- parts = pubkey.split(" ")
- if len(parts) == 3:
- # Remove the host part.
- pubkey = parts[0] + " " + parts[1]
- fingerprint = get_fingerprint(pubkey)
- with db.begin():
- user.ssh_pub_key = models.SSHPubKey(UserID=user.ID,
- PubKey=pubkey,
- Fingerprint=fingerprint)
+ keys = util.parse_ssh_keys(PK.strip())
+ for k in keys:
+ pk = " ".join(k)
+ fprint = get_fingerprint(pk)
+ with db.begin():
+ db.create(models.SSHPubKey, UserID=user.ID,
+ PubKey=pk, Fingerprint=fprint)
# Send a reset key notification to the new user.
WelcomeNotification(user.ID).send()
@@ -409,6 +408,9 @@ async def account_edit_post(request: Request,
context = make_account_form_context(context, request, user, args)
ok, errors = process_account_form(request, user, args)
+ if PK:
+ context["ssh_pks"] = [PK]
+
if not passwd:
context["errors"] = ["Invalid password."]
return render_template(request, "account/edit.html", context,
diff --git a/aurweb/users/update.py b/aurweb/users/update.py
index 685dfd80..8e42765e 100644
--- a/aurweb/users/update.py
+++ b/aurweb/users/update.py
@@ -2,7 +2,8 @@ from typing import Any, Dict
from fastapi import Request
-from aurweb import cookies, db, models, time
+from aurweb import cookies, db, models, time, util
+from aurweb.models import SSHPubKey
from aurweb.models.ssh_pub_key import get_fingerprint
from aurweb.util import strtobool
@@ -52,32 +53,35 @@ def timezone(TZ: str = str(),
context["language"] = TZ
-def ssh_pubkey(PK: str = str(),
- user: models.User = None,
- **kwargs) -> None:
- # If a PK is given, compare it against the target user's PK.
- if PK:
- # Get the second token in the public key, which is the actual key.
- pubkey = PK.strip().rstrip()
- parts = pubkey.split(" ")
- if len(parts) == 3:
- # Remove the host part.
- pubkey = parts[0] + " " + parts[1]
- fingerprint = get_fingerprint(pubkey)
- if not user.ssh_pub_key:
- # No public key exists, create one.
- with db.begin():
- db.create(models.SSHPubKey, UserID=user.ID,
- PubKey=pubkey, Fingerprint=fingerprint)
- elif user.ssh_pub_key.PubKey != pubkey:
- # A public key already exists, update it.
- with db.begin():
- user.ssh_pub_key.PubKey = pubkey
- user.ssh_pub_key.Fingerprint = fingerprint
- elif user.ssh_pub_key:
- # Else, if the user has a public key already, delete it.
+def ssh_pubkey(PK: str = str(), user: models.User = None, **kwargs) -> None:
+ if not PK:
+ # If no pubkey is provided, wipe out any pubkeys the user
+ # has and return out early.
with db.begin():
- db.delete(user.ssh_pub_key)
+ db.delete_all(user.ssh_pub_keys)
+ return
+
+ # Otherwise, parse ssh keys and their fprints out of PK.
+ keys = util.parse_ssh_keys(PK.strip())
+ fprints = [get_fingerprint(" ".join(k)) for k in keys]
+
+ with db.begin():
+ # Delete any existing keys we can't find.
+ to_remove = user.ssh_pub_keys.filter(
+ ~SSHPubKey.Fingerprint.in_(fprints))
+ db.delete_all(to_remove)
+
+ # For each key, if it does not yet exist, create it.
+ for i, full_key in enumerate(keys):
+ prefix, key = full_key
+ exists = user.ssh_pub_keys.filter(
+ SSHPubKey.Fingerprint == fprints[i]
+ ).exists()
+ if not db.query(exists).scalar():
+ # No public key exists, create one.
+ db.create(models.SSHPubKey, UserID=user.ID,
+ PubKey=" ".join([prefix, key]),
+ Fingerprint=fprints[i])
def account_type(T: int = None,
diff --git a/aurweb/users/validate.py b/aurweb/users/validate.py
index bbd6082a..26f6eec6 100644
--- a/aurweb/users/validate.py
+++ b/aurweb/users/validate.py
@@ -107,14 +107,16 @@ def invalid_pgp_key(K: str = str(), **kwargs) -> None:
def invalid_ssh_pubkey(PK: str = str(), user: models.User = None,
_: l10n.Translator = None, **kwargs) -> None:
- if PK:
- invalid_exc = ValidationError(["The SSH public key is invalid."])
- if not util.valid_ssh_pubkey(PK):
- raise invalid_exc
+ if not PK:
+ return
- fingerprint = get_fingerprint(PK.strip().rstrip())
- if not fingerprint:
- raise invalid_exc
+ try:
+ keys = util.parse_ssh_keys(PK.strip())
+ except ValueError as exc:
+ raise ValidationError([str(exc)])
+
+ for prefix, key in keys:
+ fingerprint = get_fingerprint(f"{prefix} {key}")
exists = db.query(models.SSHPubKey).filter(
and_(models.SSHPubKey.UserID != user.ID,
diff --git a/aurweb/util.py b/aurweb/util.py
index 7ed4d1d3..6759794f 100644
--- a/aurweb/util.py
+++ b/aurweb/util.py
@@ -1,4 +1,3 @@
-import base64
import math
import re
import secrets
@@ -7,7 +6,8 @@ import string
from datetime import datetime
from distutils.util import strtobool as _strtobool
from http import HTTPStatus
-from typing import Callable, Iterable, Tuple, Union
+from subprocess import PIPE, Popen
+from typing import Callable, Iterable, List, Tuple, Union
from urllib.parse import urlparse
import fastapi
@@ -82,25 +82,6 @@ def valid_pgp_fingerprint(fp):
return len(fp) == 40
-def valid_ssh_pubkey(pk):
- valid_prefixes = aurweb.config.get("auth", "valid-keytypes")
- valid_prefixes = set(valid_prefixes.split(" "))
-
- has_valid_prefix = False
- for prefix in valid_prefixes:
- if "%s " % prefix in pk:
- has_valid_prefix = True
- break
- if not has_valid_prefix:
- return False
-
- tokens = pk.strip().rstrip().split(" ")
- if len(tokens) < 2:
- return False
-
- return base64.b64encode(base64.b64decode(tokens[1])).decode() == tokens[1]
-
-
def jsonify(obj):
""" Perform a conversion on obj if it's needed. """
if isinstance(obj, datetime):
@@ -191,3 +172,29 @@ async def error_or_result(next: Callable, *args, **kwargs) \
status_code = HTTPStatus.INTERNAL_SERVER_ERROR
return JSONResponse({"error": str(exc)}, status_code=status_code)
return response
+
+
+def parse_ssh_key(string: str) -> Tuple[str, str]:
+ """ Parse an SSH public key. """
+ invalid_exc = ValueError("The SSH public key is invalid.")
+ parts = re.sub(r'\s\s+', ' ', string.strip()).split()
+ if len(parts) < 2:
+ raise invalid_exc
+
+ prefix, key = parts[:2]
+ prefixes = set(aurweb.config.get("auth", "valid-keytypes").split(" "))
+ if prefix not in prefixes:
+ raise invalid_exc
+
+ proc = Popen(["ssh-keygen", "-l", "-f", "-"], stdin=PIPE, stdout=PIPE,
+ stderr=PIPE)
+ out, _ = proc.communicate(f"{prefix} {key}".encode())
+ if proc.returncode:
+ raise invalid_exc
+
+ return (prefix, key)
+
+
+def parse_ssh_keys(string: str) -> List[Tuple[str, str]]:
+ """ Parse a list of SSH public keys. """
+ return [parse_ssh_key(e) for e in string.splitlines()]
diff --git a/templates/partials/account_form.html b/templates/partials/account_form.html
index 9136ee7a..007fb389 100644
--- a/templates/partials/account_form.html
+++ b/templates/partials/account_form.html
@@ -262,7 +262,7 @@
+ rows="5" cols="30">{{ ssh_pks | join("\n") }}
diff --git a/test/test_accounts_routes.py b/test/test_accounts_routes.py
index 92b33730..e532e341 100644
--- a/test/test_accounts_routes.py
+++ b/test/test_accounts_routes.py
@@ -577,10 +577,13 @@ def test_post_register_error_ssh_pubkey_taken(client: TestClient, user: User):
# Read in the public key, then delete the temp dir we made.
pk = open(f"{tmpdir}/test.ssh.pub").read().rstrip()
+ prefix, key, loc = pk.split()
+ norm_pk = prefix + " " + key
+
# Take the sha256 fingerprint of the ssh public key, create it.
- fp = get_fingerprint(pk)
+ fp = get_fingerprint(norm_pk)
with db.begin():
- create(SSHPubKey, UserID=user.ID, PubKey=pk, Fingerprint=fp)
+ create(SSHPubKey, UserID=user.ID, PubKey=norm_pk, Fingerprint=fp)
with client as request:
response = post_register(request, PK=pk)
@@ -1080,22 +1083,16 @@ def test_post_account_edit_missing_ssh_pubkey(client: TestClient, user: User):
def test_post_account_edit_invalid_ssh_pubkey(client: TestClient, user: User):
pubkey = "ssh-rsa fake key"
- request = Request()
- sid = user.login(request, "testPassword")
-
- post_data = {
+ data = {
"U": "test",
"E": "test@example.org",
- "P": "newPassword",
- "C": "newPassword",
"PK": pubkey,
"passwd": "testPassword"
}
-
+ cookies = {"AURSID": user.login(Request(), "testPassword")}
with client as request:
- response = request.post("/account/test/edit", cookies={
- "AURSID": sid
- }, data=post_data, allow_redirects=False)
+ response = request.post("/account/test/edit", data=data,
+ cookies=cookies, allow_redirects=False)
assert response.status_code == int(HTTPStatus.BAD_REQUEST)
diff --git a/test/test_adduser.py b/test/test_adduser.py
index 6c71a519..c6210e74 100644
--- a/test/test_adduser.py
+++ b/test/test_adduser.py
@@ -53,4 +53,4 @@ def test_adduser_ssh_pk():
"--ssh-pubkey", TEST_SSH_PUBKEY])
test = db.query(User).filter(User.Username == "test").first()
assert test is not None
- assert TEST_SSH_PUBKEY.startswith(test.ssh_pub_key.PubKey)
+ assert TEST_SSH_PUBKEY.startswith(test.ssh_pub_keys.first().PubKey)
diff --git a/test/test_ssh_pub_key.py b/test/test_ssh_pub_key.py
index 68b6e7a0..93298a11 100644
--- a/test/test_ssh_pub_key.py
+++ b/test/test_ssh_pub_key.py
@@ -1,3 +1,5 @@
+from subprocess import PIPE, Popen
+
import pytest
from aurweb import db
@@ -61,8 +63,12 @@ def test_pubkey_cs(user: User):
def test_pubkey_fingerprint():
- assert get_fingerprint(TEST_SSH_PUBKEY) is not None
+ proc = Popen(["ssh-keygen", "-l", "-f", "-"], stdin=PIPE, stdout=PIPE)
+ out, _ = proc.communicate(TEST_SSH_PUBKEY.encode())
+ expected = out.decode().split()[1].split(":", 1)[1]
+ assert get_fingerprint(TEST_SSH_PUBKEY) == expected
def test_pubkey_invalid_fingerprint():
- assert get_fingerprint("ssh-rsa fake and invalid") is None
+ with pytest.raises(ValueError):
+ get_fingerprint("invalid-prefix some-fake-content")
diff --git a/test/test_user.py b/test/test_user.py
index 7871cd61..5f25f3c9 100644
--- a/test/test_user.py
+++ b/test/test_user.py
@@ -183,14 +183,14 @@ def test_user_has_credential(user: User):
def test_user_ssh_pub_key(user: User):
- assert user.ssh_pub_key is None
+ assert user.ssh_pub_keys.first() is None
with db.begin():
ssh_pub_key = db.create(SSHPubKey, UserID=user.ID,
Fingerprint="testFingerprint",
PubKey="testPubKey")
- assert user.ssh_pub_key == ssh_pub_key
+ assert user.ssh_pub_keys.first() == ssh_pub_key
def test_user_credential_types(user: User):
diff --git a/test/test_util.py b/test/test_util.py
index 51d978fb..ae1de81b 100644
--- a/test/test_util.py
+++ b/test/test_util.py
@@ -60,3 +60,53 @@ def test_valid_homepage():
assert not util.valid_homepage("https://[google.com/broken-ipv6")
assert not util.valid_homepage("gopher://gopher.hprc.utoronto.ca/")
+
+
+def test_parse_ssh_key():
+ # Test a valid key.
+ pk = """ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyN\
+TYAAABBBEURnkiY6JoLyqDE8Li1XuAW+LHmkmLDMW/GL5wY7k4/A+Ta7bjA3MOKrF9j4EuUTvCuNX\
+ULxvpfSqheTFWZc+g="""
+ prefix, key = util.parse_ssh_key(pk)
+ e_prefix, e_key = pk.split()
+ assert prefix == e_prefix
+ assert key == e_key
+
+ # Test an invalid key with just one word in it.
+ with pytest.raises(ValueError):
+ util.parse_ssh_key("ssh-rsa")
+
+ # Test a valid key with extra words in it (after the PK).
+ pk = pk + " blah blah"
+ prefix, key = util.parse_ssh_key(pk)
+ assert prefix == e_prefix
+ assert key == e_key
+
+ # Test an invalid prefix.
+ with pytest.raises(ValueError):
+ util.parse_ssh_key("invalid-prefix fake-content")
+
+
+def test_parse_ssh_keys():
+ pks = """ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyN\
+TYAAABBBEURnkiY6JoLyqDE8Li1XuAW+LHmkmLDMW/GL5wY7k4/A+Ta7bjA3MOKrF9j4EuUTvCuNX\
+ULxvpfSqheTFWZc+g=
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDmqEapFMh/ajPHnm1dBweYPeLOUjC0Ydp6uw7rB\
+S5KCggUVQR8WfIm+sRYTj2+smGsK6zHMBjFnbzvV11vnMqcnY+Sa4LhIAdwkbt/b8HlGaLj1hCWSh\
+a5b5/noeK7L+CECGHdvfJhpxBbhq38YEdFnCGbslk/4NriNcUp/DO81CXb1RzJ9GBFH8ivPW1mbe9\
+YbxDwGimZZslg0OZu9UzoAT6xEGyiZsqJkTMbRp1ZYIOv9jHCJxRuxxuN3fzxyT3xE69+vhq2/NJX\
+8aRsxGPL9G/XKcaYGS6y6LW4quIBCz/XsTZfx1GmkQeZPYHH8FeE+XC/+toXL/kamxdOQKFYEEpWK\
+vTNJCD6JtMClxbIXW9q74nNqG+2SD/VQNMUz/505TK1PbY/4uyFfq5HquHJXQVCBll03FRerNHH2N\
+schFne6BFHpa48PCoZNH45wLjFXwUyrGU1HrNqh6ZPdRfBTrTOkgs+BKBxGNeV45aYUPu/cFBSPcB\
+fRSo6OFcejKc="""
+ keys = util.parse_ssh_keys(pks)
+ assert len(keys) == 2
+
+ pfx1, key1, pfx2, key2 = pks.split()
+ k1, k2 = keys
+
+ assert pfx1 == k1[0]
+ assert key1 == k1[1]
+
+ assert pfx2 == k2[0]
+ assert key2 == k2[1]
From 95bbdfc3bb84e1d175f558d8dd01d45131a95126 Mon Sep 17 00:00:00 2001
From: Kevin Morris
Date: Tue, 8 Feb 2022 09:13:47 -0800
Subject: [PATCH 023/481] upgrade: bump to v6.0.8
Signed-off-by: Kevin Morris
---
aurweb/config.py | 2 +-
pyproject.toml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/aurweb/config.py b/aurweb/config.py
index b154fe30..4d54e788 100644
--- a/aurweb/config.py
+++ b/aurweb/config.py
@@ -6,7 +6,7 @@ from typing import Any
# Publicly visible version of aurweb. This is used to display
# aurweb versioning in the footer and must be maintained.
# Todo: Make this dynamic/automated.
-AURWEB_VERSION = "v6.0.7"
+AURWEB_VERSION = "v6.0.8"
_parser = None
diff --git a/pyproject.toml b/pyproject.toml
index 9e14b8e3..11d4402e 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -8,7 +8,7 @@
#
[tool.poetry]
name = "aurweb"
-version = "v6.0.7"
+version = "v6.0.8"
license = "GPL-2.0-only"
description = "Source code for the Arch User Repository's website"
homepage = "https://aur.archlinux.org"
From 477e814cd81c605c59b5bc1ee38f5de49a2c812a Mon Sep 17 00:00:00 2001
From: Kevin Morris
Date: Tue, 8 Feb 2022 09:27:06 -0800
Subject: [PATCH 024/481] change: set git-cliff's output format to asciidoc
style
we'll be using git-cliff to produce changelogs for new tags from
now on. we want to include these changelogs within the tag body
without markdown.
Signed-off-by: Kevin Morris
---
cliff.toml | 43 ++++++++-----------------------------------
1 file changed, 8 insertions(+), 35 deletions(-)
diff --git a/cliff.toml b/cliff.toml
index 6ee495a3..173beefc 100644
--- a/cliff.toml
+++ b/cliff.toml
@@ -2,52 +2,25 @@
[changelog]
# changelog header
-header = """
-# Changelog
-All notable feature additions, bug fixes and changes to this project will be \
-documented in this file.\n
-"""
+header = ""
# template for the changelog body
# https://tera.netlify.app/docs/#introduction
body = """
{% if version %}\
- #### Release [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}
-{% else %}\
- {% set head = commits | last %}\
- | Branch | HEAD | Status | Coverage |
- |--------|------|--------|----------|
- | [pu](https://gitlab.archlinux.org/archlinux/aurweb/-/tree/pu) | [{{ head.id | truncate(length=8, end="") }}](https://gitlab.archlinux.org/archlinux/aurweb/-/commits/{{ head.id }}) |  |  |
+Release {{ version }} - {{ timestamp | date(format="%Y-%m-%d") }}
+---------------------------
{% endif %}\
{% for group, commits in commits | group_by(attribute="group") %}
- ### {{ group | lower }}
- | Commit | Message |
- |--------|---------| \
- {% for commit in commits %}
- | [{{ commit.id | truncate(length=8, end="") }}](https://gitlab.archlinux.org/archlinux/aurweb/-/commit/{{ commit.id }}) | {{ commit.message }} |\
- {% endfor %}
+{{ group | lower }}:\
+{% for commit in commits %}
+- {{ commit.id | truncate(length=8, end="") }} - {{ commit.message }}\
+{% endfor %}
{% endfor %}\n
"""
# remove the leading and trailing whitespaces from the template
trim = true
# changelog footer
-footer = """
-## Notes
-
-See a general project status overview at \
-https://gitlab.archlinux.org/archlinux/aurweb/-/wikis/Home.
-
-To contribute with testing of the modern aurweb FastAPI port development, visit \
-https://gitlab.archlinux.org/archlinux/aurweb/-/wikis/Testing-Guide.
-
-To file a bug, create an issue using the Bug template by following the link: \
-https://gitlab.archlinux.org/archlinux/aurweb/-/issues/new?issuable_template=Bug.
-
-To provide feedback, create an issue using the Feedback template by following
-the link: \
-https://gitlab.archlinux.org/archlinux/aurweb/-/issues/new?issuable_template=Feedback.
-
-
-"""
+footer = ""
[git]
# allow only conventional commits
From a21c48afe7f48bd87a18ebe21cc1cd119a67f74c Mon Sep 17 00:00:00 2001
From: Kevin Morris
Date: Tue, 8 Feb 2022 09:32:46 -0800
Subject: [PATCH 025/481] change: format git-cliff commit hashes a bit better
Use a ':' instead of a '-' to separate commit hash from message
Signed-off-by: Kevin Morris
---
cliff.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cliff.toml b/cliff.toml
index 173beefc..bc09935b 100644
--- a/cliff.toml
+++ b/cliff.toml
@@ -13,7 +13,7 @@ Release {{ version }} - {{ timestamp | date(format="%Y-%m-%d") }}
{% for group, commits in commits | group_by(attribute="group") %}
{{ group | lower }}:\
{% for commit in commits %}
-- {{ commit.id | truncate(length=8, end="") }} - {{ commit.message }}\
+- {{ commit.id | truncate(length=8, end="") }}: {{ commit.message }}\
{% endfor %}
{% endfor %}\n
"""
From 310484a8cc0c2c728aa11e234668697ccbefc191 Mon Sep 17 00:00:00 2001
From: Kevin Morris
Date: Tue, 8 Feb 2022 09:39:14 -0800
Subject: [PATCH 026/481] change: display git-cliff's commit scope
Signed-off-by: Kevin Morris
---
cliff.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cliff.toml b/cliff.toml
index bc09935b..4d65fd3a 100644
--- a/cliff.toml
+++ b/cliff.toml
@@ -13,7 +13,7 @@ Release {{ version }} - {{ timestamp | date(format="%Y-%m-%d") }}
{% for group, commits in commits | group_by(attribute="group") %}
{{ group | lower }}:\
{% for commit in commits %}
-- {{ commit.id | truncate(length=8, end="") }}: {{ commit.message }}\
+- {{ commit.id | truncate(length=8, end="") }}: {% if commit.scope %}({{ commit.scope }}) {% endif %}{{ commit.message }}\
{% endfor %}
{% endfor %}\n
"""
From bf0623d8c76d0ccfc5e516b4fe235ec69bd15f5c Mon Sep 17 00:00:00 2001
From: Kevin Morris
Date: Tue, 8 Feb 2022 09:43:07 -0800
Subject: [PATCH 027/481] change(git-cliff): include a header for untagged
cliffs
Signed-off-by: Kevin Morris
---
cliff.toml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/cliff.toml b/cliff.toml
index 4d65fd3a..fba14d28 100644
--- a/cliff.toml
+++ b/cliff.toml
@@ -9,6 +9,9 @@ body = """
{% if version %}\
Release {{ version }} - {{ timestamp | date(format="%Y-%m-%d") }}
---------------------------
+{% else %}\
+Changelog (untagged)
+---------------------------
{% endif %}\
{% for group, commits in commits | group_by(attribute="group") %}
{{ group | lower }}:\
From d79d7bdd1e74907580fb7c5b5b6d22533b783c2e Mon Sep 17 00:00:00 2001
From: Leonidas Spyropoulos
Date: Tue, 8 Feb 2022 17:51:07 +0000
Subject: [PATCH 028/481] docs: update issues url to gitlab
Signed-off-by: Leonidas Spyropoulos
---
README.md | 2 +-
po/Makefile | 2 +-
po/ar.po | 2 +-
po/ast.po | 2 +-
po/aurweb.pot | 2 +-
po/az.po | 2 +-
po/az_AZ.po | 2 +-
po/bg.po | 2 +-
po/ca.po | 2 +-
po/ca_ES.po | 2 +-
po/cs.po | 2 +-
po/da.po | 2 +-
po/de.po | 2 +-
po/el.po | 2 +-
po/es.po | 2 +-
po/es_419.po | 2 +-
po/et.po | 2 +-
po/fi.po | 2 +-
po/fi_FI.po | 2 +-
po/fr.po | 2 +-
po/he.po | 2 +-
po/hi_IN.po | 2 +-
po/hr.po | 2 +-
po/hu.po | 2 +-
po/id.po | 2 +-
po/id_ID.po | 2 +-
po/is.po | 2 +-
po/it.po | 2 +-
po/ja.po | 2 +-
po/ko.po | 2 +-
po/lt.po | 2 +-
po/nb.po | 2 +-
po/nb_NO.po | 2 +-
po/nl.po | 2 +-
po/pl.po | 2 +-
po/pt.po | 2 +-
po/pt_BR.po | 2 +-
po/pt_PT.po | 2 +-
po/ro.po | 2 +-
po/ru.po | 2 +-
po/sk.po | 2 +-
po/sr.po | 2 +-
po/sr_RS.po | 2 +-
po/sv_SE.po | 2 +-
po/tr.po | 2 +-
po/uk.po | 2 +-
po/vi.po | 2 +-
po/zh.po | 2 +-
po/zh_CN.po | 2 +-
po/zh_TW.po | 2 +-
templates/home.html | 2 +-
templates/partials/footer.html | 1 +
52 files changed, 52 insertions(+), 51 deletions(-)
diff --git a/README.md b/README.md
index 8ebefe13..3f156455 100644
--- a/README.md
+++ b/README.md
@@ -47,7 +47,7 @@ Links
-- see doc/CodingGuidelines for information on the patch submission process.
* Bugs can (and should) be submitted to the aurweb bug tracker:
- https://bugs.archlinux.org/index.php?project=2
+ https://gitlab.archlinux.org/archlinux/aurweb/-/issues/new?issuable_template=Bug
* Questions, comments, and patches related to aurweb can be sent to the AUR
development mailing list: aur-dev@archlinux.org -- mailing list archives:
diff --git a/po/Makefile b/po/Makefile
index 57fa9f77..0b579f48 100644
--- a/po/Makefile
+++ b/po/Makefile
@@ -37,7 +37,7 @@ LOCALES = ${MOFILES:.mo=}
UPDATEPOFILES = ${POFILES:.po=.po-update}
-MSGID_BUGS_ADDRESS = https://bugs.archlinux.org/index.php?project=2
+MSGID_BUGS_ADDRESS = https://gitlab.archlinux.org/archlinux/aurweb/-/issues
all: ${MOFILES}
diff --git a/po/ar.po b/po/ar.po
index 676a5025..ecc8b08f 100644
--- a/po/ar.po
+++ b/po/ar.po
@@ -8,7 +8,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/ast.po b/po/ast.po
index 16c363a6..b23057af 100644
--- a/po/ast.po
+++ b/po/ast.po
@@ -9,7 +9,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2020-03-07 17:55+0000\n"
"Last-Translator: enolp \n"
diff --git a/po/aurweb.pot b/po/aurweb.pot
index afad9e12..bec1b672 100644
--- a/po/aurweb.pot
+++ b/po/aurweb.pot
@@ -7,7 +7,7 @@
msgid ""
msgstr ""
"Project-Id-Version: AURWEB v4.8.0\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
diff --git a/po/az.po b/po/az.po
index 7e534b4c..d426872c 100644
--- a/po/az.po
+++ b/po/az.po
@@ -6,7 +6,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/az_AZ.po b/po/az_AZ.po
index e903027b..9fd3b5bb 100644
--- a/po/az_AZ.po
+++ b/po/az_AZ.po
@@ -6,7 +6,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/bg.po b/po/bg.po
index 7864f5dc..2ceab947 100644
--- a/po/bg.po
+++ b/po/bg.po
@@ -6,7 +6,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/ca.po b/po/ca.po
index 391dd146..accd18a0 100644
--- a/po/ca.po
+++ b/po/ca.po
@@ -10,7 +10,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/ca_ES.po b/po/ca_ES.po
index bad69bd1..ba6c0050 100644
--- a/po/ca_ES.po
+++ b/po/ca_ES.po
@@ -6,7 +6,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/cs.po b/po/cs.po
index b9bd739a..8b44d97a 100644
--- a/po/cs.po
+++ b/po/cs.po
@@ -15,7 +15,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/da.po b/po/da.po
index a6f290ea..84c6a5b8 100644
--- a/po/da.po
+++ b/po/da.po
@@ -9,7 +9,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/de.po b/po/de.po
index ec0a0fbe..07d043ef 100644
--- a/po/de.po
+++ b/po/de.po
@@ -27,7 +27,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/el.po b/po/el.po
index f1fe704e..9851d597 100644
--- a/po/el.po
+++ b/po/el.po
@@ -14,7 +14,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/es.po b/po/es.po
index ea7ac099..690680f7 100644
--- a/po/es.po
+++ b/po/es.po
@@ -18,7 +18,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/es_419.po b/po/es_419.po
index 444eccb7..47c0a835 100644
--- a/po/es_419.po
+++ b/po/es_419.po
@@ -16,7 +16,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2020-01-31 08:29+0000\n"
"Last-Translator: Lukas Fleischer\n"
diff --git a/po/et.po b/po/et.po
index 9b6493b5..f59aa904 100644
--- a/po/et.po
+++ b/po/et.po
@@ -6,7 +6,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/fi.po b/po/fi.po
index 39cfe626..8cc7fed2 100644
--- a/po/fi.po
+++ b/po/fi.po
@@ -10,7 +10,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/fi_FI.po b/po/fi_FI.po
index f3253433..6fbcb185 100644
--- a/po/fi_FI.po
+++ b/po/fi_FI.po
@@ -6,7 +6,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/fr.po b/po/fr.po
index 99d01460..95809e1d 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -18,7 +18,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/he.po b/po/he.po
index cd4a0f87..93efb44f 100644
--- a/po/he.po
+++ b/po/he.po
@@ -9,7 +9,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/hi_IN.po b/po/hi_IN.po
index 37fd082e..6b7b52eb 100644
--- a/po/hi_IN.po
+++ b/po/hi_IN.po
@@ -7,7 +7,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/hr.po b/po/hr.po
index 4932bd7e..d5b69098 100644
--- a/po/hr.po
+++ b/po/hr.po
@@ -7,7 +7,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/hu.po b/po/hu.po
index 51894457..da1d40a6 100644
--- a/po/hu.po
+++ b/po/hu.po
@@ -11,7 +11,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/id.po b/po/id.po
index 75a6c98b..16e9a988 100644
--- a/po/id.po
+++ b/po/id.po
@@ -8,7 +8,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/id_ID.po b/po/id_ID.po
index d01294c8..e50efff9 100644
--- a/po/id_ID.po
+++ b/po/id_ID.po
@@ -6,7 +6,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/is.po b/po/is.po
index a7a88b04..19320cee 100644
--- a/po/is.po
+++ b/po/is.po
@@ -6,7 +6,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/it.po b/po/it.po
index 436b6459..d72396d3 100644
--- a/po/it.po
+++ b/po/it.po
@@ -11,7 +11,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/ja.po b/po/ja.po
index 55d056bf..9ee6116c 100644
--- a/po/ja.po
+++ b/po/ja.po
@@ -10,7 +10,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/ko.po b/po/ko.po
index 808ffe27..96382f8b 100644
--- a/po/ko.po
+++ b/po/ko.po
@@ -6,7 +6,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/lt.po b/po/lt.po
index d126f193..6cb4d946 100644
--- a/po/lt.po
+++ b/po/lt.po
@@ -6,7 +6,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/nb.po b/po/nb.po
index 1cc090f1..e1fa16a0 100644
--- a/po/nb.po
+++ b/po/nb.po
@@ -12,7 +12,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/nb_NO.po b/po/nb_NO.po
index 74af6936..dd909957 100644
--- a/po/nb_NO.po
+++ b/po/nb_NO.po
@@ -8,7 +8,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/nl.po b/po/nl.po
index 282b5b40..3e7c546e 100644
--- a/po/nl.po
+++ b/po/nl.po
@@ -13,7 +13,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/pl.po b/po/pl.po
index 4856f22b..0a52d7cc 100644
--- a/po/pl.po
+++ b/po/pl.po
@@ -19,7 +19,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/pt.po b/po/pt.po
index b2cf86b2..b226ba87 100644
--- a/po/pt.po
+++ b/po/pt.po
@@ -7,7 +7,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/pt_BR.po b/po/pt_BR.po
index c9c15d72..c9deeff7 100644
--- a/po/pt_BR.po
+++ b/po/pt_BR.po
@@ -13,7 +13,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/pt_PT.po b/po/pt_PT.po
index 3518cb7b..d0ed790e 100644
--- a/po/pt_PT.po
+++ b/po/pt_PT.po
@@ -12,7 +12,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/ro.po b/po/ro.po
index fa159928..79826396 100644
--- a/po/ro.po
+++ b/po/ro.po
@@ -9,7 +9,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/ru.po b/po/ru.po
index 75550c8c..7f6efe0f 100644
--- a/po/ru.po
+++ b/po/ru.po
@@ -18,7 +18,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/sk.po b/po/sk.po
index 76d3d1a8..1ea42448 100644
--- a/po/sk.po
+++ b/po/sk.po
@@ -9,7 +9,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/sr.po b/po/sr.po
index dae37bcd..2cc46b04 100644
--- a/po/sr.po
+++ b/po/sr.po
@@ -9,7 +9,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/sr_RS.po b/po/sr_RS.po
index 985ee007..d075b589 100644
--- a/po/sr_RS.po
+++ b/po/sr_RS.po
@@ -7,7 +7,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/sv_SE.po b/po/sv_SE.po
index 6d09e207..24f8bf57 100644
--- a/po/sv_SE.po
+++ b/po/sv_SE.po
@@ -11,7 +11,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/tr.po b/po/tr.po
index 83b1e4df..9e10ec96 100644
--- a/po/tr.po
+++ b/po/tr.po
@@ -15,7 +15,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/uk.po b/po/uk.po
index a4410185..4b369615 100644
--- a/po/uk.po
+++ b/po/uk.po
@@ -12,7 +12,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/vi.po b/po/vi.po
index 3ea5bad3..23ed265d 100644
--- a/po/vi.po
+++ b/po/vi.po
@@ -6,7 +6,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/zh.po b/po/zh.po
index 04fe06f3..02bba19a 100644
--- a/po/zh.po
+++ b/po/zh.po
@@ -6,7 +6,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/zh_CN.po b/po/zh_CN.po
index 53d42bc8..ecc37bb9 100644
--- a/po/zh_CN.po
+++ b/po/zh_CN.po
@@ -17,7 +17,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/po/zh_TW.po b/po/zh_TW.po
index e7399a19..a9611e6f 100644
--- a/po/zh_TW.po
+++ b/po/zh_TW.po
@@ -9,7 +9,7 @@
msgid ""
msgstr ""
"Project-Id-Version: aurweb\n"
-"Report-Msgid-Bugs-To: https://bugs.archlinux.org/index.php?project=2\n"
+"Report-Msgid-Bugs-To: https://gitlab.archlinux.org/archlinux/aurweb/-/issues\n"
"POT-Creation-Date: 2020-01-31 09:29+0100\n"
"PO-Revision-Date: 2022-01-18 17:18+0000\n"
"Last-Translator: Kevin Morris \n"
diff --git a/templates/home.html b/templates/home.html
index a8cae5b8..c1f172f4 100644
--- a/templates/home.html
+++ b/templates/home.html
@@ -83,7 +83,7 @@
{{ "If you find a bug in the AUR web interface, please fill out a bug report on our %sbug tracker%s. Use the tracker to report bugs in the AUR web interface %sonly%s. To report packaging bugs contact the package maintainer or leave a comment on the appropriate package page."
| tr
- | format('', "",
+ | format('', "",
"", "")
| safe
}}
diff --git a/templates/partials/footer.html b/templates/partials/footer.html
index 3103699f..d88c3eb8 100644
--- a/templates/partials/footer.html
+++ b/templates/partials/footer.html
@@ -12,6 +12,7 @@
{% endif %}
{% endif %}