Got admin user login working
This commit is contained in:
parent
65d5c9631c
commit
d1698a958c
25
interface/migrations/0017_auto_20200914_0943.py
Normal file
25
interface/migrations/0017_auto_20200914_0943.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# Generated by Django 3.1.1 on 2020-09-13 23:43
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('interface', '0016_auto_20200910_2025'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='ensemble',
|
||||||
|
name='admins',
|
||||||
|
field=models.ManyToManyField(to=settings.AUTH_USER_MODEL),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='submission',
|
||||||
|
name='instrument',
|
||||||
|
field=models.CharField(max_length=100, verbose_name='Instrument / Voice'),
|
||||||
|
),
|
||||||
|
]
|
||||||
25
interface/migrations/0018_auto_20200914_1009.py
Normal file
25
interface/migrations/0018_auto_20200914_1009.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# Generated by Django 3.1.1 on 2020-09-14 00:09
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('interface', '0017_auto_20200914_0943'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='resource',
|
||||||
|
name='visible',
|
||||||
|
field=models.BooleanField(default=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='ensemble',
|
||||||
|
name='admins',
|
||||||
|
field=models.ManyToManyField(related_name='ensembles', to=settings.AUTH_USER_MODEL),
|
||||||
|
),
|
||||||
|
]
|
||||||
@ -28,6 +28,7 @@ class Ensemble(models.Model):
|
|||||||
name = models.CharField(max_length=100)
|
name = models.CharField(max_length=100)
|
||||||
code = models.CharField(max_length=9, default=generate_code)
|
code = models.CharField(max_length=9, default=generate_code)
|
||||||
passphrase = models.CharField(max_length=100)
|
passphrase = models.CharField(max_length=100)
|
||||||
|
admins = models.ManyToManyField('auth.User', related_name='ensembles')
|
||||||
|
|
||||||
def active_projects(self):
|
def active_projects(self):
|
||||||
return self.projects.filter(active=True)
|
return self.projects.filter(active=True)
|
||||||
@ -62,6 +63,7 @@ class Resource(models.Model):
|
|||||||
description = models.TextField(blank=True)
|
description = models.TextField(blank=True)
|
||||||
key = models.CharField(max_length=255, blank=True)
|
key = models.CharField(max_length=255, blank=True)
|
||||||
media_type = models.CharField(max_length=10, choices=MEDIA_TYPES, default='*')
|
media_type = models.CharField(max_length=10, choices=MEDIA_TYPES, default='*')
|
||||||
|
visible = models.BooleanField(default=True)
|
||||||
|
|
||||||
def key_template(self):
|
def key_template(self):
|
||||||
return "{}/${{filename}}".format(slugify(self.name))
|
return "{}/${{filename}}".format(slugify(self.name))
|
||||||
|
|||||||
@ -29,12 +29,9 @@
|
|||||||
Ensembles</span></a>
|
Ensembles</span></a>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if request.is_admin %}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href=""><i class="fas fa-question"></i> <span class="">About</span></a>
|
<a href="{% url 'manage' %}"><i class="fas fa-user-lock"></i></a>
|
||||||
</li>
|
|
||||||
{% if request.user.is_authenticated %}
|
|
||||||
<li class="nav-item">
|
|
||||||
<a href="/admin"><i class="fas fa-key"></i></a>
|
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
20
interface/templates/interface/manage.html
Normal file
20
interface/templates/interface/manage.html
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="narrow">
|
||||||
|
<h3>Manage {{ ensemble.name }}</h3>
|
||||||
|
<p>
|
||||||
|
Joining code for participants:<br/>
|
||||||
|
<a href="{{ ensemble_url }}">{{ ensemble_url }}</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Sorry, not much you can do here yet.
|
||||||
|
<ul>
|
||||||
|
<li>Should be able to create new projects.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
Logged in as {{ request.user }} [<a href="{% url 'logout' %}">Logout</a>]
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
@ -11,7 +11,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td>{{ submission.date|timesince }} ago</td>
|
<td>{{ submission.date|timesince }} ago</td>
|
||||||
<td>{{ submission.name }} ({{ submission.instrument }})</td>
|
<td>{{ submission.name }} ({{ submission.instrument }})</td>
|
||||||
{% if request.user.is_authenticated %}
|
{% if request.is_admin %}
|
||||||
<td>
|
<td>
|
||||||
<a href="{% url 'submission_detail' project=project.pk pk=submission.pk %}"><i class="fas fa-info-circle"></i></a>
|
<a href="{% url 'submission_detail' project=project.pk pk=submission.pk %}"><i class="fas fa-info-circle"></i></a>
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
{% if not request.user.is_authenticated %}
|
||||||
|
<a href="{% url 'login' %}" style="float: right"><i class="fa fa-key"></i></a>
|
||||||
|
{% endif %}
|
||||||
<div style="display: flex">
|
<div style="display: flex">
|
||||||
{% if current %}
|
{% if current %}
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
<i class="fas fa-download"></i> Download
|
<i class="fas fa-download"></i> Download
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if request.user.is_authenticated %}
|
{% if request.is_admin %}
|
||||||
<a href="{% url 'resource_upload' project=project.pk pk=resource.pk %}">
|
<a href="{% url 'resource_upload' project=project.pk pk=resource.pk %}">
|
||||||
<i class="fas fa-upload"></i> Upload
|
<i class="fas fa-upload"></i> Upload
|
||||||
</a>
|
</a>
|
||||||
@ -28,7 +28,7 @@
|
|||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% if request.user.is_authenticated %}
|
{% if request.is_admin %}
|
||||||
<div class="admin-actions">
|
<div class="admin-actions">
|
||||||
<a href="{% url 'resource_create' project=project.pk %}"><i class="fas fa-plus-circle"></i> Add new</a>
|
<a href="{% url 'resource_create' project=project.pk %}"><i class="fas fa-plus-circle"></i> Add new</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
11
interface/templates/registration/login.html
Normal file
11
interface/templates/registration/login.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<form method="POST" class="vertical">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form }}
|
||||||
|
<div class="form-actions">
|
||||||
|
<button type="submit">Login</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
||||||
@ -1,10 +1,16 @@
|
|||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
from django.contrib.auth import views as auth_views
|
||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('', views.EnsembleDetailView.as_view(), name='ensemble_detail'),
|
|
||||||
|
path('login', auth_views.LoginView.as_view(), name='login'),
|
||||||
|
path('logout', views.logout, name='logout'),
|
||||||
path('register', views.register, name="register"),
|
path('register', views.register, name="register"),
|
||||||
|
path('manage', views.ManageView.as_view(), name="manage"),
|
||||||
|
|
||||||
|
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:project>/page/<int:pk>', views.WikiView.as_view(), name="wiki"),
|
path('projects/<int:project>/page/<int:pk>', views.WikiView.as_view(), name="wiki"),
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,7 @@ from django.views.generic.edit import CreateView
|
|||||||
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.contrib import auth
|
||||||
|
|
||||||
from markdown2 import markdown
|
from markdown2 import markdown
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
@ -19,14 +20,26 @@ import logging
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
class EnsembleMixin(object):
|
class EnsembleMixin(object):
|
||||||
|
admin_required = False
|
||||||
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
|
|
||||||
request.ensemble_id = request.session.get('ensemble')
|
request.ensemble_id = request.session.get('ensemble')
|
||||||
|
request.is_admin = request.user.is_superuser
|
||||||
|
|
||||||
if not request.ensemble_id:
|
if not request.ensemble_id:
|
||||||
return redirect('register')
|
return redirect('register')
|
||||||
|
|
||||||
|
if not request.is_admin and request.user.is_authenticated:
|
||||||
|
try:
|
||||||
|
request.user.ensembles.get(pk=request.ensemble_id)
|
||||||
|
request.is_admin = True
|
||||||
|
except models.Ensemble.DoesNotExist:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if self.admin_required and not request.is_admin:
|
||||||
|
return redirect('login')
|
||||||
|
|
||||||
return super().dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
class ProjectMixin(EnsembleMixin):
|
class ProjectMixin(EnsembleMixin):
|
||||||
@ -134,6 +147,24 @@ def register(request):
|
|||||||
return render(request, 'interface/register.html', {'form': form, 'current': current})
|
return render(request, 'interface/register.html', {'form': form, 'current': current})
|
||||||
|
|
||||||
|
|
||||||
|
def on_login(sender, **kwargs):
|
||||||
|
request = kwargs['request']
|
||||||
|
registered = request.session.get('registered', {})
|
||||||
|
for e in kwargs['user'].ensembles.all():
|
||||||
|
if not e.code in registered:
|
||||||
|
registered[e.code] = e.pk
|
||||||
|
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 EnsembleDetailView(EnsembleMixin, DetailView):
|
class EnsembleDetailView(EnsembleMixin, DetailView):
|
||||||
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
@ -188,7 +219,7 @@ class SubmissionDetailView(ProjectMixin, S3CompleteMixin, DetailView):
|
|||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
if self.request.user.is_authenticated:
|
if self.request.is_admin:
|
||||||
context['download'] = self.object.presigned_url()
|
context['download'] = self.object.presigned_url()
|
||||||
return context
|
return context
|
||||||
|
|
||||||
@ -219,7 +250,7 @@ class ResourceCreateView(ProjectMixin, CreateView):
|
|||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
|
|
||||||
if not self.request.user.is_authenticated:
|
if not self.request.is_admin:
|
||||||
raise SuspiciousOperation("Must be logged in to create resources")
|
raise SuspiciousOperation("Must be logged in to create resources")
|
||||||
|
|
||||||
self.object = form.save(commit=False)
|
self.object = form.save(commit=False)
|
||||||
@ -250,3 +281,16 @@ class ResourceCompleteView(S3CompleteMixin, SingleObjectMixin, RedirectView):
|
|||||||
|
|
||||||
class ResourceListView(ProjectMixin, ListView):
|
class ResourceListView(ProjectMixin, ListView):
|
||||||
model = models.Resource
|
model = models.Resource
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
return super().get_queryset().filter(visible=True)
|
||||||
|
|
||||||
|
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
|
||||||
@ -99,7 +99,7 @@ AUTH_PASSWORD_VALIDATORS = [
|
|||||||
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
LOGIN_REDIRECT_URL = "/"
|
||||||
|
|
||||||
# Internationalization
|
# Internationalization
|
||||||
# https://docs.djangoproject.com/en/3.1/topics/i18n/
|
# https://docs.djangoproject.com/en/3.1/topics/i18n/
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user