gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] [taler-survey] branch stable updated (90d2bb4 -> 2a23924)


From: gnunet
Subject: [GNUnet-SVN] [taler-survey] branch stable updated (90d2bb4 -> 2a23924)
Date: Mon, 05 Feb 2018 11:50:26 +0100

This is an automated email from the git hooks/post-receive script.

marcello pushed a change to branch stable
in repository survey.

    from 90d2bb4  missing import
     add d382df0  missing link
     add 13425b4  providing 'make pylint'
     add 62118eb  use new tipping API, fix various little things
     add af77f8a  remove wait page, fix syntax/import
     add 73363b8  fix import / remove utility processor
     add d0e35fe  add missing error template
     add baba592  fix endpoint name
     add cb4c5dd  remove unused JS
     add 02e40fa  missing redirect
     add 6f053b8  don't specify (wrong!) pickup URL
     add 2a0e362  apikey
     add 6b033f2  remove comment
     add 43c869b  fix test config
     add 18ae5c3  add survey stats
     add 208efce  typos
     add 7467d75  another typo
     add 0838cd1  properly pass params
     add 2a23924  locate template in the right directory

No new revisions were added by this update.

Summary of changes:
 Makefile.in                                    |   3 +
 talersurvey/survey/amount.py                   | 135 -------------------------
 talersurvey/survey/survey.py                   |  96 +++++++++++-------
 talersurvey/survey/templates/base.html         |  16 +--
 talersurvey/survey/templates/error.html        |  22 ++++
 talersurvey/survey/templates/index.html        |   4 +-
 talersurvey/survey/templates/survey_stats.html |  15 +++
 talersurvey/survey/templates/wait.html         |   7 --
 talersurvey/tests.conf                         |   1 +
 talersurvey/tests.py                           |  36 -------
 10 files changed, 105 insertions(+), 230 deletions(-)
 delete mode 100644 talersurvey/survey/amount.py
 create mode 100644 talersurvey/survey/templates/error.html
 create mode 100644 talersurvey/survey/templates/survey_stats.html
 delete mode 100644 talersurvey/survey/templates/wait.html

diff --git a/Makefile.in b/Makefile.in
index 5f3c47a..a879ae2 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -50,3 +50,6 @@ install: $(templates) install-data
 check:
        @export address@hidden@/talersurvey/tests.conf; \
         python3 setup.py test
