From 9fdbe3f775a3d13e92a02a11e5eb4830e6daf875 Mon Sep 17 00:00:00 2001 From: Kevin Morris Date: Fri, 8 Jan 2021 20:10:45 -0800 Subject: [PATCH] add authenticated User LangPreference tracking + Use User.LangPreference when there is no set AURSID if request.user.is_authenticated is true. + Updated post /language to update LangPreference when request.user.is_authenticated. + Restore language during test where we change it. + Added the user attribute to aurweb.testing.requests.Request. Signed-off-by: Kevin Morris --- aurweb/l10n.py | 12 ++++-------- aurweb/routers/html.py | 11 ++++++++++- aurweb/testing/requests.py | 19 +++++++++++++++++++ test/test_accounts_routes.py | 6 +++++- test/test_routes.py | 25 +++++++++++++++++++++---- 5 files changed, 59 insertions(+), 14 deletions(-) diff --git a/aurweb/l10n.py b/aurweb/l10n.py index 030ab274..4a5c1a46 100644 --- a/aurweb/l10n.py +++ b/aurweb/l10n.py @@ -64,8 +64,10 @@ translator = Translator() def get_request_language(request: Request): - return request.cookies.get("AURLANG", - aurweb.config.get("options", "default_lang")) + if request.user.is_authenticated(): + return request.user.LangPreference + default_lang = aurweb.config.get("options", "default_lang") + return request.cookies.get("AURLANG", default_lang) def get_raw_translator_for_request(request: Request): @@ -77,12 +79,6 @@ def get_translator_for_request(request: Request): """ Determine the preferred language from a FastAPI request object and build a translator function for it. - - Example: - ```python - _ = get_translator_for_request(request) - print(_("Hello")) - ``` """ lang = get_request_language(request) diff --git a/aurweb/routers/html.py b/aurweb/routers/html.py index 32a7e630..e947d213 100644 --- a/aurweb/routers/html.py +++ b/aurweb/routers/html.py @@ -24,12 +24,14 @@ async def language(request: Request, set_lang: str = Form(...), next: str = Form(...), q: str = Form(default=None)): - """ A POST route used to set a session's language. + """ + A POST route used to set a session's language. Return a 303 See Other redirect to {next}?next={next}. If we are setting the language on any page, we want to preserve query parameters across the redirect. """ + from aurweb.db import session from aurweb.asgi import routes if unquote(next) not in routes: return HTMLResponse( @@ -37,6 +39,13 @@ async def language(request: Request, status_code=400) query_string = "?" + q if q else str() + + # If the user is authenticated, update the user's LangPreference. + if request.user.is_authenticated(): + request.user.LangPreference = set_lang + session.commit() + + # In any case, set the response's AURLANG cookie that never expires. response = RedirectResponse(url=f"{next}{query_string}", status_code=int(HTTPStatus.SEE_OTHER)) response.set_cookie("AURLANG", set_lang) diff --git a/aurweb/testing/requests.py b/aurweb/testing/requests.py index 2839c93f..2e64fd3d 100644 --- a/aurweb/testing/requests.py +++ b/aurweb/testing/requests.py @@ -1,8 +1,27 @@ +import aurweb.config + + +class User: + """ A fake User model. """ + # Fake columns. + LangPreference = aurweb.config.get("options", "default_lang") + + # A fake authenticated flag. + authenticated = False + + def is_authenticated(self): + return self.authenticated + + class Client: + """ A fake FastAPI Request.client object. """ + # A fake host. host = "127.0.0.1" class Request: + """ A fake Request object which mimics a FastAPI Request for tests. """ client = Client() cookies = dict() headers = dict() + user = User() diff --git a/test/test_accounts_routes.py b/test/test_accounts_routes.py index 0f548805..69896a0f 100644 --- a/test/test_accounts_routes.py +++ b/test/test_accounts_routes.py @@ -54,7 +54,7 @@ def test_get_passreset(): def test_get_passreset_translation(): - # Test that translation works. + # Test that translation works; set it to de. with client as request: response = request.get("/passreset", cookies={"AURLANG": "de"}) @@ -68,6 +68,10 @@ def test_get_passreset_translation(): # And the button. assert "Weiter".encode("utf-8") in response.content + # Restore english. + with client as request: + response = request.get("/passreset", cookies={"AURLANG": "en"}) + def test_get_passreset_with_resetkey(): with client as request: diff --git a/test/test_routes.py b/test/test_routes.py index 950d9b71..d512a172 100644 --- a/test/test_routes.py +++ b/test/test_routes.py @@ -10,13 +10,14 @@ from aurweb.asgi import app from aurweb.db import query from aurweb.models.account_type import AccountType from aurweb.testing import setup_test_db +from aurweb.testing.models import make_user +from aurweb.testing.requests import Request client = TestClient(app) - user = None -@pytest.fixture +@pytest.fixture(autouse=True) def setup(): global user @@ -46,7 +47,7 @@ def test_favicon(): def test_language(): - """ Test the language post route at '/language'. """ + """ Test the language post route as a guest user. """ post_data = { "set_lang": "de", "next": "/" @@ -67,6 +68,23 @@ def test_language_invalid_next(): assert response.status_code == int(HTTPStatus.BAD_REQUEST) +def test_user_language(): + """ Test the language post route as an authenticated user. """ + post_data = { + "set_lang": "de", + "next": "/" + } + + sid = user.login(Request(), "testPassword") + assert sid is not None + + with client as req: + response = req.post("/language", data=post_data, + cookies={"AURSID": sid}) + assert response.status_code == int(HTTPStatus.SEE_OTHER) + assert user.LangPreference == "de" + + def test_language_query_params(): """ Test the language post route with query params. """ next = urllib.parse.quote_plus("/") @@ -87,4 +105,3 @@ def test_error_messages(): response2 = client.get("/raisefivethree") assert response1.status_code == int(HTTPStatus.NOT_FOUND) assert response2.status_code == int(HTTPStatus.SERVICE_UNAVAILABLE) -