Implemented makefile building #6

Merged
tris merged 1 commits from build_chain into master 2020-11-23 13:51:17 +11:00
5 changed files with 89 additions and 2 deletions

View File

@ -131,5 +131,16 @@ class Submission(models.Model):
slugify(self.instrument) slugify(self.instrument)
) )
@property
def short_name(self):
_, ext = os.path.splitext(self.download_name)
return "{}_{}_{}{}".format(
#timezone.localtime(self.date).strftime("%Y%m%d%H%M%S"),
slugify(self.name),
slugify(self.instrument),
self.pk,
ext
)
def __str__(self): def __str__(self):
return f"{self.name}: {self.date}" return f"{self.name}: {self.date}"

View File

@ -0,0 +1,11 @@
ALL = {{ targets|join:" " }}
-include "local.mk"
all: ${ALL}
{% for s in submissions %}
{{ s.name }}:
curl -o $@ -L {{ s.url }}
{% endfor %}

View File

@ -1,6 +1,12 @@
{% extends "interface/project_base.html" %} {% extends "interface/project_base.html" %}
{% block page %} {% block page %}
<div class="admin-tools">
<a href="{{ signed_url }}">
<i class="fas fa-list"></i>
</a>
</div>
<table style="max-width: 800px; margin: 10pt auto;"> <table style="max-width: 800px; margin: 10pt auto;">
<thead> <thead>
<tr> <tr>

View File

@ -12,6 +12,7 @@ urlpatterns = [
path('', views.EnsembleDetailView.as_view(), name='ensemble_detail'), path('', views.EnsembleDetailView.as_view(), name='ensemble_detail'),
path('projects/<int:pk>', views.ProjectDetailView.as_view(), name="project_detail"), path('projects/<int:pk>', views.ProjectDetailView.as_view(), name="project_detail"),
path('projects/<int:pk>/submissions.mk', views.ProjectMakefileView.as_view(), name="project_makefile"),
path('projects/<int:project>/page/<int:pk>', views.WikiView.as_view(), name="wiki"), path('projects/<int:project>/page/<int:pk>', views.WikiView.as_view(), name="wiki"),
path('projects/<int:project>/page/<int:pk>/edit', views.WikiEditView.as_view(), name="wiki_edit"), path('projects/<int:project>/page/<int:pk>/edit', views.WikiEditView.as_view(), name="wiki_edit"),
@ -23,6 +24,7 @@ urlpatterns = [
path('projects/<int:project>/submission/<int:pk>/upload', views.SubmissionUploadView.as_view(), name="submission_upload"), path('projects/<int:project>/submission/<int:pk>/upload', views.SubmissionUploadView.as_view(), name="submission_upload"),
path('projects/<int:project>/submission/<int:pk>/cancel', views.SubmissionCancelView.as_view(), name="submission_cancel"), path('projects/<int:project>/submission/<int:pk>/cancel', views.SubmissionCancelView.as_view(), name="submission_cancel"),
path('projects/<int:project>/submission/<int:pk>/complete', views.SubmissionCompleteView.as_view(), name="submission_complete"), path('projects/<int:project>/submission/<int:pk>/complete', views.SubmissionCompleteView.as_view(), name="submission_complete"),
path('projects/<int:project>/submission/<int:pk>/download', views.SubmissionDownloadView.as_view(), name="submission_download"),
path('projects/<int:project>/submissions', views.SubmissionListView.as_view(), name="submission_list"), path('projects/<int:project>/submissions', views.SubmissionListView.as_view(), name="submission_list"),
path('projects/<int:project>/resources', views.ResourceListView.as_view(), name="resource_list"), path('projects/<int:project>/resources', views.ResourceListView.as_view(), name="resource_list"),

View File

@ -6,6 +6,7 @@ from django.views.generic.edit import CreateView, UpdateView, FormView
from django.views.generic.base import ContextMixin from django.views.generic.base import ContextMixin
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.core.exceptions import SuspiciousOperation from django.core.exceptions import SuspiciousOperation
from django.core.signing import Signer
from django.contrib import auth from django.contrib import auth
from markdown2 import markdown from markdown2 import markdown
@ -20,6 +21,13 @@ from base64 import b64decode
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
signer = Signer()
def signed_url(name, **kwargs):
url = resolve_url(name, **kwargs)
sig = signer.sign(url)
return sig.replace(":", "?auth=")
class EnsembleMixin(object): class EnsembleMixin(object):
admin_required = False admin_required = False
@ -28,6 +36,15 @@ class EnsembleMixin(object):
request.ensemble_id = request.session.get('ensemble') request.ensemble_id = request.session.get('ensemble')
request.is_admin = request.user.is_superuser request.is_admin = request.user.is_superuser
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 not request.ensemble_id: if not request.ensemble_id:
return redirect('register') return redirect('register')
@ -47,8 +64,11 @@ class ProjectMixin(EnsembleMixin):
def get_project(self): def get_project(self):
if not hasattr(self, '_project'): if not hasattr(self, '_project'):
self._project = get_object_or_404(models.Project, if self.request.is_admin: # can access any ensemble
pk=self.kwargs['project'], ensemble=self.request.ensemble_id) 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 return self._project
def get_queryset(self): def get_queryset(self):
@ -192,6 +212,31 @@ class ProjectDetailView(EnsembleMixin, DetailView):
def get_queryset(self): def get_queryset(self):
return models.Project.objects.filter(ensemble=self.request.ensemble_id) return models.Project.objects.filter(ensemble=self.request.ensemble_id)
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): class WikiView(ProjectMixin, DetailView):
template_name = 'interface/wiki.html' template_name = 'interface/wiki.html'
model = models.WikiPage model = models.WikiPage
@ -245,6 +290,13 @@ class SubmissionCompleteView(ProjectMixin, S3CompleteView):
def get_redirect_url(self, **kwargs): def get_redirect_url(self, **kwargs):
return resolve_url('submission_detail', **self.kwargs) return resolve_url('submission_detail', **self.kwargs)
class SubmissionDownloadView(ProjectMixin, SingleObjectMixin, RedirectView):
model = models.Submission
admin_required = True
def get_redirect_url(self, **kwargs):
return self.get_object().download_url
class SubmissionDetailView(ProjectMixin, DetailView): class SubmissionDetailView(ProjectMixin, DetailView):
model = models.Submission model = models.Submission
@ -307,6 +359,11 @@ class SubmissionListView(ProjectMixin, ListView):
def get_queryset(self): def get_queryset(self):
return super().get_queryset().filter(complete=True).order_by('-pk') return super().get_queryset().filter(complete=True).order_by('-pk')
def get_context_data(self, **kwargs):
data = super().get_context_data(**kwargs)
data['signed_url'] = self.request.build_absolute_uri(signed_url('project_makefile', pk=self.kwargs['project']))
return data
class ResourceCreateView(ProjectMixin, CreateView): class ResourceCreateView(ProjectMixin, CreateView):
model = models.Resource model = models.Resource
fields = ['name', 'media_type', 'description'] fields = ['name', 'media_type', 'description']