334 lines
11 KiB
Python
334 lines
11 KiB
Python
from django.shortcuts import render, get_object_or_404, redirect, resolve_url
|
|
from django.views.generic import TemplateView, RedirectView
|
|
from django.views.generic.detail import DetailView
|
|
from django.views.generic.list import ListView
|
|
from django.views.generic.edit import CreateView, UpdateView
|
|
from django.core.exceptions import SuspiciousOperation
|
|
from django.contrib import auth
|
|
|
|
from markdown2 import markdown
|
|
|
|
from . import models, forms
|
|
|
|
import logging
|
|
logger = logging.getLogger(__name__)
|
|
|
|
#from django.core.signing import Signer
|
|
#signer = Signer()
|
|
|
|
#def signed_url(name, **kwargs):
|
|
# url = resolve_url(name, **kwargs)
|
|
# sig = signer.sign(url)
|
|
# return sig.replace(":", "?auth=")
|
|
|
|
class EnsembleMixin(object):
|
|
admin_required = False
|
|
|
|
def dispatch(self, request, *args, **kwargs):
|
|
|
|
request.ensemble_id = request.session.get('ensemble')
|
|
request.is_admin = request.user.is_superuser
|
|
|
|
if request.is_admin:
|
|
if request.ensemble_id is None:
|
|
return redirect('ensemble_list')
|
|
return super().dispatch(request, *args, **kwargs)
|
|
|
|
# if 'auth' in request.GET:
|
|
# sig = signer.sign(request.path)
|
|
# if sig[len(request.path)+1:] == request.GET['auth']:
|
|
# logger.info("Allowing auth key")
|
|
# request.is_admin = True
|
|
# return super().dispatch(request, *args, **kwargs)
|
|
# else:
|
|
# raise SuspiciousOperation("Bad auth code")
|
|
|
|
if request.user.is_authenticated:
|
|
try:
|
|
request.user.ensembles.get(pk=request.ensemble_id)
|
|
request.is_admin = True
|
|
except models.Ensemble.DoesNotExist:
|
|
pass
|
|
|
|
if not request.ensemble_id:
|
|
return redirect('register')
|
|
|
|
if self.admin_required and not request.is_admin:
|
|
return redirect('login')
|
|
|
|
return super().dispatch(request, *args, **kwargs)
|
|
|
|
@property
|
|
def ensemble(self):
|
|
return models.Ensemble.objects.get(pk=self.request.ensemble_id)
|
|
|
|
#def get_context_data(self, **kwargs):
|
|
# context = super().get_context_data(**kwargs)
|
|
# context['ensemble'] = self.ensemble
|
|
# return context
|
|
|
|
class ProjectMixin(EnsembleMixin):
|
|
|
|
def get_project(self):
|
|
if not hasattr(self, '_project'):
|
|
if self.request.is_admin: # can access any ensemble
|
|
self._project = get_object_or_404(models.Project, pk=self.kwargs['project'])
|
|
else:
|
|
self._project = get_object_or_404(models.Project,
|
|
pk=self.kwargs['project'], ensemble=self.request.ensemble_id)
|
|
return self._project
|
|
|
|
def get_queryset(self):
|
|
return super().get_queryset().filter(project=self.get_project())
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
context['project'] = self.get_project()
|
|
context['modules'] = context['project'].modules.values_list('name', flat=True)
|
|
return context
|
|
|
|
def register(request):
|
|
|
|
if 'clear' in request.GET:
|
|
request.session.clear()
|
|
|
|
request.ensemble_id = request.session.get('ensemble')
|
|
registered = request.session.setdefault('registered', [])
|
|
|
|
code = request.GET.get('code', '').replace('-', '')
|
|
logger.debug("Registering with code %s", code)
|
|
|
|
# check if already joined
|
|
if code in registered or request.user.is_superuser:
|
|
request.session['ensemble'] = models.Ensemble.objects.get(code=code).pk
|
|
return redirect('ensemble_detail')
|
|
|
|
if request.method == "POST":
|
|
form = forms.CodeForm(request.POST)
|
|
|
|
if form.is_valid():
|
|
|
|
data = form.cleaned_data
|
|
try:
|
|
ensemble = models.Ensemble.objects.get(code=data['code'].replace('-', ''))
|
|
if ensemble.passphrase.lower() == data['passphrase'].lower():
|
|
request.session['ensemble'] = ensemble.pk
|
|
registered.append(ensemble.code)
|
|
return redirect('ensemble_detail')
|
|
except models.Ensemble.DoesNotExist:
|
|
form.add_error(None, "Incorrect code or passphrase")
|
|
|
|
|
|
|
|
else:
|
|
form = forms.CodeForm(initial=request.GET)
|
|
|
|
if request.user.is_superuser:
|
|
current = models.Ensemble.objects.all()
|
|
else:
|
|
current = models.Ensemble.objects.filter(pk__in=registered)
|
|
|
|
return render(request, 'interface/register.html', {'form': form, 'current': current})
|
|
|
|
def on_login(sender, **kwargs):
|
|
user = kwargs['user']
|
|
request = kwargs['request']
|
|
registered = request.session.get('registered', [])
|
|
for e in user.ensembles.all():
|
|
if not e.code in registered:
|
|
registered.append(e.code)
|
|
request.session['registered'] = registered
|
|
auth.signals.user_logged_in.connect(on_login)
|
|
|
|
def logout(request):
|
|
ensemble = request.session.get('ensemble')
|
|
registered = request.session.get('registered', {})
|
|
auth.logout(request)
|
|
request.session['ensemble'] = ensemble
|
|
request.session['registered'] = registered
|
|
return redirect('/')
|
|
|
|
class EnsembleForgetView(EnsembleMixin, RedirectView):
|
|
|
|
def get_redirect_url(self, *args, **kwargs):
|
|
|
|
registered = self.request.session.setdefault('registered', [])
|
|
|
|
ensemble = models.Ensemble.objects.get(pk=self.kwargs['pk'])
|
|
try:
|
|
registered.remove(ensemble.code)
|
|
self.request.session['registered'] = registered
|
|
except KeyError:
|
|
pass
|
|
|
|
if self.request.ensemble_id == ensemble.pk:
|
|
del(self.request.session['ensemble'])
|
|
|
|
return resolve_url('ensemble_detail')
|
|
|
|
class EnsembleListView(ListView):
|
|
|
|
def get_queryset(self):
|
|
registered = self.request.session.get('registered', [])
|
|
if self.request.user.is_superuser:
|
|
current = models.Ensemble.objects.all()
|
|
else:
|
|
current = models.Ensemble.objects.filter(code__in=registered)
|
|
|
|
return current
|
|
|
|
#def get_context_data(self, **kwargs):
|
|
# context = super().get_context_data(**kwargs)
|
|
# context['ensemble_id'] = self.request.session.get('ensemble')
|
|
# return context
|
|
|
|
class EnsembleProjectListView(EnsembleMixin, DetailView):
|
|
template_name = 'interface/ensemble_project_list.html'
|
|
|
|
def dispatch(self, request, *args, **kwargs):
|
|
# capture provided urls
|
|
if 'code' in request.GET:
|
|
return redirect('/register?code={0}'.format(request.GET['code']))
|
|
|
|
return super().dispatch(request, *args, **kwargs)
|
|
|
|
def get_object(self):
|
|
return models.Ensemble.objects.get(pk=self.request.ensemble_id)
|
|
|
|
def get_context_data(self, **kwargs):
|
|
data = super().get_context_data(**kwargs)
|
|
if self.request.is_admin:
|
|
data['ensemble_url'] = self.request.build_absolute_uri('/?code={0}'.format(self.ensemble.ensemble_code()))
|
|
return data
|
|
|
|
class EnsembleDetailView(DetailView):
|
|
model = models.Ensemble
|
|
|
|
class ProjectDetailView(ProjectMixin, DetailView):
|
|
|
|
def get_object(self):
|
|
return self.get_project()
|
|
|
|
class ProjectCreateView(EnsembleMixin, CreateView):
|
|
model = models.Project
|
|
template_name = "interface/default_form.html"
|
|
title = "Add a new project"
|
|
form_class = forms.ProjectForm
|
|
|
|
def form_valid(self, form):
|
|
self.object = form.save(commit=False)
|
|
self.object.ensemble_id = self.request.ensemble_id
|
|
self.object.owner = self.request.user
|
|
self.object.save()
|
|
return redirect('project_detail', project=self.object.pk)
|
|
|
|
class ProjectUpdateView(EnsembleMixin, UpdateView):
|
|
model = models.Project
|
|
template_name = "interface/default_form.html"
|
|
#fields = ['name', 'description', 'event_date', 'enable_library', 'enable_submissions', 'active']
|
|
pk_url_kwarg = 'project'
|
|
form_class = forms.ProjectForm
|
|
|
|
def get_success_url(self):
|
|
return resolve_url('project_detail', project=self.kwargs['project'])
|
|
|
|
#class ProjectMakefileView(EnsembleMixin, DetailView):
|
|
# template_name = 'interface/project_submissions.mk'
|
|
# content_type = 'text/plain'
|
|
#
|
|
# def get_queryset(self):
|
|
# if self.request.is_admin:
|
|
# return models.Project.objects.all()
|
|
#
|
|
# return models.Project.objects.filter(ensemble=self.request.ensemble_id)
|
|
#
|
|
# def get_context_data(self, **kwargs):
|
|
# data = super().get_context_data(**kwargs)
|
|
#
|
|
# data['submissions'] = []
|
|
# data['targets'] = []
|
|
# for s in self.object.submissions:
|
|
# name = s.short_name
|
|
# data['targets'].append(name)
|
|
# data['submissions'].append({
|
|
# 'url': self.request.build_absolute_uri(signed_url('submission_download', project=self.kwargs['pk'], pk=s.pk)),
|
|
# 'name': name,
|
|
# })
|
|
#
|
|
# return data
|
|
|
|
class WikiView(ProjectMixin, DetailView):
|
|
template_name = 'interface/wiki.html'
|
|
model = models.WikiPage
|
|
|
|
def get_context_data(self, **kwargs):
|
|
data = super().get_context_data(**kwargs)
|
|
data['wiki_html'] = markdown(self.object.markdown)
|
|
return data
|
|
|
|
class WikiCreateView(ProjectMixin, CreateView):
|
|
admin_required = True
|
|
model = models.WikiPage
|
|
fields = ['title', 'markdown']
|
|
|
|
def form_valid(self, form):
|
|
self.object = form.save(commit=False)
|
|
self.object.project = self.get_project()
|
|
self.object.save()
|
|
return redirect('wiki', project=self.object.project_id, pk=self.object.pk)
|
|
|
|
class WikiEditView(ProjectMixin, UpdateView):
|
|
admin_required = True
|
|
model = models.WikiPage
|
|
fields = ['title', 'markdown']
|
|
|
|
|
|
class ResourceCreateView(ProjectMixin, CreateView):
|
|
model = models.Resource
|
|
form_class = forms.ResourceForm
|
|
template_name = 'interface/project_form.html'
|
|
title = "Add a new resource"
|
|
admin_required = True
|
|
|
|
def form_valid(self, form):
|
|
self.object = form.save(commit=False)
|
|
self.object.project = self.get_project()
|
|
self.object.save()
|
|
return redirect('resource_upload', project=self.object.project_id, pk=self.object.pk)
|
|
|
|
class ResourceUploadView(ProjectMixin, UpdateView):
|
|
admin_required = True
|
|
model = models.Resource
|
|
fields = ['file']
|
|
template_name = 'interface/default_form.html'
|
|
|
|
def get_success_url(self):
|
|
return resolve_url('resource_list', project=self.kwargs['project'])
|
|
|
|
class ResourceListView(ProjectMixin, ListView):
|
|
model = models.Resource
|
|
|
|
def get_queryset(self):
|
|
qs = super().get_queryset()
|
|
if not self.request.is_admin:
|
|
qs = qs.filter(visible=True)
|
|
return qs
|
|
|
|
class ResourceEditView(ProjectMixin, UpdateView):
|
|
admin_required = True
|
|
model = models.Resource
|
|
fields = ['name', 'description', 'visible']
|
|
template_name = 'interface/default_form.html'
|
|
|
|
def get_success_url(self):
|
|
return resolve_url('resource_list', project=self.kwargs['project'])
|
|
|
|
class ManageView(EnsembleMixin, TemplateView):
|
|
template_name = 'interface/manage.html'
|
|
admin_required = True
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
context['ensemble'] = models.Ensemble.objects.get(pk=self.request.ensemble_id)
|
|
context['ensemble_url'] = self.request.build_absolute_uri('/?code={0}'.format(context['ensemble'].ensemble_code()))
|
|
return context |