from django.shortcuts import render from django.http import HttpResponseForbidden, Http404 from django.conf import settings from django.utils.safestring import mark_safe from django.contrib.auth.decorators import login_required from django.db.models import Q import codecs import os import re import markdown from postgresqleu.confreg.models import Conference, ConferenceSeries from postgresqleu.util.auth import PERMISSION_GROUPS reTitle = re.compile('

([^<]+)

') _reSvgInline = re.compile(r'([^') def _replaceSvgInline(m, section): # Group 1 = alt text # Group 2 = filename excluding svg filename = 'docs/{0}/{1}.svg'.format(section, m.group(2)) if not os.path.isfile(filename): return m.group(0) with codecs.open(filename, 'r', 'utf8') as f: return f.read() @login_required def docspage(request, page=None): # Allow a person who has *any* permissions on a conference to read the docs, # because, well, they are docs. # Since we also have docs for non-conference things, check for membership # of *any* permissions groups. if not request.user.is_superuser: q = Q(administrators=request.user) | Q(talkvoters=request.user) if not Conference.objects.filter(q).exists() and \ not ConferenceSeries.objects.filter(administrators=request.user).exists() and \ not request.user.groups.filter(name__in=PERMISSION_GROUPS).exists(): return HttpResponseForbidden("Access denied") if page: page = page.rstrip('/') urlpage = page else: page = "index" urlpage = '' # Do we have the actual docs file? # It's safe to just put the filename in here, because the regexp in urls.py ensures # that we can not get into a path traversal case. # The file can be in different subdirectories though, so enumerate them for d in os.listdir('docs/'): filename = 'docs/{0}/{1}.md'.format(d, page) if os.path.isfile(filename): section = d break else: raise Http404() with open(filename) as f: md = markdown.Markdown(extensions=['markdown.extensions.def_list', 'markdown.extensions.fenced_code']) contents = md.convert(f.read()) contents = _reSvgInline.sub(lambda m: _replaceSvgInline(m, section), contents) # Find the title m = reTitle.search(contents) if m: title = m.group(1) else: title = '{0} Administration'.format(settings.ORG_SHORTNAME) return render(request, 'confreg/admin_backend_docpage.html', { 'basepage': 'adm/admin_base.html', 'page': page, 'contents': contents, 'title': mark_safe(title), 'urlpage': urlpage, })