+
+pylint:
+       @pylint talersurvey/
diff --git a/talersurvey/survey/amount.py b/talersurvey/survey/amount.py
deleted file mode 100644
index 46e3446..0000000
--- a/talersurvey/survey/amount.py
+++ /dev/null
@@ -1,135 +0,0 @@
-#  This file is part of TALER
-#  (C) 2017 TALER SYSTEMS
-#
-#  This library 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 of the License, or (at your option) any later version.
-#
-#  This library 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 this library; if not, write to the Free Software
-#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  
USA
-#
-#  @author Marcello Stanisci
-#  @version 0.1
-#  @repository https://git.taler.net/copylib.git/
-#  This code is "copylib", it is versioned under the Git repository
-#  mentioned above, and it is meant to be manually copied into any project
-#  which might need it.
-
-class CurrencyMismatch(Exception):
-    def __init__(self, curr1, curr2):
-        super(CurrencyMismatch, self).__init__(
-            "%s vs %s" % (curr1, curr2))
-
-class BadFormatAmount(Exception):
-    def __init__(self, faulty_str):
-        super(BadFormatAmount, self).__init__(
-            "Bad format amount: " + faulty_str)
-
-class Amount:
-    # How many "fraction" units make one "value" unit of currency
-    # (Taler requires 10^8).  Do not change this 'constant'.
-    @staticmethod
-    def _fraction():
-        return 10 ** 8
-
-    @staticmethod
-    def _max_value():
-        return (2 ** 53) - 1
-
-    def __init__(self, currency, value=0, fraction=0):
-        # type: (str, int, int) -> Amount
-        assert value >= 0 and fraction >= 0
-        self.value = value
-        self.fraction = fraction
-        self.currency = currency
-        self.__normalize()
-        assert self.value <= Amount._max_value()
-
-    # Normalize amount
-    def __normalize(self):
-        if self.fraction >= Amount._fraction():
-            self.value += int(self.fraction / Amount._fraction())
-            self.fraction = self.fraction % Amount._fraction()
-
-    # Parse a string matching the format "A:B.C"
-    # instantiating an amount object.
-    @classmethod
-    def parse(cls, amount_str):
-        exp = r'^\s*([-_*A-Za-z0-9]+):([0-9]+)\.([0-9]+)\s*$'
-        import re
-        parsed = re.search(exp, amount_str)
-        if not parsed:
-            raise BadFormatAmount(amount_str)
-        value = int(parsed.group(2))
-        fraction = 0
-        for i, digit in enumerate(parsed.group(3)):
-            fraction += int(int(digit) * (Amount._fraction() / 10 ** (i+1)))
-        return cls(parsed.group(1), value, fraction)
-
-    # Comare two amounts, return:
-    # -1 if a < b
-    # 0 if a == b
-    # 1 if a > b
-    @staticmethod
-    def cmp(am1, am2):
-        if am1.currency != am2.currency:
-            raise CurrencyMismatch(am1.currency, am2.currency)
-        if am1.value == am2.value:
-            if am1.fraction < am2.fraction:
-                return -1
-            if am1.fraction > am2.fraction:
-                return 1
-            return 0
-        if am1.value < am2.value:
-            return -1
-        return 1
-
-    def set(self, currency, value=0, fraction=0):
-        self.currency = currency
-        self.value = value
-        self.fraction = fraction
-
-    # Add the given amount to this one
-    def add(self, amount):
-        if self.currency != amount.currency:
-            raise CurrencyMismatch(self.currency, amount.currency)
-        self.value += amount.value
-        self.fraction += amount.fraction
-        self.__normalize()
-
-    # Subtract passed amount from this one
-    def subtract(self, amount):
-        if self.currency != amount.currency:
-            raise CurrencyMismatch(self.currency, amount.currency)
-        if self.fraction < amount.fraction:
-            self.fraction += Amount._fraction()
-            self.value -= 1
-        if self.value < amount.value:
-            raise ValueError('self is lesser than amount to be subtracted')
-        self.value -= amount.value
-        self.fraction -= amount.fraction
-
-    # Dump string from this amount, will put 'ndigits' numbers
-    # after the dot.
-    def stringify(self, ndigits):
-        assert ndigits > 0
-        ret = '%s:%s.' % (self.currency, str(self.value))
-        fraction = self.fraction
-        while ndigits > 0:
-            ret += str(int(fraction / (Amount._fraction() / 10)))
-            fraction = (fraction * 10) % (Amount._fraction())
-            ndigits -= 1
-        return ret
-
-    # Dump the Taler-compliant 'dict' amount
-    def dump(self):
-        return dict(value=self.value,
-                    fraction=self.fraction,
-                    currency=self.currency)
diff --git a/talersurvey/survey/survey.py b/talersurvey/survey/survey.py
index 6c2f4c8..5126963 100644
--- a/talersurvey/survey/survey.py
+++ b/talersurvey/survey/survey.py
@@ -21,8 +21,8 @@ import json
 from urllib.parse import urljoin
 import flask
 import requests
+import traceback
 from ..talerconfig import TalerConfig
-from .amount import Amount
 
 BASE_DIR = os.path.dirname(os.path.abspath(__file__))
 app = flask.Flask(__name__, template_folder=BASE_DIR)
@@ -31,6 +31,7 @@ app.secret_key = 
base64.b64encode(os.urandom(64)).decode('utf-8')
 TC = TalerConfig.from_env()
 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)
 app.config.from_object(__name__)
 LOGGER = logging.getLogger(__name__)
 
