gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] [taler-blog] branch stable updated (c27a91f -> 8013b26)


From: gnunet
Subject: [GNUnet-SVN] [taler-blog] branch stable updated (c27a91f -> 8013b26)
Date: Fri, 29 Mar 2019 18:40:55 +0100

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

marcello pushed a change to branch stable
in repository blog.

 discard c27a91f  Fix article name (#5508).
     add 99e8d4d  changelog
     add d4984a2  Restore back-office link
     add d152a01  4809.
     add cd0a652  Submodule update
     add c352611  Ignore "dirty" submodule
     add 1eff6d6  fix HTML
     add 98b815f  Doxyfile
     add b982160  Instruct doxygen to crawl recursively.
     add 9a02cbe  Doxygen-commenting blog.py, and content.py.
     add 9de91ef  Doxygen-commenting the blog tests.
     add da74956  Doxygen.
     add 75fdb56  ^bank^blog
     add 66096d8  Exclude Makefile.in from Doxygenation.
     add ba368f5  fix pip3
     add b97e198  fix shebang
     new 8013b26  Fix article name (#5508).

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (c27a91f)
            \
             N -- N -- N   refs/heads/stable (8013b26)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .gitignore                               |   1 +
 .gitmodules                              |   3 +-
 ChangeLog                                |   3 +
 Doxyfile                                 | 331 +++++++++++++++++++++++++++++++
 Makefile.in                              |   4 +-
 configure.ac                             |  10 +
 setup.py                                 |   4 -
 taler-merchant-blog.in                   |  42 +++-
 talerblog/blog/blog.py                   | 152 +++++++++++---
 talerblog/blog/content.py                |  45 ++++-
 talerblog/blog/static/web-common         |   2 +-
 talerblog/blog/templates/base.html       |   1 +
 talerblog/blog/templates/javascript.html |  42 ++--
 talerblog/tests.py                       |  30 +++
 14 files changed, 604 insertions(+), 66 deletions(-)
 create mode 100644 ChangeLog
 create mode 100644 Doxyfile

diff --git a/.gitignore b/.gitignore
index 409c488..c8f7a59 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+doxygen-doc/
 .eggs/
 Makefile
 aclocal.m4
diff --git a/.gitmodules b/.gitmodules
index 8a8b04d..b268674 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,4 @@
 [submodule "talerblog/blog/static/web-common"]
        path = talerblog/blog/static/web-common
-       url = git://taler.net/web-common
+       url = git://git.taler.net/web-common
+        ignore = dirty
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..596330b
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,3 @@
+Tue Feb 13 10:26:37 CET 2018
+        Payment logic which is less state-dependant
+        and more mobile-friendly.
diff --git a/Doxyfile b/Doxyfile
new file mode 100644
index 0000000..933897a
--- /dev/null
+++ b/Doxyfile
@@ -0,0 +1,331 @@
+# Doxyfile 1.8.13
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+DOXYFILE_ENCODING      = UTF-8
+PROJECT_NAME           = "taler-blog"
+PROJECT_NUMBER         =
+PROJECT_BRIEF          =
+PROJECT_LOGO           =
+OUTPUT_DIRECTORY       = doxygen-doc/
+CREATE_SUBDIRS         = NO
+ALLOW_UNICODE_NAMES    = NO
+OUTPUT_LANGUAGE        = English
+BRIEF_MEMBER_DESC      = YES
+REPEAT_BRIEF           = YES
+ABBREVIATE_BRIEF       = "The $name class" \
+                         "The $name widget" \
+                         "The $name file" \
+                         is \
+                         provides \
+                         specifies \
+                         contains \
+                         represents \
+                         a \
+                         an \
+                         the
+ALWAYS_DETAILED_SEC    = NO
+INLINE_INHERITED_MEMB  = NO
+FULL_PATH_NAMES        = YES
+STRIP_FROM_PATH        =
+STRIP_FROM_INC_PATH    =
+SHORT_NAMES            = NO
+JAVADOC_AUTOBRIEF      = NO
+QT_AUTOBRIEF           = NO
+MULTILINE_CPP_IS_BRIEF = NO
+INHERIT_DOCS           = YES
+SEPARATE_MEMBER_PAGES  = NO
+TAB_SIZE               = 4
+ALIASES                =
+TCL_SUBST              =
+OPTIMIZE_OUTPUT_FOR_C  = NO
+OPTIMIZE_OUTPUT_JAVA   = NO
+OPTIMIZE_FOR_FORTRAN   = NO
+OPTIMIZE_OUTPUT_VHDL   = NO
+EXTENSION_MAPPING      = in=Python
+MARKDOWN_SUPPORT       = YES
+TOC_INCLUDE_HEADINGS   = 0
+AUTOLINK_SUPPORT       = YES
+BUILTIN_STL_SUPPORT    = NO
+CPP_CLI_SUPPORT        = NO
+SIP_SUPPORT            = NO
+IDL_PROPERTY_SUPPORT   = YES
+DISTRIBUTE_GROUP_DOC   = NO
+GROUP_NESTED_COMPOUNDS = NO
+SUBGROUPING            = YES
+INLINE_GROUPED_CLASSES = NO
+INLINE_SIMPLE_STRUCTS  = NO
+TYPEDEF_HIDES_STRUCT   = NO
+LOOKUP_CACHE_SIZE      = 0
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL            = YES
+EXTRACT_PRIVATE        = NO
+EXTRACT_PACKAGE        = NO
+EXTRACT_STATIC         = NO
+EXTRACT_LOCAL_CLASSES  = YES
+EXTRACT_LOCAL_METHODS  = NO
+EXTRACT_ANON_NSPACES   = NO
+HIDE_UNDOC_MEMBERS     = NO
+HIDE_UNDOC_CLASSES     = NO
+HIDE_FRIEND_COMPOUNDS  = NO
+HIDE_IN_BODY_DOCS      = NO
+INTERNAL_DOCS          = NO
+CASE_SENSE_NAMES       = YES
+HIDE_SCOPE_NAMES       = NO
+HIDE_COMPOUND_REFERENCE= NO
+SHOW_INCLUDE_FILES     = YES
+SHOW_GROUPED_MEMB_INC  = NO
+FORCE_LOCAL_INCLUDES   = NO
+INLINE_INFO            = YES
+SORT_MEMBER_DOCS       = YES
+SORT_BRIEF_DOCS        = NO
+SORT_MEMBERS_CTORS_1ST = NO
+SORT_GROUP_NAMES       = NO
+SORT_BY_SCOPE_NAME     = NO
+STRICT_PROTO_MATCHING  = NO
+GENERATE_TODOLIST      = YES
+GENERATE_TESTLIST      = YES
+GENERATE_BUGLIST       = YES
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS       =
+MAX_INITIALIZER_LINES  = 30
+SHOW_USED_FILES        = YES
+SHOW_FILES             = YES
+SHOW_NAMESPACES        = NO
+FILE_VERSION_FILTER    =
+LAYOUT_FILE            =
+CITE_BIB_FILES         =
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET                  = NO
+WARNINGS               = YES
+WARN_IF_UNDOCUMENTED   = YES
+WARN_IF_DOC_ERROR      = YES
+WARN_NO_PARAMDOC       = NO
+WARN_AS_ERROR          = NO
+WARN_FORMAT            = "$file:$line: $text"
+WARN_LOGFILE           =
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT                  =
+INPUT_ENCODING         = UTF-8
+FILE_PATTERNS          = *.py *.in
+RECURSIVE              = YES
+EXCLUDE                = Makefile.in
+EXCLUDE_SYMLINKS       = NO
+EXCLUDE_PATTERNS       =
+EXCLUDE_SYMBOLS        =
+EXAMPLE_PATH           =
+EXAMPLE_PATTERNS       = *
+EXAMPLE_RECURSIVE      = NO
+IMAGE_PATH             =
+INPUT_FILTER           =
+FILTER_PATTERNS        =
+FILTER_SOURCE_FILES    = NO
+FILTER_SOURCE_PATTERNS =
+USE_MDFILE_AS_MAINPAGE =
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER         = NO
+INLINE_SOURCES         = NO
+STRIP_CODE_COMMENTS    = YES
+REFERENCED_BY_RELATION = NO
+REFERENCES_RELATION    = NO
+REFERENCES_LINK_SOURCE = YES
+SOURCE_TOOLTIPS        = YES
+USE_HTAGS              = NO
+VERBATIM_HEADERS       = YES
+CLANG_ASSISTED_PARSING = NO
+CLANG_OPTIONS          =
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX     = YES
+COLS_IN_ALPHA_INDEX    = 5
+IGNORE_PREFIX          =
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML          = YES
+HTML_OUTPUT            = html
+HTML_FILE_EXTENSION    = .html
+HTML_HEADER            =
+HTML_FOOTER            =
+HTML_STYLESHEET        =
+HTML_EXTRA_STYLESHEET  =
+HTML_EXTRA_FILES       =
+HTML_COLORSTYLE_HUE    = 220
+HTML_COLORSTYLE_SAT    = 100
+HTML_COLORSTYLE_GAMMA  = 80
+HTML_TIMESTAMP         = NO
+HTML_DYNAMIC_SECTIONS  = NO
+HTML_INDEX_NUM_ENTRIES = 100
+GENERATE_DOCSET        = NO
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+DOCSET_PUBLISHER_NAME  = Publisher
+GENERATE_HTMLHELP      = NO
+CHM_FILE               =
+HHC_LOCATION           =
+GENERATE_CHI           = NO
+CHM_INDEX_ENCODING     =
+BINARY_TOC             = NO
+TOC_EXPAND             = NO
+GENERATE_QHP           = NO
+QCH_FILE               =
+QHP_NAMESPACE          = org.doxygen.Project
+QHP_VIRTUAL_FOLDER     = doc
+QHP_CUST_FILTER_NAME   =
+QHP_CUST_FILTER_ATTRS  =
+QHP_SECT_FILTER_ATTRS  =
+QHG_LOCATION           =
+GENERATE_ECLIPSEHELP   = NO
+ECLIPSE_DOC_ID         = org.doxygen.Project
+DISABLE_INDEX          = NO
+GENERATE_TREEVIEW      = NO
+ENUM_VALUES_PER_LINE   = 4
+TREEVIEW_WIDTH         = 250
+EXT_LINKS_IN_WINDOW    = NO
+FORMULA_FONTSIZE       = 10
+FORMULA_TRANSPARENT    = YES
+USE_MATHJAX            = NO
+MATHJAX_FORMAT         = HTML-CSS
+MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
+MATHJAX_EXTENSIONS     =
+MATHJAX_CODEFILE       =
+SEARCHENGINE           = YES
+SERVER_BASED_SEARCH    = NO
+EXTERNAL_SEARCH        = NO
+SEARCHENGINE_URL       =
+SEARCHDATA_FILE        = searchdata.xml
+EXTERNAL_SEARCH_ID     =
+EXTRA_SEARCH_MAPPINGS  =
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX         = NO
+LATEX_OUTPUT           = latex
+LATEX_CMD_NAME         = latex
+MAKEINDEX_CMD_NAME     = makeindex
+COMPACT_LATEX          = NO
+PAPER_TYPE             = a4
+EXTRA_PACKAGES         =
+LATEX_HEADER           =
+LATEX_FOOTER           =
+LATEX_EXTRA_STYLESHEET =
+LATEX_EXTRA_FILES      =
+PDF_HYPERLINKS         = YES
+USE_PDFLATEX           = YES
+LATEX_BATCHMODE        = NO
+LATEX_HIDE_INDICES     = NO
+LATEX_SOURCE_CODE      = NO
+LATEX_BIB_STYLE        = plain
+LATEX_TIMESTAMP        = NO
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF           = NO
+RTF_OUTPUT             = rtf
+COMPACT_RTF            = NO
+RTF_HYPERLINKS         = NO
+RTF_STYLESHEET_FILE    =
+RTF_EXTENSIONS_FILE    =
+RTF_SOURCE_CODE        = NO
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN           = NO
+MAN_OUTPUT             = man
+MAN_EXTENSION          = .3
+MAN_SUBDIR             =
+MAN_LINKS              = NO
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML           = NO
+XML_OUTPUT             = xml
+XML_PROGRAMLISTING     = YES
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+GENERATE_DOCBOOK       = NO
+DOCBOOK_OUTPUT         = docbook
+DOCBOOK_PROGRAMLISTING = NO
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF   = NO
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD       = NO
+PERLMOD_LATEX          = NO
+PERLMOD_PRETTY         = YES
+PERLMOD_MAKEVAR_PREFIX =
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING   = YES
+MACRO_EXPANSION        = NO
+EXPAND_ONLY_PREDEF     = NO
+SEARCH_INCLUDES        = YES
+INCLUDE_PATH           =
+INCLUDE_FILE_PATTERNS  =
+PREDEFINED             =
+EXPAND_AS_DEFINED      =
+SKIP_FUNCTION_MACROS   = YES
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+TAGFILES               =
+GENERATE_TAGFILE       =
+ALLEXTERNALS           = NO
+EXTERNAL_GROUPS        = YES
+EXTERNAL_PAGES         = YES
+PERL_PATH              = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS         = NO
+MSCGEN_PATH            =
+DIA_PATH               =
+HIDE_UNDOC_RELATIONS   = YES
+HAVE_DOT               = YES
+DOT_NUM_THREADS        = 0
+DOT_FONTNAME           = Helvetica
+DOT_FONTSIZE           = 10
+DOT_FONTPATH           =
+CLASS_GRAPH            = YES
+COLLABORATION_GRAPH    = YES
+GROUP_GRAPHS           = YES
+UML_LOOK               = NO
+UML_LIMIT_NUM_FIELDS   = 10
+TEMPLATE_RELATIONS     = NO
+INCLUDE_GRAPH          = YES
+INCLUDED_BY_GRAPH      = YES
+CALL_GRAPH             = NO
+CALLER_GRAPH           = NO
+GRAPHICAL_HIERARCHY    = YES
+DIRECTORY_GRAPH        = YES
+DOT_IMAGE_FORMAT       = png
+INTERACTIVE_SVG        = NO
+DOT_PATH               =
+DOTFILE_DIRS           =
+MSCFILE_DIRS           =
+DIAFILE_DIRS           =
+PLANTUML_JAR_PATH      =
+PLANTUML_CFG_FILE      =
+PLANTUML_INCLUDE_PATH  =
+DOT_GRAPH_MAX_NODES    = 50
+MAX_DOT_GRAPH_DEPTH    = 0
+DOT_TRANSPARENT        = NO
+DOT_MULTI_TARGETS      = NO
+GENERATE_LEGEND        = YES
+DOT_CLEANUP            = YES
diff --git a/Makefile.in b/Makefile.in
index c42a688..f900143 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -40,9 +40,9 @@ devinstall: $(templates) install-data
 # install into prefix
 .PHONY: install
 install: $(templates) install-data
-       @pip3 install . --install-option="address@hidden@"
+       @pip3 install . @DEBIAN_PIP3_SYSTEM@ --install-option="address@hidden@"
        @# force update when sources changed
-       @pip3 install . --install-option="address@hidden@" --upgrade --no-deps
+       @pip3 install . @DEBIAN_PIP3_SYSTEM@ --install-option="address@hidden@" 
--upgrade --no-deps
        cd talerblog/blog/static/web-common && make install && cd -
 
 # run testcases
diff --git a/configure.ac b/configure.ac
index db0e695..9f8d9b0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -31,6 +31,16 @@ AC_MSG_RESULT([$VERSION])
 
 AX_COMPARE_VERSION([$VERSION],[lt],[6.0], [AC_MSG_ERROR([Please install 
pip3>=6.0])])
 
+# On Debian systems, we may need to pass "--system" to pip3 to get
+# to the desired installation target directory
+pip3 install --help | grep '\-\-system' >> /dev/null
+if test $? -ne 0;
+then
+   DEBIAN_PIP3_SYSTEM=""
+else
+   DEBIAN_PIP3_SYSTEM="--system"
+fi
+AC_SUBST(DEBIAN_PIP3_SYSTEM)
 
 #
 # Check for tsc
diff --git a/setup.py b/setup.py
index 08c7ee5..8304034 100755
--- a/setup.py
+++ b/setup.py
@@ -17,12 +17,8 @@ setup(name='talerblog',
               "blog/templates/*.html",
               "blog/static/*.svg",
               "blog/static/*.css",
-              "blog/static/*.js",
-              "blog/static/*.js.tar.gz",
               "blog/static/web-common/*.png",
               "blog/static/web-common/*.css",
-              "blog/static/web-common/*.js",
-              "blog/static/web-common/*.js.tar.gz",
               "blog/static/web-common/*.html",
               "blog/articles/*",
               "blog/data/*"
diff --git a/taler-merchant-blog.in b/taler-merchant-blog.in
index 0b25879..dcc1e29 100644
--- a/taler-merchant-blog.in
+++ b/taler-merchant-blog.in
@@ -1,8 +1,25 @@
 #!/usr/bin/env python3
 
-"""
-Stand-alone script to manage the GNU Taler blog frontend.
-"""
+##
+# This file is part of TALER
+# (C) 2017 INRIA
+#
+# TALER is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Affero General Public
+# License as published by the Free Software Foundation; either
+# version 3, 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with TALER; see the file COPYING.  If not,
+# see <http://www.gnu.org/licenses/>
+#
+#  @author Florian Dold
+#  @file Standalone script to run the blog.
 
 import logging
 import argparse
@@ -18,12 +35,20 @@ site.addsitedir("%s/lib/python%d.%d/site-packages" % (
     sys.version_info.major,
     sys.version_info.minor))
 
+## @cond
 LOGGER = logging.getLogger(__name__)
 TC = TalerConfig.from_file(os.environ.get("TALER_CONFIG_FILE"))
 
 # No perfect match to our logging format, but good enough ...
 UWSGI_LOGFMT = "%(ltime) %(proto) %(method) %(uri) %(proto) => %(status)"
+## @endcond
 
+
+##
+# This function interprets the 'serve-http' subcommand.
+# The effect it to launch the blog HTTP service.
+#
+# @param args command line options.
 def handle_serve_http(args):
     port = args.port
     if port is None:
@@ -36,6 +61,13 @@ def handle_serve_http(args):
               "--http", spec,
               "--wsgi-file", "@prefix@/share/taler/frontend-blog.wsgi")
 
+##
+# This function interprets the 'serve-uwsgi' subcommand.
+# The effect is to launch the blog UWSGI service.  This
+# type of service is usually used when the HTTP blog interface
+# is accessed via a reverse proxy (like Nginx, for example).
+#
+# @param command line options.
 def handle_serve_uwsgi(args):
     del args # pacify PEP checkers
     serve_uwsgi = TC["blog"]["uwsgi_serve"].value_string(required=True).lower()
@@ -58,8 +90,7 @@ def handle_serve_uwsgi(args):
     logging.info("launching uwsgi with argv %s", params[1:])
     os.execlp(*params)
 
-
-
+## @cond
 PARSER = argparse.ArgumentParser()
 PARSER.set_defaults(func=None)
 PARSER.add_argument('--config', '-c',
@@ -77,6 +108,7 @@ P = SUB.add_parser('serve-uwsgi', help="Serve over UWSGI")
 P.set_defaults(func=handle_serve_uwsgi)
 
 ARGS = PARSER.parse_args()
+## @endcond
 if getattr(ARGS, 'func', None) is None:
     PARSER.print_help()
     sys.exit(1)
diff --git a/talerblog/blog/blog.py b/talerblog/blog/blog.py
index 02d10d0..860a3a9 100644
--- a/talerblog/blog/blog.py
+++ b/talerblog/blog/blog.py
@@ -1,3 +1,4 @@
+##
 # This file is part of GNU TALER.
 # Copyright (C) 2014-2017 INRIA
 #
@@ -14,11 +15,7 @@
 #
 # @author Florian Dold
 # @author Marcello Stanisci
-
-
-"""
-Implement URL handlers and payment logic for the blog merchant.
-"""
+# @brief Implementation of a Taler-compatible blog.
 
 from urllib.parse import urljoin, quote
 import logging
@@ -48,6 +45,11 @@ ARTICLE_AMOUNT = CURRENCY + ":0.5"
 app.config.from_object(__name__)
 
 
+##
+# Extends the templating language with a function (@c env)
+# that fetches values from the environment.
+#
+# @return a @a dict containing the extension.
 @app.context_processor
 def utility_processor():
     # These helpers will be available in templates
@@ -56,11 +58,22 @@ def utility_processor():
     return dict(env=env)
 
 
+##
+# Return a error response to the client.
+#
+# @param abort_status_code status code to return along the response.
+# @param params _kw_ arguments to passed verbatim to the templating engine.
 def err_abort(abort_status_code, **params):
     t = flask.render_template("templates/error.html", **params)
     flask.abort(flask.make_response(t, abort_status_code))
 
-
+##
+# Issue a GET request to the backend.
+#
+# @param endpoint the backend endpoint where to issue the request.
+# @param params (dict type of) URL parameters to append to the request.
+# @return the JSON response from the backend, or a error response
+#         if something unexpected happens.
 def backend_get(endpoint, params):
     headers = {"Authorization": "ApiKey " + APIKEY}
     try:
@@ -76,7 +89,14 @@ def backend_get(endpoint, params):
                   json=response_json, status_code=resp.status_code)
     return response_json
 
-
+##
+# POST a request to the backend, and return a error
+# response if any error occurs.
+#
+# @param endpoint the backend endpoint where to POST
+#        this request.
+# @param json the POST's body.
+# @return the backend response (JSON format).
 def backend_post(endpoint, json):
     headers = {"Authorization": "ApiKey " + APIKEY}
     try:
@@ -94,28 +114,42 @@ def backend_post(endpoint, json):
     return response_json
 
 
+
+##
+# "Fallback" 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",
                                  message="Internal error",
                                  stack=traceback.format_exc())
 
-
+##
+# Serve the main index page.
+#
+# @return response object of the index page.
 @app.route("/")
 def index():
     return flask.render_template("templates/index.html",
                                  merchant_currency=CURRENCY,
                                  articles=ARTICLES.values())
 
-
+##
+# Serve the "/javascript" page.
+#
+# @return response object for the /javascript page.
 @app.route("/javascript")
 def javascript_licensing():
     return flask.render_template("templates/javascript.html")
 
 
-# Cache for paid articles (in the form <session_id>-<article_name>), so we
-# don't always have to ask the backend / DB, and so we don't have to store
-# variable-size cookies on the client.
+##
+# @brief Cache for paid articles (in the form <session_id>-<article_name>),
+#        so we don't always have to ask the backend / DB, and so we don't
+#        have to store variable-size cookies on the client.
 try:
     import uwsgi
     paid_articles_cache = UWSGICache(0, "paid_articles")
@@ -123,8 +157,18 @@ except ImportError:
     paid_articles_cache = SimpleCache()
 
 
+##
 # Triggers the refund by serving /refund/test?order_id=XY.
 # Will be triggered by a "refund button".
+#
+# @param order_id the order ID of the transaction to refund.
+# @return the following errors (named by HTTP response code):
+#         - 400: no article was asked to be refunded! 
+#         - 401: the refund was asked on a non-payed article.
+#         - 500: the backend was unable to give response.
+#         Or, in the successful case, a redirection to the
+#         "refund URL" is returned; then the wallet will run
+#         the refund protocol in a transparent way.
 @app.route("/refund/<order_id>", methods=["POST"])
 def refund(order_id):
     article_name = flask.request.form.get("article_name")
@@ -133,12 +177,10 @@ def refund(order_id):
     LOGGER.info("Looking for %s to refund" % article_name)
     if not order_id:
         return flask.jsonify(dict(error="Aborting refund: article not 
payed")), 401
-    refund_spec = dict(
-        instance=INSTANCE,
-        order_id=order_id,
-        reason="Demo reimbursement",
-        refund=ARTICLE_AMOUNT,
-    )
+    refund_spec = dict(instance=INSTANCE,
+                       order_id=order_id,
+                       reason="Demo reimbursement",
+                       refund=ARTICLE_AMOUNT)
     resp = backend_post("refund", refund_spec)
     try:
         # delete from paid article cache
@@ -151,6 +193,20 @@ def refund(order_id):
                 json=resp, stack=traceback.format_exc())
 
 
+
+##
+# Render the article after a successful purchase.
+#
+# @param article_name _slugged_ (= spaces converted to underscores) article 
title.
+# @param data image filename to return along the article.
+# @param order_id the ID of the order where this article got purchased.
+#        (Will be put in the refund-request form action, since any article
+#         will also have a "refund button" aside.)
+# @return the following errors (named by HTTP return code):
+#         - 500: file for article not found.
+#         - 404: supplemental @a data not found.
+#         In the successful case, a response object carrying the
+#         article in it will be returned.
 def render_article(article_name, data, order_id):
     article_info = ARTICLES.get(article_name)
     if article_info is None:
@@ -169,6 +225,25 @@ def render_article(article_name, data, order_id):
                                  order_id=order_id)
 
 
+##
+# Trigger a article purchase.  The logic follows the main steps:
+#
+# 1. Always check if the article was paid already, via the
+#    "/check-payment" API from the backend.
+# 2. If so, return the article.
+# 3. If not, redirect the browser to a page where the
+#    wallet will initiate the payment protocol.
+#
+# @param article_name (slugged) article title.
+# @param data filename of a supplement data (image/sound/..)
+# @return the following errors might occur (named by HTTP response code):
+#         - 402: @a article_name does not correspond to the @a order_id
+#                of a PAYED article.
+#         - 500: neither the article was paid, nor a payment was triggered.
+#         - 400: a invalid order_id was passed along the GET parameters.
+#         In the successful case, either the article is returned, or
+#         the browser gets redirected to a page where the wallet can
+#         send the payment.
 @app.route("/essay/<article_name>")
 @app.route("/essay/<article_name>/data/<data>")
 def article(article_name, data=None):
@@ -187,42 +262,59 @@ def article(article_name, data=None):
     if cached_order_id:
         return render_article(article_name, data, cached_order_id)
 
+    ##
+    # If there was an order_id but no session_sig, either the user played
+    # around with the URL or the wallet is old/broken.
     if order_id and not session_sig:
-        # If there was an order_id but no session_sig, either the user played
-        # around with the URL or the wallet is old/broken.
         err_abort(400, message=("Bad request (session_sig missing). "
                                 "Your wallet might be broken or outdated"))
-
+    ##
+    # First-timer; generate order first.
     if not order_id:
         order = dict(
             amount=ARTICLE_AMOUNT,
             extra=dict(article_name=article_name),
             fulfillment_url=flask.request.base_url,
             instance=INSTANCE,
-            summary="Essay: " + article_name.replace("_", " "),
-        )
+            summary="Essay: " + article_name.replace("_", " "))
         order_resp = backend_post("order", dict(order=order))
         order_id = order_resp["order_id"]
 
