Finally got authentication to somewhere I'm happy

This commit is contained in:
Tris Forster
2023-02-10 12:01:32 +11:00
parent bc9f292a2e
commit b85440d25c
20 changed files with 415 additions and 171 deletions
+7 -1
View File
@@ -64,7 +64,7 @@ class ProjectItem(models.Model):
approved_by = models.ForeignKey('auth.User', on_delete=models.CASCADE)
order = models.SmallIntegerField(default=0)
section = models.CharField(max_length=100, blank=True)
#version = models.CharField(max_length=30, blank=True, help_text="Limited to specific version tag")
class Meta:
ordering = ['order', 'work']
@@ -101,6 +101,12 @@ class Collection(models.Model):
def genres(self):
return self.meta('genre')
def has_administrator(self, user):
if not user.is_authenticated:
return False
if user.is_superuser:
return True
return user.pk in self.administrators.values_list('pk', flat=True)
def __str__(self):
return self.name
@@ -8,14 +8,14 @@
<div class="column is-half">
<div class="card">
<header class="card-header">
<a class="" href="{% url 'collection_work_list' pk=collection.id %}">
<a class="" href="{% url 'collection_work_list' collection=collection.id %}">
<p class="card-header-title">{{ collection.name }}</p>
</a>
</header>
<div class="card-content">
<p>
{% if collection.location %}{{ collection.location }},{% endif %}
{{ collection.works.count }} items.
{{ collection.works.count }} item{{ collection.works.count|pluralize }}.
</p>
<p>
{% for tag in collection.tags %}
@@ -3,7 +3,8 @@
{% if project %}
<li><a href="{% url 'item_list' project=project.pk %}">My Music</a></li>
{% endif %}
{% if request.is_admin %}
{% if request.user.is_authenticated %}
<li><a href="{% url 'work_list' %}">Library</a></li>
<li><a href="{% url 'collection_list' %}">Collections</a></li>
{% endif %}
</ul>
+3 -3
View File
@@ -29,8 +29,8 @@
<th>Work</th>
<th>Composer</th>
<th class="is-hidden-mobile">Edition</th>
{% if request.is_admin %}
<th class="is-hidden-touch">Collection</th>
{% if request.is_admin %}
<th class="is-hidden-mobile">Copies</th>
{% endif %}
</tr>
@@ -38,11 +38,11 @@
<tbody>
{% for work in object_list %}
<tr>
<td><a href="{% url 'work_detail' pk=work.pk %}">{{ work.name }}</a></td>
<td><a href="{% url 'work_detail' collection=work.collection.pk pk=work.pk %}">{{ work.name }}</a></td>
<td title="{{ work.composer }}">{{ work.composer|truncatewords:3 }}</td>
<td class="is-hidden-mobile" title="{{ work.edition }}">{{ work.edition|truncatewords:2 }}</td>
{% if request.is_admin %}
<td class="is-hidden-touch">{{ work.collection.name }}</td>
{% if request.is_admin %}
<td class="is-hidden-mobile {{ work.is_available|yesno:'has-text-success,has-text-danger' }}">{{ work.available }}</td>
{% endif %}
</tr>
+15 -14
View File
@@ -15,22 +15,23 @@ urlpatterns = [
path('projects/<int:project>/items', views.ProjectItemListView.as_view(), name="item_list"),
path('projects/<int:project>/items/manage', views.ProjectItemManageView.as_view(), name="item_list_manage"),
path('projects/<int:project>/items/append', views.ProjectItemAddView.as_view(), name="item_list_append"),
path('library/collections', views.CollectionListView.as_view(), name="collection_list"),
path('library/collections/<int:pk>', views.CollectionWorkListView.as_view(), name="collection_work_list"),
path('library/collections/<int:pk>/create', views.WorkAddView.as_view(), name="work_add"),
path('library/works', views.WorkListView.as_view(), name="work_list"),
path('library/works/<int:pk>', views.WorkDetailView.as_view(), name="work_detail"),
path('library/works/<int:pk>/edit', views.WorkUpdateView.as_view(), name="work_edit"),
path('library/works/<int:pk>/partset', views.WorkPartSetView.as_view(), name="work_partset"),
path('library/works/<int:pk>/add_to_project', views.WorkAddToProject.as_view(), name="work_add_to_project"),
path('library/works/<int:pk>/upload', views.WorkAddDocumentView.as_view(), name="document_add"),
path('library', views.WorkListView.as_view(), name="work_list"),
path('library/documents/<int:pk>/delete', views.DocumentDeleteView.as_view(), name="document_delete"),
path('library/documents/<int:pk>/download', views.DocumentDownloadView.as_view(), name="document_download"),
path('library/documents/<int:pk>/annotate', views.DocumentAnnotateView.as_view(), name="document_annotate"),
path('library/parts/<int:pk>/<str:filename>', views.PartDownloadView.as_view(), name="part_download"),
path('collections', views.CollectionListView.as_view(), name="collection_list"),
path('collections/<int:collection>', views.CollectionWorkListView.as_view(), name="collection_work_list"),
path('collections/<int:collection>/add', views.WorkAddView.as_view(), name="work_add"),
path('collections/<int:collection>/works/<int:pk>', views.WorkDetailView.as_view(), name="work_detail"),
path('collections/<int:collection>/works/<int:pk>/edit', views.WorkUpdateView.as_view(), name="work_edit"),
path('collections/<int:collection>/works/<int:pk>/partset', views.WorkPartSetView.as_view(), name="work_partset"),
path('collections/<int:collection>/works/<int:pk>/add_to_project', views.WorkAddToProject.as_view(), name="work_add_to_project"),
path('collections/<int:collection>/works/<int:pk>/upload', views.WorkAddDocumentView.as_view(), name="document_add"),
path('collections/<int:collection>/docs/<int:pk>/delete', views.DocumentDeleteView.as_view(), name="document_delete"),
path('collections/<int:collection>/docs/<int:pk>/download', views.DocumentDownloadView.as_view(), name="document_download"),
path('collections/<int:collection>/docs/<int:pk>/annotate', views.DocumentAnnotateView.as_view(), name="document_annotate"),
path('collections/<int:collection>/docs/<int:pk>/<str:filename>', views.PartDownloadView.as_view(), name="part_download"),
#path('api/', include(router.urls))
path('api/library/collections/<int:pk>/export', api.CollectionExportView.as_view(), name="collection_export"),
+53 -13
View File
@@ -13,13 +13,18 @@ import json
import os.path
import re
from interface.views import EnsembleMixin, ProjectMixin
from interface.views import EnsembleMixin, ProjectMixin, AuthorizedResourceMixin
from interface.models import Project
from library.models import Collection, Work, Document, Section
from library.imslp import INSTRUMENT_TAGS, INSTRUMENTS
from library import forms, models
from library.pdf_utils import extract_pages, extract_and_concat
"""
"""
class ProjectItemListView(ProjectMixin, ListView):
template_name = "library/item_list.html"
model = models.ProjectItem
@@ -76,6 +81,7 @@ class ProjectItemListView(ProjectMixin, ListView):
# data['running_time'] = "-:--"
return data
class ProjectItemManageView(ProjectMixin, ListView):
template_name = "library/item_list_manage.html"
model = models.ProjectItem
@@ -109,25 +115,60 @@ class ProjectItemAddView(ProjectMixin, UpdateView):
def get_object(self):
return self.get_project()
class CollectionListView(EnsembleMixin, ListView):
""" COLLECTION VIEWS """
class CollectionMixin(AuthorizedResourceMixin):
def is_authorized(self):
super().is_authorized()
try:
self.collection = self.get_collection()
return True
except (models.Collection.DoesNotExist, KeyError):
return False
def get_queryset(self):
return Collection.objects.filter(administrators=self.request.user)
return super().get_queryset().filter(collection=self.collection)
def get_collection(self):
collection = self.get_collection_queryset().get(pk=self.kwargs['collection'])
self.request.is_admin = collection.has_administrator(self.request.user)
return collection
class WorkListView(EnsembleMixin, ListView):
def get_collection_queryset(self):
collections = models.Collection.objects.all()
if self.request.user.is_anonymous:
return models.Collection.objects.none()
if self.request.is_admin:
return collections
return collections.filter(Q(administrators=self.request.user) | Q(allowed_ensembles__ensemble__admins=self.request.user))
class CollectionListView(CollectionMixin, ListView):
paginate_by = 20
def is_authorized(self):
return True
def get_queryset(self):
return self.get_collection_queryset()
class WorkListView(CollectionMixin, ListView):
paginate_by = 20
def get_works(self):
return Work.objects.filter(collection__allowed_ensembles__ensemble=self.request.ensemble_id).order_by('name').distinct().select_related('collection')
collections = CollectionMixin.get_queryset(self)
return Work.objects.filter(collection__in=collections).order_by('name').distinct().select_related('collection')
def get_context_data(self, *args, **kwargs):
data = super(WorkListView, self).get_context_data(*args, **kwargs)
data['title'] = f'Music available to {self.ensemble.name}'
#data['title'] = f'Music available to {self.ensemble.name}'
data['title'] = "My Library"
return data
def get_queryset(self):
works = self.get_works().order_by('name')
works = self.get_works()
q = self.request.GET.get('filter')
if q:
@@ -142,7 +183,7 @@ class WorkListView(EnsembleMixin, ListView):
class CollectionWorkListView(WorkListView):
def get_works(self):
works = Work.objects.filter(collection=self.kwargs['pk']).distinct()
works = Work.objects.filter(collection=self.kwargs['collection']).distinct()
loan_count = Count('project_items', Q(project_items__checkout__lte=now(), project_items__returned=None))
works = works.annotate(loan_count=loan_count)
@@ -150,11 +191,10 @@ class CollectionWorkListView(WorkListView):
def get_context_data(self, *args, **kwargs):
data = super(CollectionWorkListView, self).get_context_data(*args, **kwargs)
data['title'] = Collection.objects.get(pk=self.kwargs['pk']).name
data['collection_id'] = self.kwargs['pk']
data['title'] = self.collection.name
return data
class WorkAddView(EnsembleMixin, FormView):
class WorkAddView(CollectionMixin, FormView):
template_name = "interface/default_form.html"
form_class = forms.WorkCreateForm
@@ -185,10 +225,10 @@ class WorkMixin(object):
return Work.objects.filter(collection__allowed_ensembles__ensemble=self.request.ensemble_id)
class WorkDetailView(EnsembleMixin, WorkMixin, DetailView):
class WorkDetailView(CollectionMixin, WorkMixin, DetailView):
pass
class WorkUpdateView(EnsembleMixin, WorkMixin, UpdateView):
class WorkUpdateView(CollectionMixin, WorkMixin, UpdateView):
fields = ['name', 'composer', 'edition', 'code', 'licence', 'max_projects', 'running_time', 'notes']
template_name = 'interface/default_form.html'