Use Jinja2 strict rendering.

For this I had to create an Jinja2 explicit environment, so I put a
function in `ihatemoney.utils.create_jinja2_env(strict_rendering=False)`.

When using this environment and if `strict_rendering` is activated,
templates using undefined variables will now error out rather than
failing silently.
This commit is contained in:
Alexis Métaireau 2018-01-14 16:52:52 +01:00
parent 0504fd82f5
commit 230eafdf58
3 changed files with 24 additions and 12 deletions

View file

@ -1,8 +1,7 @@
<VirtualHost *:80> <VirtualHost *:80>
ServerAdmin admin@example.com # CUSTOMIZE ServerAdmin admin@example.com # CUSTOMIZE
ServerName ihatemoney.example.com # CUSTOMIZE ServerName ihatemoney.example.com # CUSTOMIZE
WSGIDaemonProcess ihatemoney user=www-data group=www-data threads=5 python-path={{ pkg_path }} {% if bin_path %}python-home={{ bin_path }}{% endif %}
WSGIDaemonProcess ihatemoney user=www-data group=www-data threads=5 python-path={{ pkg_path }} {% if venv_path %}python-home={{ venv_path }}{% endif %}
WSGIScriptAlias / {{ pkg_path }}/wsgi.py WSGIScriptAlias / {{ pkg_path }}/wsgi.py
WSGIPassAuthorization On WSGIPassAuthorization On

View file

@ -1,18 +1,17 @@
#!/usr/bin/env python #!/usr/bin/env python
import os import os
import pkgutil
import random import random
import sys import sys
import getpass import getpass
from flask_script import Manager, Command, Option from flask_script import Manager, Command, Option
from flask_migrate import Migrate, MigrateCommand from flask_migrate import Migrate, MigrateCommand
from jinja2 import Template
from werkzeug.security import generate_password_hash from werkzeug.security import generate_password_hash
from ihatemoney.run import create_app from ihatemoney.run import create_app
from ihatemoney.models import db from ihatemoney.models import db
from ihatemoney.utils import create_jinja_env
class GeneratePasswordHash(Command): class GeneratePasswordHash(Command):
@ -44,15 +43,14 @@ class GenerateConfig(Command):
for i in range(50)]) for i in range(50)])
def run(self, config_file): def run(self, config_file):
template_content = pkgutil.get_data( env = create_jinja_env('conf-templates', strict_rendering=True)
'ihatemoney', template = env.get_template('%s.j2' % config_file)
os.path.join('conf-templates/', config_file) + '.j2'
).decode('utf-8')
bin_path = os.path.dirname(sys.executable) bin_path = os.path.dirname(sys.executable)
pkg_path = os.path.abspath(os.path.dirname(__file__))
print(Template(template_content).render( print(template.render(
pkg_path=os.path.abspath(os.path.dirname(__file__)), pkg_path=pkg_path,
bin_path=bin_path, bin_path=bin_path,
secret_key=self.gen_secret_key(), secret_key=self.gen_secret_key(),
)) ))

View file

@ -2,7 +2,7 @@ import base64
import re import re
from io import BytesIO, StringIO from io import BytesIO, StringIO
from jinja2 import filters import jinja2
from json import dumps from json import dumps
from flask import redirect from flask import redirect
from werkzeug.routing import HTTPException, RoutingException from werkzeug.routing import HTTPException, RoutingException
@ -83,7 +83,7 @@ def minimal_round(*args, **kw):
from http://stackoverflow.com/questions/28458524/ from http://stackoverflow.com/questions/28458524/
""" """
# Use the original round filter, to deal with the extra arguments # Use the original round filter, to deal with the extra arguments
res = filters.do_round(*args, **kw) res = jinja2.filters.do_round(*args, **kw)
# Test if the result is equivalent to an integer and # Test if the result is equivalent to an integer and
# return depending on it # return depending on it
ires = int(res) ires = int(res)
@ -170,3 +170,18 @@ class LoginThrottler():
def reset(self, ip): def reset(self, ip):
self._attempts.pop(ip, None) self._attempts.pop(ip, None)
def create_jinja_env(folder, strict_rendering=False):
"""Creates and return a Jinja2 Environment object, used, to load the
templates.
:param strict_rendering:
if set to `True`, all templates which use an undefined variable will
throw an exception (default to `False`).
"""
loader = jinja2.PackageLoader('ihatemoney', folder)
kwargs = {'loader': loader}
if strict_rendering:
kwargs['undefined'] = jinja2.StrictUndefined
return jinja2.Environment(**kwargs)