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/aurweb/packages/search.py b/aurweb/packages/search.py index b4af5aab..01b0e154 100644 --- a/aurweb/packages/search.py +++ b/aurweb/packages/search.py @@ -120,24 +120,25 @@ 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: 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: 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/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/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/aurweb/util.py b/aurweb/util.py index 1f75ac22..7ed4d1d3 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 @@ -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. @@ -133,9 +132,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/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:: 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" 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 " 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) }} 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 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"