From d69934f816c7e48d758452dd443eca0f02dd14ce Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 11 Oct 2020 17:03:12 +0200 Subject: add landing subpage, simplify deployment --- talermerchantdemos/landing/__init__.py | 3 + talermerchantdemos/landing/landing.py | 164 +++++++++++++++++++++ talermerchantdemos/landing/static | 1 + talermerchantdemos/landing/templates/base.html.j2 | 114 ++++++++++++++ talermerchantdemos/landing/templates/error.html.j2 | 13 ++ talermerchantdemos/landing/templates/index.html.j2 | 73 +++++++++ talermerchantdemos/landing/translations | 1 + 7 files changed, 369 insertions(+) create mode 100644 talermerchantdemos/landing/__init__.py create mode 100644 talermerchantdemos/landing/landing.py create mode 120000 talermerchantdemos/landing/static create mode 100644 talermerchantdemos/landing/templates/base.html.j2 create mode 100644 talermerchantdemos/landing/templates/error.html.j2 create mode 100644 talermerchantdemos/landing/templates/index.html.j2 create mode 120000 talermerchantdemos/landing/translations (limited to 'talermerchantdemos') diff --git a/talermerchantdemos/landing/__init__.py b/talermerchantdemos/landing/__init__.py new file mode 100644 index 0000000..b5d856c --- /dev/null +++ b/talermerchantdemos/landing/__init__.py @@ -0,0 +1,3 @@ +from talermerchantdemos.landing.landing import app + +__all__ = ["app"] 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 +# +# @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 // +# +# @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("//", 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() + ) diff --git a/talermerchantdemos/landing/static b/talermerchantdemos/landing/static new file mode 120000 index 0000000..d9bc54d --- /dev/null +++ b/talermerchantdemos/landing/static @@ -0,0 +1 @@ +../static/ \ No newline at end of file diff --git a/talermerchantdemos/landing/templates/base.html.j2 b/talermerchantdemos/landing/templates/base.html.j2 new file mode 100644 index 0000000..7cf16f1 --- /dev/null +++ b/talermerchantdemos/landing/templates/base.html.j2 @@ -0,0 +1,114 @@ + + + + + + {{ gettext("Taler Demo") }} + + + + + + {% block styles %}{% endblock %} + {% block scripts %}{% endblock %} + + + +
+

{{ gettext("Taler Demo") }}

+

{{ gettext("Survey") }}

+

{{ + gettext("This is the Taler demo.") + "
" + + gettext("Here you can try out the Taler payment system using a toy currency.") + }} +

+
+ + +
+ {% block main %} + This is the main content of the page. + {% endblock %} +
+
+

{{ gettext('You can learn more about Taler on our main website.').format(site="https://taler.net/") }}

+
+

Copyright © 2014—2020 Taler Systems SA

+
+
+ + diff --git a/talermerchantdemos/landing/templates/error.html.j2 b/talermerchantdemos/landing/templates/error.html.j2 new file mode 100644 index 0000000..009947c --- /dev/null +++ b/talermerchantdemos/landing/templates/error.html.j2 @@ -0,0 +1,13 @@ +{% extends "templates/base.html.j2" %} +{% block main %} +

{{ gettext("Error encountered") }}

+ +

{{ message }}

+ + {% if stack %} +

{{gettext("Stack trace:")}}

+
+    {{ stack }}
+  
+ {% endif %} +{% endblock main %} diff --git a/talermerchantdemos/landing/templates/index.html.j2 b/talermerchantdemos/landing/templates/index.html.j2 new file mode 100644 index 0000000..cc6b874 --- /dev/null +++ b/talermerchantdemos/landing/templates/index.html.j2 @@ -0,0 +1,73 @@ +{% extends "templates/base.html.j2" %} +{% block main %} +
+

Step 1: Install the Taler wallet

+ Install the wallet from the installation page. + It only takes one click. +

+ You don't have a wallet installed yet. +

+

+ Congratulations, you have installed the Taler wallet correctly. + You can now proceed with the next steps. +

+
+ +
+

Step 2: Withdraw coins

+

+ + Now you can withdraw coins into your wallet by going to our bank. + + In this demo you are paying with KUDOS, an imaginary currency. When you + create an account at our bank, you'll get 100 KUDOS for free. +

+

+ We cannnot check if you were able to complete this step, since websites + cannot see the balance in your wallet. Please click on the Taler icon + in your browser to check your balance. +

+
+ +
+

Step 3: Pay

+ We have two demo merchants where you can spend your coins: +
    +
  • + The essay store, where you can pay KUDOS for + individual chapters of Richard Stallman's book "Free Software, Free + Society", which is also available for free at the FSF. +
  • +
  • + The project donation website, where + you can show respect to a software project of your choice + by giving them KUDOS. +
  • +
+
+
+

Step 4: Check money flow

+
    +
  • + Check if people who received your Taler payment got eventually + paid by the exchange via a wire transfer; visit the: + public accounts page at the bank. + Note that only those account whose owners gave permission are showed + on that page. +
  • +
+
+ +
+

Step 5: Reach out to us

+ Let us know what you think by contacting us. +
+{% endblock %} diff --git a/talermerchantdemos/landing/translations b/talermerchantdemos/landing/translations new file mode 120000 index 0000000..0a951f7 --- /dev/null +++ b/talermerchantdemos/landing/translations @@ -0,0 +1 @@ +../../translations/ \ No newline at end of file -- cgit v1.2.3