landing.py (5209B)
1 ## 2 # This file is part of GNU TALER. 3 # Copyright (C) 2017, 2020 Taler Systems SA 4 # 5 # TALER is free software; you can redistribute it and/or modify it under the 6 # terms of the GNU Lesser General Public License as published by the Free Software 7 # Foundation; either version 2.1, or (at your option) any later version. 8 # 9 # TALER is distributed in the hope that it will be useful, but WITHOUT ANY 10 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 12 # 13 # You should have received a copy of the GNU Lesser General Public License along with 14 # GNU TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 # 16 # @author Christian Grothoff 17 # @brief Minimal Website for the landing page. 18 19 import os 20 import base64 21 import logging 22 import flask 23 import werkzeug 24 from flask import url_for 25 from flask_babel import Babel 26 from flask_babel import gettext 27 from werkzeug.middleware.proxy_fix import ProxyFix 28 import traceback 29 from ..appconfig import load_taler_config 30 from ..httpcommon import ( 31 get_locale, 32 make_utility_processor, 33 ) 34 import sys 35 36 if not sys.version_info.major == 3 and sys.version_info.minor >= 6: 37 print("Python 3.6 or higher is required.") 38 print( 39 "You are using Python {}.{}.".format( 40 sys.version_info.major, sys.version_info.minor 41 ) 42 ) 43 sys.exit(1) 44 45 app = flask.Flask(__name__, template_folder="../templates", static_folder="../static") 46 app.wsgi_app = ProxyFix(app.wsgi_app, x_host=1, x_prefix=1) 47 app.debug = True 48 app.secret_key = base64.b64encode(os.urandom(64)).decode("utf-8") 49 50 LOGGER = logging.getLogger(__name__) 51 52 config = load_taler_config() 53 54 CURRENCY = config["taler"]["currency"].value_string(required=True) 55 56 57 BABEL_TRANSLATION_DIRECTORIES = "../translations" 58 59 app.config.from_object(__name__) 60 61 babel = Babel(app, locale_selector=get_locale) 62 63 # Add context processor that will make additional variables 64 # and functions available in the template. 65 app.context_processor( 66 make_utility_processor("landing", os.environ.get("TALER_ENV_URL_INTRO")) 67 ) 68 69 70 ## 71 # Exception handler to capture all the unmanaged errors. 72 # 73 # @param e the Exception object, currently unused. 74 # @return flask-native response object carrying the error message 75 # (and execution stack!). 76 @app.errorhandler(Exception) 77 def internal_error(e): 78 return flask.render_template( 79 "landing-error.html.j2", 80 page_title=gettext("GNU Taler Demo: Error"), 81 message=gettext("Internal error"), 82 stack=traceback.format_exc(), 83 ) 84 85 86 ## 87 # Serve the /favicon.ico requests. 88 # 89 # @return the favicon.ico file. 90 @app.route("/favicon.ico") 91 def favicon(): 92 LOGGER.info("will look into: " + os.path.join(app.root_path, "static")) 93 return flask.send_from_directory( 94 os.path.join(app.root_path, "static"), 95 "favicon.ico", 96 mimetype="image/vnd.microsoft.ico", 97 ) 98 99 100 ## 101 # Serve the main index page, redirecting to /<lang>/ 102 # 103 # @return response object of the index page. 104 @app.route("/") 105 def index(): 106 default = "en" 107 translations = [x.language for x in babel.list_translations()] 108 target = flask.request.accept_languages.best_match(translations, default) 109 return flask.redirect(url_for("index") + target + "/", code=302) 110 111 112 ## 113 # Serve the internationalized main index page. 114 # 115 # @return response object of the index page. 116 @app.route("/<lang>/", methods=["GET"]) 117 def start(lang): 118 119 # get_locale defaults to english, hence the 120 # condition below happens only when lang is 121 # wrong or unsupported, respond 404. 122 if lang != get_locale(): 123 raise werkzeug.exceptions.NotFound() 124 125 if x := os.environ.get("TALER_ENV_URL_BANK"): 126 bank_url = x 127 bank_register_url = bank_url 128 bank_public_accounts_url = bank_url + "#public-accounts" 129 else: 130 bank_register_url = "#" 131 bank_url = "#" 132 bank_public_accounts_url = "#" 133 134 if x := os.environ.get("TALER_ENV_URL_MERCHANT_BLOG"): 135 merchant_blog_url = "/".join([x.strip("/"), lang]) 136 else: 137 merchant_blog_url = "#" 138 139 if x := os.environ.get("TALER_ENV_URL_MERCHANT_DONATIONS"): 140 merchant_donations_url = "/".join([x.strip("/"), lang]) 141 else: 142 merchant_donations_url = "#" 143 144 return flask.render_template( 145 "landing-index.html.j2", 146 merchant_currency=CURRENCY, 147 page_title=gettext("GNU Taler Demo"), 148 bank_register_url=bank_register_url, 149 bank_url=bank_url, 150 bank_public_accounts_url=bank_public_accounts_url, 151 merchant_blog_url=merchant_blog_url, 152 merchant_donations_url=merchant_donations_url, 153 ) 154 155 156 @app.errorhandler(404) # How to trigger this? 157 @app.errorhandler(werkzeug.exceptions.NotFound) 158 def handler_404(e): 159 return flask.render_template( 160 "landing-error.html.j2", 161 page_title=gettext("GNU Taler Demo: Error"), 162 message=gettext("Page not found"), 163 ) 164 165 166 @app.errorhandler(405) 167 def handler_405(e): 168 return flask.render_template( 169 "landing-error.html.j2", 170 page_title=gettext("GNU Taler Demo: Error"), 171 message=gettext("HTTP method not allowed for this page"), 172 )