-    pay_params = dict(
-        instance=INSTANCE,
-        order_id=order_id,
-        resource_url=flask.request.base_url,
-        session_id=session_id,
-        session_sig=session_sig,
-    )
+    ##
+    # Prepare data for the upcoming payment check.
+    pay_params = dict(instance=INSTANCE,
+                      order_id=order_id,
+                      resource_url=flask.request.base_url,
+                      session_id=session_id,
+                      session_sig=session_sig)
 
     pay_status = backend_get("check-payment", pay_params)
 
     if pay_status.get("paid"):
+
+        ##
+        # Somehow, a session with a payed article which _differs_ from
+        # the article requested in the URL existed; trigger the pay protocol!
         if pay_status["contract_terms"]["extra"]["article_name"] != 
article_name:
             err_abort(402, message="You did not pay for this article (nice 
try!)", json=pay_status)
+            
+        ##
+        # Show a "article refunded" page, in that case.
         if pay_status.get("refunded"):
             return flask.render_template("templates/article_refunded.html",
                                          article_name=article_name)
+        ##
+        # Put the article in the cache.
         paid_articles_cache.set(session_id + "-" + article_name, order_id)
+
+        ##
+        # Finally return the article.
         return render_article(article_name, data, order_id)
+
     else:
+        ##
+        # Redirect the browser to a page where the wallet can
+        # run the payment protocol.
         if pay_status.get("payment_redirect_url"):
             return flask.redirect(pay_status["payment_redirect_url"])
 
