taler-merchant-demos

Python-based Frontends for the Demonstration Web site
Log | Files | Refs | Submodules | README | LICENSE

commit 103a42647c10a169de6a724b17e8418026f73ebc
parent 1482948f26b0e24d329fbda2b17aeb8ec5129996
Author: Özgür Kesim <oec@codeblau.de>
Date:   Sun, 20 Apr 2025 17:19:07 +0200

[provision] fixed redirect and local issues

Diffstat:
Mtalermerchantdemos/httpcommon/__init__.py | 11+++++++++--
Mtalermerchantdemos/provision/provision.py | 65++++++++++++++++++++++++++++++++++++++++++++++-------------------
2 files changed, 55 insertions(+), 21 deletions(-)

diff --git a/talermerchantdemos/httpcommon/__init__.py b/talermerchantdemos/httpcommon/__init__.py @@ -197,8 +197,12 @@ all_languages = { ## # Make the environment available into templates. # +# @param pagename name of the target app +# @param base_url url of the app +# @param add additional dictionary elements to add or overwrite +# # @return the environment-reading function -def make_utility_processor(pagename, base_url): +def make_utility_processor(pagename, base_url, add=None): def utility_processor(): def getactive(): return pagename @@ -221,7 +225,7 @@ def make_utility_processor(pagename, base_url): def static(name): return flask.url_for("static", filename=name) - return dict( + rd = dict( env=env, prettydate=prettydate, getactive=getactive, @@ -229,5 +233,8 @@ def make_utility_processor(pagename, base_url): all_languages=all_languages, static=static, ) + rd.update(add_dict) + + return rd return utility_processor diff --git a/talermerchantdemos/provision/provision.py b/talermerchantdemos/provision/provision.py @@ -36,7 +36,7 @@ import subprocess import urllib from ..util.talerconfig import TalerConfig, ConfigurationError from urllib.parse import urljoin -from ..httpcommon import backend_post, backend_get, make_utility_processor, get_locale +from ..httpcommon import backend_post, backend_get, make_utility_processor from ..appconfig import load_taler_config import sys @@ -58,11 +58,39 @@ app = flask.Flask(__name__, template_folder="../templates", static_folder="../static", static_url_path="/static") -app.wsgi_app = ProxyFix(app.wsgi_app, x_host=1, x_prefix=1) +app.wsgi_app = ProxyFix(app.wsgi_app, x_host=1) app.debug = True app.secret_key = base64.b64encode(os.urandom(64)).decode("utf-8") app.config.from_object(__name__) +# The path prefix for the provision system, without the leading or trailing "/" +provision_prefix=os.environ.get("TALER_ENV_URL_MERCHANT_PROVISION_PREFIX", "provision") + +# We need a special local handler for this app, +# as our path's have the prefix {provision_prefix} +def get_locale(): + parts = request.path.split("/", 3) + if 3 >= len(parts): + # Totally unexpected path format, do not localize + return "en" + if parts[1] == f"{provision_prefix}": + lang = parts[2] + else: + lang = parts[1] + + # Sanity check on the language code. + try: + babel.core.Locale.parse(lang) + except Exception as err: + # Not a locale, default to english. + LOGGER.error(f"language {lang} did not parse, default to english") + return "en" + if lang == "static": + # Static resource, not a language indicator. + # Do not localize then. + return "en" + return lang + BABEL_TRANSLATION_DIRECTORIES = "../translations" babel = Babel(app) babel.localeselector(get_locale) @@ -98,9 +126,12 @@ LOGGER.info( # Add context processor that will make additional variables # and functions available in the template. +# Overwrite the "getlang" helper from httpcommon with the +# specific one for provision. app.context_processor( make_utility_processor( - "provision", os.environ.get("TALER_ENV_URL_MERCHANT_PROVISION") + "provision", os.environ.get("TALER_ENV_URL_MERCHANT_PROVISION"), + dict(getlang=get_locale) ) ) @@ -153,25 +184,12 @@ def internal_error(e): ) flask.abort(flask.make_response(t, 500)) -## -# Serve the /favicon.ico requests. -# -# @return the favicon.ico file. -@app.route("/favicon.ico") -def favicon(): - LOGGER.info("will look into: " + os.path.join(app.root_path, "static")) - return flask.send_from_directory( - os.path.join(app.root_path, "static"), - "favicon.ico", - mimetype="image/vnd.microsoft.ico", - ) - ## # Serve the main index page, redirecting to /<lang>/ # # @return response object of the index page. -@app.route("/") +@app.route(f"/{provision_prefix}") def index(): default = "en" target = flask.request.accept_languages.best_match(translations, default) @@ -182,8 +200,17 @@ def index(): # Serve the main index page. # # @return response object of the index page. -@app.route("/<lang>/") +@app.route(f"/{provision_prefix}/<lang>/") def start(lang): + # get_locale defaults to english, hence the + # condition below happens only when lang is + # wrong or unsupported, respond 404. + if lang != get_locale(): + err_abort( + 404, + message=f"Language {lang} not found", + ) + return flask.render_template( "provision-index.html.j2", page_title=gettext("GNU Taler Demo: Provision"), @@ -201,7 +228,7 @@ allowed = re.compile("^[a-zA-Z]([a-zA-Z0-9_. -]+)[a-zA-Z0-9][.]?$") # and create a merchant instance and bank account. # # @return response object for the /provision page. -@app.route("/<lang>/create", methods=["POST"]) +@app.route(f"/{provision_prefix}/<lang>/create", methods=["POST"]) def create(lang): fullname = flask.request.form.get("fullname") fullname = fullname.strip(' \t\n\r')