@@ -48,57 +49,76 @@ def backend_error(requests_response):
 
 @app.context_processor
 def utility_processor():
-
-    def join_urlparts(*parts):
-        ret = ""
-        part = 0
-        while part < len(parts):
-            buf = parts[part]
-            part += 1
-            if ret.endswith("/"):
-                buf = buf.lstrip("/")
-            elif ret and not buf.startswith("/"):
-                buf = "/" + buf
-            ret += buf
-        return ret
-
-    def url(my_url):
-        return join_urlparts(flask.request.script_root, my_url)
     def env(name, default=None):
         return os.environ.get(name, default)
-    return dict(url=url, env=env)
+    return dict(env=env)
+
 
+def err_abort(abort_status_code, **params):
+    t = flask.render_template("templates/error.html", **params)
+    flask.abort(flask.make_response(t, abort_status_code))
 
address@hidden("/tip-pickup", methods=["POST"])
-def pick():
-    request_body = flask.request.get_json()
-    resp = requests.post(urljoin(BACKEND_URL, "tip-pickup"),
-                         json=request_body)
+
+def backend_post(endpoint, json):
+    headers = {"Authorization": "ApiKey " + APIKEY}
+    try:
+        resp = requests.post(urljoin(BACKEND_URL, endpoint), json=json, 
headers=headers)
+    except requests.ConnectionError:
+        err_abort(500, message="Could not establish connection to backend")
+    try:
+        response_json = resp.json()
+    except ValueError:
+        err_abort(500, message="Could not parse response from backend",
+                  status_code=resp.status_code)
     if resp.status_code != 200:
-        return backend_error(resp)
-    response_body = resp.json()
-    return flask.jsonify(response_body)
+        err_abort(500, message="Backend returned error status",
+                  json=response_json, status_code=resp.status_code)
+    return response_json
+
+
+def backend_get(endpoint, params):
+    headers = {"Authorization": "ApiKey " + APIKEY}
+    try:
+        resp = requests.get(urljoin(BACKEND_URL, endpoint), params=params, 
headers=headers)
+    except requests.ConnectionError:
+        err_abort(500, message="Could not establish connection to backend")
+    try:
+        response_json = resp.json()
+    except ValueError:
+        err_abort(500, message="Could not parse response from backend")
+    if resp.status_code != 200:
+        err_abort(500, message="Backend returned error status",
+                  json=response_json, status_code=resp.status_code)
+    return response_json
+
+
address@hidden(Exception)
+def internal_error(e):
+    return flask.render_template("templates/error.html",
+                                 message="Internal error",
+                                 stack=traceback.format_exc())
+
address@hidden("/survey-stats", methods=["GET"])
+def survey_stats():
+    stats = backend_get("tip-query", dict(instance="default"))
+    return flask.render_template("templates/survey_stats.html", stats=stats)
+
 
 @app.route("/submit-survey", methods=["POST"])
 def submit_survey():
