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 <kevr@0cost.org>
This commit is contained in:
Kevin Morris 2021-01-08 20:10:45 -08:00
parent a33d076d8b
commit 9fdbe3f775
5 changed files with 59 additions and 14 deletions

View file

@ -64,8 +64,10 @@ translator = Translator()
def get_request_language(request: Request): def get_request_language(request: Request):
return request.cookies.get("AURLANG", if request.user.is_authenticated():
aurweb.config.get("options", "default_lang")) 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): 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 Determine the preferred language from a FastAPI request object and build a
translator function for it. translator function for it.
Example:
```python
_ = get_translator_for_request(request)
print(_("Hello"))
```
""" """
lang = get_request_language(request) lang = get_request_language(request)

View file

@ -24,12 +24,14 @@ async def language(request: Request,
set_lang: str = Form(...), set_lang: str = Form(...),
next: str = Form(...), next: str = Form(...),
q: str = Form(default=None)): 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 Return a 303 See Other redirect to {next}?next={next}. If we are
setting the language on any page, we want to preserve query setting the language on any page, we want to preserve query
parameters across the redirect. parameters across the redirect.
""" """
from aurweb.db import session
from aurweb.asgi import routes from aurweb.asgi import routes
if unquote(next) not in routes: if unquote(next) not in routes:
return HTMLResponse( return HTMLResponse(
@ -37,6 +39,13 @@ async def language(request: Request,
status_code=400) status_code=400)
query_string = "?" + q if q else str() 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}", response = RedirectResponse(url=f"{next}{query_string}",
status_code=int(HTTPStatus.SEE_OTHER)) status_code=int(HTTPStatus.SEE_OTHER))
response.set_cookie("AURLANG", set_lang) response.set_cookie("AURLANG", set_lang)

View file

@ -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: class Client:
""" A fake FastAPI Request.client object. """
# A fake host.
host = "127.0.0.1" host = "127.0.0.1"
class Request: class Request:
""" A fake Request object which mimics a FastAPI Request for tests. """
client = Client() client = Client()
cookies = dict() cookies = dict()
headers = dict() headers = dict()
user = User()

View file

@ -54,7 +54,7 @@ def test_get_passreset():
def test_get_passreset_translation(): def test_get_passreset_translation():
# Test that translation works. # Test that translation works; set it to de.
with client as request: with client as request:
response = request.get("/passreset", cookies={"AURLANG": "de"}) response = request.get("/passreset", cookies={"AURLANG": "de"})
@ -68,6 +68,10 @@ def test_get_passreset_translation():
# And the button. # And the button.
assert "Weiter".encode("utf-8") in response.content 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(): def test_get_passreset_with_resetkey():
with client as request: with client as request:

View file

@ -10,13 +10,14 @@ from aurweb.asgi import app
from aurweb.db import query from aurweb.db import query
from aurweb.models.account_type import AccountType from aurweb.models.account_type import AccountType
from aurweb.testing import setup_test_db from aurweb.testing import setup_test_db
from aurweb.testing.models import make_user
from aurweb.testing.requests import Request
client = TestClient(app) client = TestClient(app)
user = None user = None
@pytest.fixture @pytest.fixture(autouse=True)
def setup(): def setup():
global user global user
@ -46,7 +47,7 @@ def test_favicon():
def test_language(): def test_language():
""" Test the language post route at '/language'. """ """ Test the language post route as a guest user. """
post_data = { post_data = {
"set_lang": "de", "set_lang": "de",
"next": "/" "next": "/"
@ -67,6 +68,23 @@ def test_language_invalid_next():
assert response.status_code == int(HTTPStatus.BAD_REQUEST) 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(): def test_language_query_params():
""" Test the language post route with query params. """ """ Test the language post route with query params. """
next = urllib.parse.quote_plus("/") next = urllib.parse.quote_plus("/")
@ -87,4 +105,3 @@ def test_error_messages():
response2 = client.get("/raisefivethree") response2 = client.get("/raisefivethree")
assert response1.status_code == int(HTTPStatus.NOT_FOUND) assert response1.status_code == int(HTTPStatus.NOT_FOUND)
assert response2.status_code == int(HTTPStatus.SERVICE_UNAVAILABLE) assert response2.status_code == int(HTTPStatus.SERVICE_UNAVAILABLE)