Select Git revision
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
template_helper.py 8.29 KiB
import subprocess
from time import mktime
from email.utils import formatdate
from socket import gethostname
from ipaddress import ip_address, ip_network
import base64
from server import *
app.jinja_env.trim_blocks = True #pylint: disable=no-member
app.jinja_env.lstrip_blocks = True #pylint: disable=no-member
app.add_template_global(random.randint, name='randint')
app.add_template_global(datetime, name='datetime')
app.add_template_global(timedelta, name='timedelta')
app.add_template_global(gethostname, name='gethostname')
app.add_template_global(min, name='min')
app.add_template_global(max, name='max')
# get git commit
GITOUTPUT = subprocess.check_output(['git', "log", "-g", "-1", "--pretty=%H#%h#%d#%s"]).decode('UTF-8').split('#', 3)
app.jinja_env.globals['gitversion'] = {'hash': GITOUTPUT[1], 'longhash': GITOUTPUT[0], 'branch': GITOUTPUT[2], 'msg': GITOUTPUT[3]} #pylint: disable=no-member
@app.url_defaults
def static_version_inject(endpoint, values):
if endpoint == 'static':
values['v'] = app.jinja_env.globals['gitversion']['longhash'] #pylint: disable=no-member
@app.template_global()
def ismod(*args): #pylint: disable=unused-argument
return 'user' in session
app.jinja_env.globals['navbar'] = [] #pylint: disable=no-member
# iconlib can be 'bootstrap'
# ( see: http://getbootstrap.com/components/#glyphicons )
# or 'fa'
# ( see: http://fontawesome.io/icons/ )
def register_navbar(name, iconlib='bootstrap', icon=None, userendpoint=False, group=None, endpoint=None): #pylint: disable=too-many-arguments
def wrapper(func):
urlendpoint = endpoint
if not endpoint:
urlendpoint = func.__name__
item = {}
item['iconlib'] = iconlib
item['icon'] = icon
item['userendpoint'] = userendpoint
item['group'] = group
item['endpoint'] = urlendpoint
item['visible'] = not urlendpoint in mod_endpoints
item['name'] = name
app.jinja_env.globals['navbar'].append(item) #pylint: disable=no-member
return func
return wrapper
csrf_endpoints = [] #pylint: disable=invalid-name
def csrf_protect(func):
csrf_endpoints.append(func.__name__)
@wraps(func)
def decorator(*args, **kwargs):
if '_csrf_token' in request.values:
token = request.values['_csrf_token']
elif request.get_json() and ('_csrf_token' in request.get_json()):
token = request.get_json()['_csrf_token']
else:
token = None
if ('_csrf_token' not in session) or (session['_csrf_token'] != token) or not token:
return 'csrf test failed', 403
else:
return func(*args, **kwargs)
return decorator
@app.url_defaults
def csrf_inject(endpoint, values):
if endpoint not in csrf_endpoints or not session.get('_csrf_token'):
return
values['_csrf_token'] = session['_csrf_token']
@app.template_filter()
def base64encode(str):
try:
return base64.b64encode(str.encode('UTF-8')).decode('UTF-8')
except: #pylint: disable=bare-except
return ''
@app.template_filter()
def checkperm(perms, username=None, password=None): #pylint: disable=too-many-branches,too-many-return-statements
if ismod():
return True
perms = evalperm(perms)
for perm in perms:
if perm['type'] == 'public':
return True
elif perm['type'] == 'password':
if perm['param1'] == username and perm['param2'] == password:
return True
elif perm['type'] == 'l2p':
if perm['param1'] in session.get('l2p_courses', []):
return True
elif perm['type'] == 'moodle':
if perm['param1'] in session.get('moodle_courses', []):
return True
elif perm['type'] == 'rwth':
if session.get('rwthintern', False):
return True
if 'X-Real-IP' not in request.headers:
continue
ip = ip_address(request.headers['X-Real-IP'])
for net in config['RWTH_IP_RANGES']:
if ip in ip_network(net):
return True
return False
def checkperm_array(perms, auth_data):
for username, password in auth_data.items():
if checkperm(perms, username, password):
return True
# Authentication can also be performed without username/password
if checkperm(perms):
return True
return False
def permtypes(perms): #pylint: disable=too-many-branches,too-many-return-statements
perms = evalperm(perms)
perm_set = set()
for perm in perms:
perm_set.add(perm['type'])
return list(perm_set)
@app.template_filter()
def permdescr(perms): #pylint: disable=too-many-branches,too-many-return-statements
perms = evalperm(perms)
public = False
password = False
l2p_courses = []
moodle_courses = []
rwth_intern = False
fsmpi_intern = False
for perm in perms:
if perm['type'] == 'public':
public = True
elif perm['type'] == 'password':
password = True
elif perm['type'] == 'l2p':
l2p_courses.append(perm['param1'])
elif perm['type'] == 'moodle':
moodle_courses.append(perm['param1'])
elif perm['type'] == 'rwth':
rwth_intern = True
elif perm['type'] == 'fsmpi':
fsmpi_intern = True
if public or not perms:
return 'public', 'Öffentlich verfügbar'
if rwth_intern:
if password:
return 'rwth', 'Nur für RWTH-Angehörige und Nutzer mit Passwort verfügbar'
return 'rwth', 'Nur für RWTH-Angehörige verfügbar'
if fsmpi_intern:
return 'fsmpi', 'Nur für Fachschaftler verfügbar'
if l2p_courses:
if password:
if moodle_courses:
return 'l2pandmoodle', 'Nur für Teilnehmer der Veranstaltung und Nutzer mit Passwort verfügbar'
return 'l2p', 'Nur für Teilnehmer der Veranstaltung und Nutzer mit Passwort verfügbar'
if moodle_courses:
return 'l2pandmoodle', 'Nur für Teilnehmer der Veranstaltung verfügbar'
return 'l2p', 'Nur für Teilnehmer der Veranstaltung verfügbar'
if moodle_courses:
if password:
if l2p_courses:
return 'l2pandmoodle', 'Nur für Teilnehmer der Veranstaltung und Nutzer mit Passwort verfügbar'
return 'moodle', 'Nur für Teilnehmer der Veranstaltung und Nutzer mit Passwort verfügbar'
if l2p_courses:
return 'l2pandmoodle', 'Nur für Teilnehmer der Veranstaltung verfügbar'
return 'moodle', 'Nur für Teilnehmer der Veranstaltung verfügbar'
if password:
return 'password', 'Nur für Nutzer mit Passwort verfügbar'
return 'none', 'Nicht verfügbar'
# debian ships jinja2 without this test...
@app.template_test(name='equalto')
def equalto(value_a, value_b):
return value_a == value_b
@app.template_filter(name='filterdict')
def jinja2_filterdict(value, attrdel):
value = dict(value)
for attr in attrdel:
if attr in value:
del value[attr]
return dict(value)
@app.template_filter(name='semester')
def human_semester(value, long=False):
if not value or value == 'zeitlos' or len(value) != 6:
return 'Zeitlos'
year = value[0:4]
semester = value[4:6].upper()
if not year.isdigit() or semester not in ['SS', 'WS']:
print('Invalid semester string "%s"'%value)
return '??'
if not long:
return semester+year[2:]
elif semester == 'SS':
return 'Sommersemester %s'%year
else:
return 'Wintersemester %s/%s'%(year, str(int(year)+1)[2:])
@app.template_filter(name='date')
def human_date(value):
return value.strftime('%d.%m.%Y')
@app.template_filter(name='fulldate')
def human_fulldate(value):
return value.strftime('%a, %d.%m.%Y, %H:%M Uhr')
@app.template_filter(name='time')
def human_time(value):
return value.strftime('%H:%M')
@app.template_filter()
def rfc3339(value):
return value.strftime('%Y-%m-%dT%H:%M:%S+02:00')
@app.template_filter()
def time_offset(value):
return '%02d:%02d:%02d'%(value//3600, (value//60)%60, value%60)
@app.template_filter()
def rfc822(value):
return formatdate(mktime(value.timetuple()))
@app.template_global()
def get_announcements(minlevel=0):
offset = timedelta()
if ismod():
offset = timedelta(hours=24)
try:
return query('SELECT * FROM announcements WHERE \
NOT deleted AND \
((time_expire = NULL) OR time_expire > ?) AND \
(? OR (visible AND time_publish < ?)) AND \
level >= ? \
ORDER BY level DESC',
datetime.now()-offset, ismod(), datetime.now(), minlevel)
except: #pylint: disable=bare-except
return []
@app.template_filter()
def fixnl(value):
# To be remove, as soon as db schema is cleaned-up
return str(value).replace('\n', '<br>')
@app.template_filter()
def tagid(value):
if not value:
return 'EMPTY'
value = value.replace(' ', '_').lower()
result = ''
for char in value:
if char in string.ascii_lowercase+string.digits+'_':
result = result + char
return result
@app.template_global()
def is_readonly():
try:
return show('SHOW GLOBAL STATUS LIKE "wsrep_ready"')['wsrep_ready'] != 'ON'
except: #pylint: disable=bare-except
return True