gnunet-svn
[Top][All Lists]
Advanced

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

[taler-taler-merchant-demos] branch master updated: Addressing #6860


From: gnunet
Subject: [taler-taler-merchant-demos] branch master updated: Addressing #6860
Date: Fri, 28 Apr 2023 18:27:55 +0200

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

ms pushed a commit to branch master
in repository taler-merchant-demos.

The following commit(s) were added to refs/heads/master by this push:
     new 9431000  Addressing #6860
9431000 is described below

commit 943100018fc087e3293e93722c2ebc183607bb2f
Author: MS <ms@taler.net>
AuthorDate: Fri Apr 28 18:27:47 2023 +0200

    Addressing #6860
---
 talermerchantdemos/blog/blog.py | 91 ++++++++++++++++++++++++++++++++++-------
 1 file changed, 77 insertions(+), 14 deletions(-)

diff --git a/talermerchantdemos/blog/blog.py b/talermerchantdemos/blog/blog.py
index 263c7cf..3074f91 100644
--- a/talermerchantdemos/blog/blog.py
+++ b/talermerchantdemos/blog/blog.py
@@ -46,6 +46,25 @@ from talermerchantdemos.httpcommon import (
     get_locale,
 )
 
+def req_add_cookie_check():
+    current_url = list(urllib.parse.urlparse(flask.request.base_url))
+    args_writable = flask.request.args.copy()
+    # Adding the used param.
+    args_writable.update(dict(expect_state="yes"))
+    current_url[4] = urllib.parse.urlencode(args_writable) 
+    # Stringify the result.
+    return urllib.parse.urlunparse(current_url) 
+
+
+def req_rm_cookie_check():
+    current_url = list(urllib.parse.urlparse(flask.request.base_url))
+    args_writable = flask.request.args.copy()
+    # Stripping the used param.
+    args_writable.pop("expect_state")
+    current_url[4] = urllib.parse.urlencode(args_writable) 
+    # Stringify the result.
+    return urllib.parse.urlunparse(current_url) 
+
 
 def err_abort(abort_status_code, **params):
     """
@@ -351,22 +370,42 @@ def post_order(article_name, lang):
 def article(article_name, lang=None, data=None):
     # We use an explicit session ID so that each payment (or payment replay) is
     # bound to a browser.  This forces re-play and prevents sharing the article
-    # by just sharing the URL.
+    # by just sharing the URL.  flask.session is transparently set by Flask, 
when
+    # the user agent supports cookies.  All the key-value pairs associated to 
it
+    # are only stored in the server.
     session_id = flask.session.get("session_id")
     order_id = flask.request.cookies.get("order_id")
 
+    # Check if cookies are expected for this request.
+    maybe_expect_state = request.args.get("expect_state")
+    if maybe_expect_state == "yes":
+        if not order_id:
+            error_page = flask.render_template(
+                "blog-error.html.j2",
+                page_title=gettext("GNU Taler Demo: Error"),
+                message=gettext("Please enable cookies."),
+            )
+            return flask.make_response(error_page, 412)
+        # Cookies enabled and found, redirect once again by
+        # stripping the "expect_state" parameter.
+        return flask.redirect(req_rm_cookie_check(), code=302)
+
+    # Whenever we set one session ID, we nullify the order ID (regardless
+    # of it being found in the cookies or not).
     if not session_id:
         session_id = flask.session["session_id"] = str(uuid.uuid4())
+        # This command ensures that fresh sessions are tied to fresh order IDs.
         order_id = None
-    ##
-    # First-timer; generate order first.
+
+    # Merchant backend wasn't asked already to generate the order under
+    # this session, so doing it now.
     if not order_id:
         if not lang:
             err_abort(403, message=gettext("Direct access forbidden"))
         order_resp = post_order(article_name, lang)
         order_id = order_resp["order_id"]
 
-    # Ask the backend for the status of the payment
+    # Ask the backend for the status of the payment.
     pay_status = backend_get(
         BACKEND_URL,
         f"private/orders/{order_id}",
@@ -374,6 +413,7 @@ def article(article_name, lang=None, data=None):
         auth_token=APIKEY,
     )
     order_status = pay_status.get("order_status")
+
     if order_status == "claimed":
         if not lang:
             err_abort(403, message=gettext("Direct access forbidden"))
@@ -387,7 +427,6 @@ def article(article_name, lang=None, data=None):
             auth_token=APIKEY,
         )
         order_status = pay_status.get("order_status")
-        # This really must be 'unpaid' now...
 
     if order_status == "paid":
         refunded = pay_status["refunded"]
@@ -399,15 +438,28 @@ def article(article_name, lang=None, data=None):
                 order_id=order_id,
             )
         response = render_article(
-            article_name, lang, data, order_id, refundable(pay_status)
+            article_name,
+            lang,
+            data,
+            order_id,
+            refundable(pay_status)
         )
         return response
 
-    # Check if the customer came on this page via the
-    # re-purchase detection mechanism
+    # Checking repurchase case.  That happens when the client
+    # visits this page in the same session where the article
+    # was paid already.
     ai = pay_status.get("already_paid_order_id")
     au = pay_status.get("already_paid_fulfillment_url")
+
+    # If the condition below holds, then the browser gets
+    # the paid order ID in the cookies, and the protocol starts
+    # again from that associated fulfillment URL (likely to be
+    # this page).
     if ai is not None and au is not None:
+        # NOT appending the "expect_state" URI param to check
+        # cookies, because at this point the user agent DID show
+        # a session, so their cookies must be enabled.
         response = flask.redirect(au)
         response.set_cookie(
             "order_id",
@@ -421,13 +473,23 @@ def article(article_name, lang=None, data=None):
         )
         return response
 
-    # Redirect the browser to a page where the wallet can
-    # run the payment protocol.
+    # No claim, nor repurchase, nor paid statuses were found so far.
+    # The actual payment protocol needs to be run, and the following
+    # URL instructs the browser+wallet to run it.
     redirect_url = pay_status["order_status_url"]
-    LOGGER.info(
-        "Redirecting (with order_id cookies) to", redirect_url
-    )
-    response = flask.redirect(redirect_url)
+    # The order_id cookies MIGHT already be set, if the browser
+    # passed successfully the cookie support check (see at the very
+    # top of this function), and got redirected here thereafter.
+    # In this case, we can now redirect the browser to the URL that
+    # triggers the wallet.
+
+    if flask.request.cookies.get("order_id") and order_status != "paid":
+        LOGGER.info("Redirecting (with order_id cookies) to", redirect_url)
+        return flask.redirect(redirect_url)
+
+    # Order ID is fresh, thus setting the cookies now, and
+    # redirecting the client to the cookie support check.
+    response = flask.redirect(req_add_cookie_check())
     response.set_cookie(
         "order_id",
         order_id,
@@ -438,6 +500,7 @@ def article(article_name, lang=None, data=None):
         order_id,
         path=urllib.parse.quote(url_for ('index') + 
f"{lang}/essay/{article_name}")
     )
+
     return response
 
 

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

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