diff --git a/talerblog/blog/content.py b/talerblog/blog/content.py
index 4aeb865..8dddd1f 100644
--- a/talerblog/blog/content.py
+++ b/talerblog/blog/content.py
@@ -1,3 +1,4 @@
+##
 # This file is part of GNU TALER.
 # Copyright (C) 2014-2016 INRIA
 #
@@ -13,10 +14,7 @@
 # GNU TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 #
 # @author Florian Dold
-
-"""
-Define content and associated metadata that is served on the blog.
-"""
+# @brief Define content and associated metadata that is served on the blog.
 
 from collections import OrderedDict, namedtuple
 import logging
@@ -29,27 +27,56 @@ LOGGER = logging.getLogger(__name__)
 NOISY_LOGGER = logging.getLogger("chardet.charsetprober")
 NOISY_LOGGER.setLevel(logging.INFO)
 Article = namedtuple("Article", "slug title teaser main_file extra_files")
-ARTICLES = OrderedDict()
 
+##
+# @var if a article is added to this list, then it will
+#      be made available in the blog.
+ARTICLES = OrderedDict()
 
+##
+# Add article to the list of the available articles.
+#
+# @param slug article's title with all the spaces converted to underscores.
+# @param title article's title.
+# @param teaser a short description of the main article's content.
+# @param main_file path to the article's HTML file.
+# @param extra_file collection of extra files associated with the
+#        article, like images and sounds.
 def add_article(slug, title, teaser, main_file, extra_files):
     ARTICLES[slug] = Article(slug, title, teaser, main_file, extra_files)
 
 