-    tip_spec = dict(pickup_url=urljoin(flask.request.base_url, "/tip-pickup"),
-                    amount=Amount(CURRENCY, 1).dump(),
+    tip_spec = dict(amount=CURRENCY + ":1.0",
                     next_url=os.environ.get("TALER_ENV_URL_INTRO", 
"https://taler.net/";),
                     instance="default",
                     justification="Payment methods survey")
-    resp = requests.post(urljoin(BACKEND_URL, "tip-authorize"),
-                         json=tip_spec)
-    if resp.status_code != 200:
-        return backend_error(resp)
+    resp = backend_post("tip-authorize", tip_spec)
 
-    response = flask.make_response(
-        flask.render_template("templates/wait.html", success=True),
-        402)
-    response.headers["X-Taler-Tip"] = resp.json()["tip_token"]
+    if resp.get("tip_redirect_url"):
+        return flask.redirect(resp["tip_redirect_url"])
 
-    return response
+    err_abort(500, message="Tipping failed, unexpected backend response",
+              json=resp)
 
 
 @app.route("/", methods=["GET"])
-def survey():
+def index():
     return flask.render_template("templates/index.html", 
merchant_currency=CURRENCY)
diff --git a/talersurvey/survey/templates/base.html 
b/talersurvey/survey/templates/base.html
index 3826797..806ba63 100644
--- a/talersurvey/survey/templates/base.html
+++ b/talersurvey/survey/templates/base.html
@@ -18,10 +18,8 @@
 <html>
 <head>
   <title>Taler Survey Demo</title>
-  <link rel="stylesheet" type="text/css" href="{{ 
url('/static/web-common/pure.css') }}" />
-  <link rel="stylesheet" type="text/css" href="{{ 
url('/static/web-common/demo.css') }}" />
-  <script src="{{ url("/static/web-common/taler-wallet-lib.js") }}" 
type="application/javascript"></script>
-  <script src="{{ url("/static/web-common/lang.js") }}" 
type="application/javascript"></script>
+  <link rel="stylesheet" type="text/css" href="{{ url_for('static', 
filename='web-common/pure.css') }}" />
+  <link rel="stylesheet" type="text/css" href="{{ url_for('static', 
filename='web-common/demo.css') }}" />
   {% block styles %}{% endblock %}
   {% block scripts %}{% endblock %}
 </head>
@@ -36,19 +34,13 @@
       <li><a href="{{ env('TALER_ENV_URL_BANK', '#') }}">Bank</a></li>
       <li><a href="{{ env('TALER_ENV_URL_MERCHANT_BLOG', '#') }}">Essay 
Shop</a></li>
       <li><a href="{{ env('TALER_ENV_URL_MERCHANT_DONATIONS', '#') 
}}">Donations</a></li>
+      <li><a href="{{ env('TALER_ENV_URL_MERCHANT_SURVEY', '#') 
}}">Survey</a></li>
     </ul>
     <p>You can learn more about Taler on our main <a 
href="https://taler.net";>website</a>.</p>
   </div>
 
   <section id="main" class="content">
-    <a href="{{ url("/") }}">
-      <div id="logo">
-        <svg height="100" width="100">
-          <circle cx="50" cy="50" r="40" stroke="darkcyan" stroke-width="6" 
fill="white" />
-          <text x="19" y="82" font-family="Verdana" font-size="90" 
fill="darkcyan">S</text>
-        </svg>
-      </div>
-    </a>
+    <h1>Taler Survey Demo</h1>
     {% block main %}
       This is the main content of the page.
     {% endblock %}
diff --git a/talersurvey/survey/templates/error.html 
b/talersurvey/survey/templates/error.html
new file mode 100644
index 0000000..0d4bd02
--- /dev/null
+++ b/talersurvey/survey/templates/error.html
@@ -0,0 +1,22 @@
+{% extends "templates/base.html" %}
+{% block main %}
+  <h1>An Error Occurred</h1>
+
+  <p>{{ message }}</p>
+
+  {% if status_code %}
+  <p>The backend returned status code {{ status_code }}.</p>
+  {% endif %}
+
+  {% if json %}
+  <p>Backend Response:</p>
+  <pre>{{ json }}</pre>
+  {% endif %}
+
+  {% if stack %}
+  <p>Stack trace:</p>
+  <pre>
+    {{ stack }}
+  </pre>
+  {% endif %}
+{% endblock main %}
diff --git a/talersurvey/survey/templates/index.html 
b/talersurvey/survey/templates/index.html
index 1799abd..e58e669 100644
--- a/talersurvey/survey/templates/index.html
+++ b/talersurvey/survey/templates/index.html
@@ -4,11 +4,11 @@
   <div>
     <p>
       In this page, you can participate in our survey about payment systems
-      and get a nice tip - via your Taler wallet - from this shop!
+      and get a nice tip - via your Taler wallet - from this shop! <a href={{ 
url_for('survey_stats') }}>(survey stats)</a>
     </p>
   </div>
   <div>
