diff options
author | Christian Grothoff <christian@grothoff.org> | 2020-10-11 17:03:12 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2020-10-11 17:03:12 +0200 |
commit | d69934f816c7e48d758452dd443eca0f02dd14ce (patch) | |
tree | e0b4493cc328b2bbda16a83edf443a697d47957d /talermerchantdemos/landing/landing.py | |
parent | aa06ddd3cf1de03922fc4e45e46ef3476a69e3f8 (diff) | |
download | taler-merchant-demos-d69934f816c7e48d758452dd443eca0f02dd14ce.tar.gz taler-merchant-demos-d69934f816c7e48d758452dd443eca0f02dd14ce.tar.bz2 taler-merchant-demos-d69934f816c7e48d758452dd443eca0f02dd14ce.zip |
add landing subpage, simplify deployment
Diffstat (limited to 'talermerchantdemos/landing/landing.py')
-rw-r--r-- | talermerchantdemos/landing/landing.py | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/talermerchantdemos/landing/landing.py b/talermerchantdemos/landing/landing.py new file mode 100644 index 0000000..6bc4249 --- /dev/null +++ b/talermerchantdemos/landing/landing.py @@ -0,0 +1,164 @@ +## +# This file is part of GNU TALER. +# Copyright (C) 2017, 2020 Taler Systems SA +# +# TALER is free software; you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free Software +# Foundation; either version 2.1, or (at your option) any later version. +# +# TALER is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License along with +# GNU TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> +# +# @author Christian Grothoff +# @brief Minimal Website for the landing page. + +import os +import re +import datetime +import base64 +import logging +from urllib.parse import urljoin +import flask +from flask import request +from flask_babel import Babel +from flask_babel import refresh +from flask_babel import force_locale +from flask_babel import gettext +import traceback +from taler.util.talerconfig import TalerConfig, ConfigurationError +from ..httpcommon import backend_get, backend_post, self_localized +import sys + +if not sys.version_info.major == 3 and sys.version_info.minor >= 6: + print("Python 3.6 or higher is required.") + print("You are using Python {}.{}.".format(sys.version_info.major, sys.version_info.minor)) + sys.exit(1) + +BASE_DIR = os.path.dirname(os.path.abspath(__file__)) +app = flask.Flask(__name__, template_folder=BASE_DIR) +app.debug = True +app.secret_key = base64.b64encode(os.urandom(64)).decode('utf-8') + +LOGGER = logging.getLogger(__name__) +TC = TalerConfig.from_env() +try: + BACKEND_URL = TC["frontends"]["backend"].value_string(required=True) + CURRENCY = TC["taler"]["currency"].value_string(required=True) + APIKEY = TC["frontends"]["backend_apikey"].value_string(required=True) +except ConfigurationError as ce: + print(ce) + exit(1) + +app.config.from_object(__name__) +babel = Babel(app) + +LOGGER.info("Using translations from:" + ':'.join(list(babel.translation_directories))) +translations = [str(translation) for translation in babel.list_translations()] +if not 'en' in translations: + translations.append('en') +LOGGER.info("Operating with the following translations available: " + ' '.join(translations)) + +app.jinja_env.globals.update(self_localized=self_localized) + +@babel.localeselector +def get_locale(): + parts = request.path.split('/', 2) + if (2 >= len(parts)): + # Totally unexpected path format, do not localize + return "en" + lang = parts[1] + if lang in translations: + return lang + return "en" + +## +# Make the environment available into templates. +# +# @return the environment-reading function. +@app.context_processor +def utility_processor(): + def env(name, default=None): + return os.environ.get(name, default) + + def prettydate(talerdate): + parsed_time = re.search(r"/Date\(([0-9]+)\)/", talerdate) + if not parsed_time: + return "malformed date given" + parsed_time = int(parsed_time.group(1)) + timestamp = datetime.datetime.fromtimestamp(parsed_time) + # returns the YYYY-MM-DD date format. + return timestamp.strftime("%Y-%b-%d") + + return dict(env=env, prettydate=prettydate) + + +## +# Exception handler to capture all the unmanaged errors. +# +# @param e the Exception object, currently unused. +# @return flask-native response object carrying the error message +# (and execution stack!). +@app.errorhandler(Exception) +def internal_error(e): + return flask.render_template( + "templates/error.html.j2", + message=gettext("Internal error"), + stack=traceback.format_exc(), + lang=get_locale() + ) + +## +# 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("/") +def index(): + default = 'en' + target = flask.request.accept_languages.best_match(translations, default) + return flask.redirect("/" + target + "/", code=302) + +## +# Serve the internationalized main index page. +# +# @return response object of the index page. +@app.route("/<lang>/", methods=["GET"]) +def start(lang): + return flask.render_template( + "templates/index.html.j2", + merchant_currency=CURRENCY, + lang=lang + ) + +@app.errorhandler(404) +def handler(e): + return flask.render_template( + "templates/error.html.j2", + message=gettext("Page not found"), + lang=get_locale() + ) + +@app.errorhandler(405) +def handler(e): + return flask.render_template( + "templates/error.html.j2", + message=gettext("HTTP method not allowed for this page"), + lang=get_locale() + ) |