+##
+# Build the file path of a image.
+#
+# @param image the image filename.
+# @return the path to the image file.
 def get_image_file(image):
     filex = resource_filename("talerblog", os.path.join("blog/data/", image))
     return os.path.abspath(filex)
 
-
+##
+# Build the file path of a article.
+#
+# @param article the article filename.
+# @return the path to the article HTML file.
 def get_article_file(article):
     filex = resource_filename("talerblog", article.main_file)
     return os.path.basename(filex)
 
 
+##
+# Extract information from HTML file, and use these informations
+# to make the article available in the blog.
+#
+# @param resource_name path to the (HTML) article.
+# @param teaser_paragraph position of the teaser paragraph in the
+#        article's list of all the P tags.  Defaults to zero, as normally
+#        this information is found under the very first P tag.
+# @param title article's title; normally, this bit is extracted from the
+#        HTML itself, so give it here if a explicit title needs to be
+#        specified.
 def add_from_html(resource_name, teaser_paragraph=0, title=None):
-    """
-    Extract information from article html.
-    """
     res = resource_stream("talerblog", resource_name)
     soup = BeautifulSoup(res, 'html.parser')
     res.close()
diff --git a/talerblog/blog/static/web-common b/talerblog/blog/static/web-common
index 0a65d59..e9554ba 160000
--- a/talerblog/blog/static/web-common
+++ b/talerblog/blog/static/web-common
@@ -1 +1 @@
-Subproject commit 0a65d5985b0474b4597dc2936f5791559c2a8a5a
+Subproject commit e9554baf0f3f880d656284ef5e9089bbd8313464
diff --git a/talerblog/blog/templates/base.html 
b/talerblog/blog/templates/base.html
index 98ce2e3..fa8b813 100644
--- a/talerblog/blog/templates/base.html
+++ b/talerblog/blog/templates/base.html
@@ -62,6 +62,7 @@
       <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', '#') 
}}">Tipping/Survey</a></li>
+      <li><a href="{{ env('TALER_ENV_URL_BACKOFFICE', '#') 
}}">Back-office</a></li>
     </ul>
     <p>You can learn more about Taler on our main <a 