-    <form action="{{ url('/submit-survey') }}" method="post" class="pure-form 
pure-form-stacked">
+    <form action="{{ url_for('submit_survey') }}" method="post" 
class="pure-form pure-form-stacked">
       <legend>What do you prefer?</legend>
       <fieldset>
       <label for="option-taler">
diff --git a/talersurvey/survey/templates/survey_stats.html 
b/talersurvey/survey/templates/survey_stats.html
new file mode 100644
index 0000000..62c77dd
--- /dev/null
+++ b/talersurvey/survey/templates/survey_stats.html
@@ -0,0 +1,15 @@
+{% extends "templates/base.html" %}
+
+{% block main %}
+  <div>
+    <p>This page shows information about the tipping configuration of the
+    merchant.  Usually this should not be visible to users.</p>
+    <ul>
+    <li>Reserve pub: {{ stats['reserve_pub'] }}</li>
+    <li>Reserve expiration: {{ stats['reserve_expiration'] }}</li>
+    <li>Amount available {{ stats['amount_available'] }}</li>
+    <li>Amount picked up {{ stats['amount_picked_up'] }}</li>
+    <li>Amount authorized {{ stats['amount_authorized'] }}</li>
+    <ul>
+  </div>
+{% endblock %}
diff --git a/talersurvey/survey/templates/wait.html 
b/talersurvey/survey/templates/wait.html
deleted file mode 100644
index 81dd36a..0000000
--- a/talersurvey/survey/templates/wait.html
+++ /dev/null
@@ -1,7 +0,0 @@
-{% extends "templates/base.html" %}
-
-{% block main %}
-  <p>
-    Please wait while the tip is being generated..
-  </p>
-{% endblock %}
diff --git a/talersurvey/tests.conf b/talersurvey/tests.conf
index bf77dbc..d0d1791 100644
--- a/talersurvey/tests.conf
+++ b/talersurvey/tests.conf
@@ -3,3 +3,4 @@ currency = TESTKUDOS
 
 [frontends]
 BACKEND = http://backend.test.taler.net/
+BACKEND_APIKEY = sandbox
diff --git a/talersurvey/tests.py b/talersurvey/tests.py
index 437a8d3..7dc2446 100644
--- a/talersurvey/tests.py
+++ b/talersurvey/tests.py
@@ -14,41 +14,5 @@ class SurveyTestCase(unittest.TestCase):
         survey.app.testing = True
         self.app = survey.app.test_client()
 
-    @patch("requests.post")
-    def test_authorize(self, mocked_post):
-        ret_post = MagicMock()
-        ret_post.status_code = 200
-        ret_post.json.return_value = {
-            "tip_id": "Jeppo02",
-            "tip_token": "mytiptoken",
-            "exchange_uri": "http://exchange.example.com/";,
-            "expiration": "/Date(2018)/"}
-        mocked_post.return_value = ret_post
-        self.app.post("/submit-survey")
-        mocked_post.assert_called_with(
-            "http://backend.test.taler.net/tip-authorize";,
-            json={
-                "pickup_url": "http://localhost/tip-pickup";,
-                "next_url": os.environ.get("TALER_ENV_URL_INTRO", 
"https://taler.net/";),
-                "amount": {
-                    "value": 1,
-                    "fraction": 0,
-                    "currency": CURRENCY},
-                "instance": "default",
-                "justification": "Payment methods survey"})
-
-    @patch("requests.post")
-    def test_pick(self, mocked_post):
-        ret_post = MagicMock()
-        ret_post.status_code = 200
-        ret_post.json.return_value = {}
-        mocked_post.return_value = ret_post
-        self.app.post("/tip-pickup",
-                      data="{}",
-                      content_type="application/json")
-        mocked_post.assert_called_with(
-            "http://backend.test.taler.net/tip-pickup";,
-            json={})
-
 if __name__ == "__main__":
     unittest.main()

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]