Build a translation facility for FastAPI

Signed-off-by: Lukas Fleischer <lfleischer@archlinux.org>
This commit is contained in:
Frédéric Mangano-Tarumi 2020-07-20 16:25:28 +02:00 committed by Lukas Fleischer
parent e323156947
commit 239988def7
2 changed files with 33 additions and 9 deletions

View file

@ -16,3 +16,25 @@ class Translator:
self._localedir, self._localedir,
languages=[lang]) languages=[lang])
return self._translator[lang].gettext(s) return self._translator[lang].gettext(s)
def get_translator_for_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 = request.cookies.get("AURLANG")
if lang is None:
lang = aurweb.config.get("options", "default_lang")
translator = Translator()
def translate(message):
return translator.translate(message, lang)
return translate

View file

@ -14,6 +14,7 @@ from starlette.requests import Request
import aurweb.config import aurweb.config
import aurweb.db import aurweb.db
from aurweb.l10n import get_translator_for_request
from aurweb.schema import Bans, Sessions, Users from aurweb.schema import Bans, Sessions, Users
router = fastapi.APIRouter() router = fastapi.APIRouter()
@ -46,13 +47,13 @@ def is_account_suspended(conn, user_id):
return row is not None and bool(row[0]) return row is not None and bool(row[0])
def open_session(conn, user_id): def open_session(request, conn, user_id):
""" """
Create a new user session into the database. Return its SID. Create a new user session into the database. Return its SID.
""" """
# TODO Handle translations.
if is_account_suspended(conn, user_id): if is_account_suspended(conn, user_id):
raise HTTPException(status_code=403, detail='Account suspended') _ = get_translator_for_request(request)
raise HTTPException(status_code=403, detail=_('Account suspended'))
# TODO This is a terrible message because it could imply the attempt at # TODO This is a terrible message because it could imply the attempt at
# logging in just caused the suspension. # logging in just caused the suspension.
# TODO apply [options] max_sessions_per_user # TODO apply [options] max_sessions_per_user
@ -81,25 +82,26 @@ async def authenticate(request: Request, conn=Depends(aurweb.db.connect)):
Receive an OpenID Connect ID token, validate it, then process it to create Receive an OpenID Connect ID token, validate it, then process it to create
an new AUR session. an new AUR session.
""" """
# TODO Handle translations
if is_ip_banned(conn, request.client.host): if is_ip_banned(conn, request.client.host):
_ = get_translator_for_request(request)
raise HTTPException( raise HTTPException(
status_code=403, status_code=403,
detail='The login form is currently disabled for your IP address, ' detail=_('The login form is currently disabled for your IP address, '
'probably due to sustained spam attacks. Sorry for the ' 'probably due to sustained spam attacks. Sorry for the '
'inconvenience.') 'inconvenience.'))
token = await oauth.sso.authorize_access_token(request) token = await oauth.sso.authorize_access_token(request)
user = await oauth.sso.parse_id_token(request, token) user = await oauth.sso.parse_id_token(request, token)
sub = user.get("sub") # this is the SSO account ID in JWT terminology sub = user.get("sub") # this is the SSO account ID in JWT terminology
if not sub: if not sub:
raise HTTPException(status_code=400, detail="JWT is missing its `sub` field.") _ = get_translator_for_request(request)
raise HTTPException(status_code=400, detail=_("JWT is missing its `sub` field."))
aur_accounts = conn.execute(select([Users.c.ID]).where(Users.c.SSOAccountID == sub)) \ aur_accounts = conn.execute(select([Users.c.ID]).where(Users.c.SSOAccountID == sub)) \
.fetchall() .fetchall()
if not aur_accounts: if not aur_accounts:
return "Sorry, we dont seem to know you Sir " + sub return "Sorry, we dont seem to know you Sir " + sub
elif len(aur_accounts) == 1: elif len(aur_accounts) == 1:
sid = open_session(conn, aur_accounts[0][Users.c.ID]) sid = open_session(request, conn, aur_accounts[0][Users.c.ID])
response = RedirectResponse("/") response = RedirectResponse("/")
# TODO redirect to the referrer # TODO redirect to the referrer
response.set_cookie(key="AURSID", value=sid, httponly=True, response.set_cookie(key="AURSID", value=sid, httponly=True,