href="https://taler.net";>website</a>.</p>
     <div style="flex-grow:1"></div>
diff --git a/talerblog/blog/templates/javascript.html 
b/talerblog/blog/templates/javascript.html
index 8f27425..436c186 100644
--- a/talerblog/blog/templates/javascript.html
+++ b/talerblog/blog/templates/javascript.html
@@ -1,17 +1,31 @@
 <!-- This file is in the public domain -->
+
 <html>
-<body>
-<table id="jslicense-labels1">
-<tr>
-  <td><a 
href="/static/web-common/taler-wallet-lib.js">taler-wallet-lib.js</a></td>
-  <td><a href="https://www.gnu.org/licenses/lgpl-2.1.html";>LGPL</a></td>
-  <td><a 
href="/static/web-common/taler-wallet-lib.js.tar.gz">taler-wallet-lib.js.tar.gz</a></td>
-</tr>
-<tr>
-  <td><a 
href="/static/web-common/dropdown-navbar_script.js">dropdown-navbar_script.js</a></td>
-  <td><a href="https://www.gnu.org/licenses/lgpl-2.1.html";>LGPL</a></td>
-  <td><a 
href="/static/web-common/dropdown-navbar_script.js">dropdown-navbar_script.js</a></td>
-</tr>
-</table>
-</body>
+  <head>
+    <title>JavaScript disclaimer.</title>
+  </head>
+  <body>
+    <h3>This site does not use JavaScript.</h3>
+  </body>
 </html>
+
+<!-- The following lines are kept as a template for future inclusion of 
JavaScript files. -->
+
+<!--
+  <html>
+  <body>
+  <table id="jslicense-labels1">
+  <tr>
+    <td><a href="/static/path/to/example0.js">example0.js</a></td>
+    <td><a href="https://www.gnu.org/licenses/lgpl-2.1.html";>LGPL</a></td>
+    <td><a 
href="/static/path/to/example0.js.tar.gz">example0.js.tar.gz</a></td>
+  </tr>
+  <tr>
+    <td><a href="/static/path/to/example1.js">example1.js</a></td>
+    <td><a href="https://www.gnu.org/licenses/lgpl-2.1.html";>LGPL</a></td>
+    <td><a 
href="/static/path/to/example1.js.tar.gz">example1.js.tar.gz</a></td>
+  </tr>
+  </table>
+  </body>
+  </html>
+-->
diff --git a/talerblog/tests.py b/talerblog/tests.py
index 8ad3556..a5d1e8e 100644
--- a/talerblog/tests.py
+++ b/talerblog/tests.py
@@ -1,3 +1,21 @@
+##
+# This file is part of GNU TALER.
+# Copyright (C) 2014-2017 INRIA
+#
+# 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 Marcello Stanisci
+# @brief Test cases for the blog.
+
 #!/usr/bin/env python3
 
 import unittest
@@ -10,12 +28,24 @@ TC = TalerConfig.from_env()
 CURRENCY = TC["taler"]["currency"].value_string(required=True)
 LOGGER = logging.getLogger(__name__)
 
+
+##
+# Main class that gathers all the tests.
 class BlogTestCase(unittest.TestCase):
     def setUp(self):
         blog.app.testing = True
         self.app = blog.app.test_client()
         self.instance = TC["blog"]["instance"].value_string(required=True)
 
+
+
+    ##
+    # Test the refund logic.
+    #
+    # @param self the object itself.
+    # @param mocked_session mock object pretending to be the flask session.
+    # @param mocked_post mock function pretending to be 'requests.post'
+    # @param mocked_get mock function pretending to be 'requests.get'
     @patch("requests.get")
     @patch("requests.post")
     @patch("flask.session")

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



reply via email to

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