Bans - Implement show bans

This commit is contained in:
Evert Prants 2017-12-27 17:01:39 +02:00
parent b302999956
commit 4c2e0d0f91
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
9 changed files with 133 additions and 17 deletions

View File

@ -68,7 +68,14 @@ class Show(TimestampedModel):
upload_to = name_banner, upload_to = name_banner,
help_text="A banner used for the show's page.", help_text="A banner used for the show's page.",
verbose_name="Banner" verbose_name="Banner"
) )
class Meta:
permissions = (
('can_create_show_ban', 'Can ban an user from submitting to this show'),
('can_moderate_show', 'Can add episodes, seasons and unrestricted submissions'),
)
def __str__(self): def __str__(self):
return '%s [%s]'%(self.name,self.abbr) return '%s [%s]'%(self.name,self.abbr)

View File

@ -26,7 +26,7 @@ label {
width: 200px; width: 200px;
display: block; display: block;
} }
input[type=text], input:not([type=submit]) { input[type=text], input[type=email], input[type=password], input[type=number], input[type=url] {
padding: 5px; padding: 5px;
font-size: 120%; font-size: 120%;
width: 280px; width: 280px;

View File

@ -1,5 +1,5 @@
from django import forms from django import forms
from LandingPage.models import Submission, Season, Episode from LandingPage.models import Submission, Season, Episode, Ban, User
class SubmissionForm(forms.ModelForm): class SubmissionForm(forms.ModelForm):
class Meta(): class Meta():
@ -19,3 +19,8 @@ class EpisodeForm(forms.ModelForm):
class Meta(): class Meta():
model = Episode model = Episode
fields = ('episode','name','summary','airdate',) fields = ('episode','name','summary','airdate',)
class BanForm(forms.ModelForm):
class Meta():
model = Ban
fields = ('reason','expiration','permanent',)

View File

@ -0,0 +1,34 @@
{% extends "base.html" %}
{% block title %}
Ban an user from {{show.name}} - Episodes.Community
{% endblock %}
{% block content %}
<section class="show-details">
<div class="banner" style="background-image: url(/media/uploaded_resources/{{show.banner}});"></div>
<div class="banner-cover">
<div class="artwork">
<img src="/media/uploaded_resources/{{show.artwork}}">
</div>
<div class="details">
<h1>{{show.name}}</h1>
<p class="description">
{{show.description}}
</p>
</div>
</div>
</section>
<section class="submissions">
<a href="/show/{{show.abbr}}" class="button"><i class="fa fa-fw fa-home"></i>&nbsp;Show Index</a>
<h1>Ban an User</h1>
{% if error %}
<div class="message error">{{error}}</div>
{% endif %}
<form action="" method="post">
{% csrf_token %}
<p>Banning user <b>{{ target.display_name }}</b></p>
{{ form }}
<input type="submit" value="Submit" />
</form>
</div>
</section>
{% endblock %}

View File

@ -42,7 +42,7 @@
<section class="submissions"> <section class="submissions">
<a href="/show/{{show.abbr}}" class="button"><i class="fa fa-fw fa-home"></i>&nbsp;Show Index</a> <a href="/show/{{show.abbr}}" class="button"><i class="fa fa-fw fa-home"></i>&nbsp;Show Index</a>
{% if user.is_authenticated %} {% if user.is_authenticated %}
{% if "change_show" in show_perms %} {% if "can_moderate_show" in show_perms %}
<a href="/show/{{show.abbr}}/episode/{{episode.season.number}}/{{episode.episode}}/submit" class="button modbutton"><i class="fa fa-fw fa-plus"></i>&nbsp;Add New Link</a> <a href="/show/{{show.abbr}}/episode/{{episode.season.number}}/{{episode.episode}}/submit" class="button modbutton"><i class="fa fa-fw fa-plus"></i>&nbsp;Add New Link</a>
{% else %} {% else %}
<a href="/show/{{show.abbr}}/episode/{{episode.season.number}}/{{episode.episode}}/submit" class="button"><i class="fa fa-fw fa-plus"></i>&nbsp;Submit New Link</a> <a href="/show/{{show.abbr}}/episode/{{episode.season.number}}/{{episode.episode}}/submit" class="button"><i class="fa fa-fw fa-plus"></i>&nbsp;Submit New Link</a>
@ -71,7 +71,7 @@
</div> </div>
<div class="data"> <div class="data">
<span class="timestamp">Submitted {{sbm.timestamp}} by {{sbm.user.display_name}}</span><span class="divider">&middot;</span> <span class="timestamp">Submitted {{sbm.timestamp}} by {{sbm.user.display_name}}</span><span class="divider">&middot;</span>
{% if "change_show" in show_perms %} {% if "can_moderate_show" in show_perms %}
<a href="/show/{{show.abbr}}/submission/{{sbm.id}}/moderate" class="button modbutton"><i class="fa fa-fw fa-shield"></i>&nbsp;Change</a> <a href="/show/{{show.abbr}}/submission/{{sbm.id}}/moderate" class="button modbutton"><i class="fa fa-fw fa-shield"></i>&nbsp;Change</a>
{% else %} {% else %}
<a href="/report?url={{ request.get_full_path|urlencode }}&submission={{ sbm.id }}" class="report">Report Invalid or Spam</a> <a href="/report?url={{ request.get_full_path|urlencode }}&submission={{ sbm.id }}" class="report">Report Invalid or Spam</a>

View File

@ -38,13 +38,13 @@
</div> </div>
</section> </section>
<section class="seasons"> <section class="seasons">
{% if "change_show" in show_perms %} {% if "can_moderate_show" in show_perms %}
<a href="/show/{{show.abbr}}/season/new" class="button modbutton"><i class="fa fa-fw fa-plus"></i>&nbsp;Add a Season</a> <a href="/show/{{show.abbr}}/season/new" class="button modbutton"><i class="fa fa-fw fa-plus"></i>&nbsp;Add a Season</a>
{% endif %} {% endif %}
<h1>Watch Now</h1> <h1>Watch Now</h1>
{% for season in seasons %} {% for season in seasons %}
<div class="season" data-season="{{season.number}}"> <div class="season" data-season="{{season.number}}">
{% if "change_show" in show_perms %} {% if "can_moderate_show" in show_perms %}
<div class="actions"> <div class="actions">
<a href="/show/{{show.abbr}}/season/{{season.number}}/append" class="action"><i class="fa fa-fw fa-plus"></i></a> <a href="/show/{{show.abbr}}/season/{{season.number}}/append" class="action"><i class="fa fa-fw fa-plus"></i></a>
</div> </div>

View File

@ -27,6 +27,8 @@
</div> </div>
</section> </section>
<section class="submissions"> <section class="submissions">
{% load guardian_tags %}
{% get_obj_perms request.user for show as "show_perms" %}
<a href="/show/{{show.abbr}}" class="button"><i class="fa fa-fw fa-home"></i>&nbsp;Show Index</a> <a href="/show/{{show.abbr}}" class="button"><i class="fa fa-fw fa-home"></i>&nbsp;Show Index</a>
<a href="/show/{{show.abbr}}/episode/{{episode.season.number}}/{{episode.episode}}-{{episode.name|slugify}}" class="button">Back to Episode</a> <a href="/show/{{show.abbr}}/episode/{{episode.season.number}}/{{episode.episode}}-{{episode.name|slugify}}" class="button">Back to Episode</a>
<h1>Submission</h1> <h1>Submission</h1>
@ -38,7 +40,9 @@
{{ form }} {{ form }}
<input type="submit" value="Edit" /> <input type="submit" value="Edit" />
<input type="submit" name="delete" value="Delete" /> <input type="submit" name="delete" value="Delete" />
{% if "can_create_show_ban" in show_perms %}
<input type="submit" name="delete_ban" value="Delete and Ban User" /> <input type="submit" name="delete_ban" value="Delete and Ban User" />
{% endif %}
</form> </form>
</div> </div>
</section> </section>

View File

@ -20,6 +20,7 @@ from . import views
urlpatterns = [ urlpatterns = [
url(r'^$', views.IndexView.as_view()), url(r'^$', views.IndexView.as_view()),
url(r'^create_ban$', views.BanFromShowForm),
url(r'^season/new$', views.SeasonSubmitForm), url(r'^season/new$', views.SeasonSubmitForm),
url(r'^season/(?P<season>\d{1,4})/append$', views.EpisodeSubmitForm), url(r'^season/(?P<season>\d{1,4})/append$', views.EpisodeSubmitForm),
url(r'^submission/(?P<submission>\d{1,4})/moderate$', views.SubmissionModForm), url(r'^submission/(?P<submission>\d{1,4})/moderate$', views.SubmissionModForm),

View File

@ -4,15 +4,13 @@ from django.views import View
from django.views.generic.base import TemplateView from django.views.generic.base import TemplateView
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.conf import settings from django.conf import settings
from django.http import Http404 from django.http import Http404, HttpResponseForbidden, HttpResponse, HttpResponseRedirect
from django.http import HttpResponse from django.db.models import Case, When, Value, IntegerField, Count, F, Q
from django.http import HttpResponseRedirect
from django.db.models import Case, When, Value, IntegerField, Count, F
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from guardian.decorators import permission_required_or_403 from guardian.decorators import permission_required_or_403
from LandingPage.models import User, Show, Season, Episode, Submission, SubmissionVote from LandingPage.models import User, Show, Season, Episode, Submission, SubmissionVote, Ban
from . import forms from . import forms
@ -87,6 +85,12 @@ def SubmissionForm(req, abbr, season, episode):
'episode': episode 'episode': episode
} }
# Get bans for this user regarding this show
bans = Ban.objects.filter(Q(scope=show) | Q(site_wide=True), Q(expiration__gte=datetime.datetime.now()) | Q(permanent=True), user=user)
if bans.count() > 0:
return HttpResponseForbidden('You are banned from submitting links to this show.<br>Reason: %s'%(bans.first().reason))
# Handle POST # Handle POST
if req.method == 'POST': if req.method == 'POST':
form = forms.SubmissionForm(req.POST) form = forms.SubmissionForm(req.POST)
@ -100,7 +104,7 @@ def SubmissionForm(req, abbr, season, episode):
ctx['error'] = 'This URL has already been submitted!' ctx['error'] = 'This URL has already been submitted!'
return render(req, "submit.html", ctx) return render(req, "submit.html", ctx)
if not user.has_perm('LandingPage.change_show'): if not user.has_perm('LandingPage.can_moderate_show', show):
# Check if there has been a submission by this user for this episode within the last 24 hours # Check if there has been a submission by this user for this episode within the last 24 hours
if Submission.objects.filter(user=user,episode=episode,timestamp__gte=datetime.datetime.now() - datetime.timedelta(hours=24)).count() > 0: if Submission.objects.filter(user=user,episode=episode,timestamp__gte=datetime.datetime.now() - datetime.timedelta(hours=24)).count() > 0:
ctx['error'] = 'You can only submit one link for an episode in 24 hours!' ctx['error'] = 'You can only submit one link for an episode in 24 hours!'
@ -118,7 +122,7 @@ def SubmissionForm(req, abbr, season, episode):
return render(req, "submit.html", ctx) return render(req, "submit.html", ctx)
# Edit a submission - for moderators # Edit a submission - for moderators
@permission_required_or_403('LandingPage.change_show', (Show, 'abbr', 'abbr'), accept_global_perms=True) @permission_required_or_403('LandingPage.can_moderate_show', (Show, 'abbr', 'abbr'), accept_global_perms=True)
def SubmissionModForm(req, abbr, submission): def SubmissionModForm(req, abbr, submission):
show = get_object_or_404(Show, abbr=abbr) show = get_object_or_404(Show, abbr=abbr)
submission = get_object_or_404(Submission, pk=submission) submission = get_object_or_404(Submission, pk=submission)
@ -143,7 +147,7 @@ def SubmissionModForm(req, abbr, submission):
if 'delete_ban' in req.POST: if 'delete_ban' in req.POST:
submission.delete() submission.delete()
return HttpResponseRedirect('/ban?user=%d'%(submission.user.pk)) return HttpResponseRedirect('/show/%s/create_ban?user=%s'%(abbr,submission.user.username))
form = forms.SubmissionForm(req.POST, instance=submission) form = forms.SubmissionForm(req.POST, instance=submission)
ctx['form'] = form ctx['form'] = form
@ -159,7 +163,7 @@ def SubmissionModForm(req, abbr, submission):
return render(req, "submit_mod.html", ctx) return render(req, "submit_mod.html", ctx)
# Season form GET and POST # Season form GET and POST
@permission_required_or_403('LandingPage.change_show', (Show, 'abbr', 'abbr'), accept_global_perms=True) @permission_required_or_403('LandingPage.can_moderate_show', (Show, 'abbr', 'abbr'), accept_global_perms=True)
def SeasonSubmitForm(req, abbr): def SeasonSubmitForm(req, abbr):
show = get_object_or_404(Show, abbr=abbr) show = get_object_or_404(Show, abbr=abbr)
user = req.user user = req.user
@ -196,7 +200,7 @@ def SeasonSubmitForm(req, abbr):
return render(req, "season_add.html", ctx) return render(req, "season_add.html", ctx)
# Episode form GET and POST # Episode form GET and POST
@permission_required_or_403('LandingPage.change_show', (Show, 'abbr', 'abbr'), accept_global_perms=True) @permission_required_or_403('LandingPage.can_moderate_show', (Show, 'abbr', 'abbr'), accept_global_perms=True)
def EpisodeSubmitForm(req, abbr, season): def EpisodeSubmitForm(req, abbr, season):
show = get_object_or_404(Show, abbr=abbr) show = get_object_or_404(Show, abbr=abbr)
season = get_object_or_404(Season, show=show,number=season) season = get_object_or_404(Season, show=show,number=season)
@ -251,6 +255,14 @@ class SubmissionVoteSubmit(LoginRequiredMixin, View):
if submission.user == user: if submission.user == user:
return HttpResponse('<h1>Error</h1><p>You cannot vote for your own submission.</p>', status=400) return HttpResponse('<h1>Error</h1><p>You cannot vote for your own submission.</p>', status=400)
show = submission.episode.show
# Get bans for this user regarding this show
bans = Ban.objects.filter(Q(scope=show) | Q(site_wide=True), Q(expiration__gte=datetime.datetime.now()) | Q(permanent=True), user=user)
if bans.count() > 0:
return HttpResponseForbidden('You are banned from voting on this show.<br>Reason: %s'%(bans.first().reason))
# Allow changing a vote from positive to negative or vice-versa. Delete vote if its a re-vote # Allow changing a vote from positive to negative or vice-versa. Delete vote if its a re-vote
vote = submission.votes.filter(user=user,submission__id=submission.id).first() vote = submission.votes.filter(user=user,submission__id=submission.id).first()
if vote: if vote:
@ -269,3 +281,56 @@ class SubmissionVoteSubmit(LoginRequiredMixin, View):
return HttpResponseRedirect('/show/%s/episode/%d/%d'%(abbr, submission.episode.season.number, submission.episode.episode)) return HttpResponseRedirect('/show/%s/episode/%d/%d'%(abbr, submission.episode.season.number, submission.episode.episode))
# Episode form GET and POST
@permission_required_or_403('LandingPage.can_create_show_ban', (Show, 'abbr', 'abbr'), accept_global_perms=True)
def BanFromShowForm(req, abbr):
show = get_object_or_404(Show, abbr=abbr)
user = req.user
banTarget = get_object_or_404(User, username=req.GET.get('user', None))
if banTarget == user:
return HttpResponseForbidden('You cannot ban yourself!')
if banTarget.is_staff:
return HttpResponseForbidden('You cannot ban a staff member!')
if banTarget.has_perm('LandingPage.can_moderate_show', show):
return HttpResponseForbidden('You cannot ban another moderator!')
form = forms.BanForm()
# Request context
ctx = {
'form': form,
'show': show,
'target': banTarget
}
# Handle POST
if req.method == 'POST':
form = forms.BanForm(req.POST)
ctx['form'] = form
if form.is_valid():
form_data = form.cleaned_data
# Save
new_ban = form.save(commit=False)
if form_data['permanent']:
new_ban.expiration = datetime.datetime.now()
new_ban.site_wide = False
new_ban.user = banTarget
new_ban.admin = user
new_ban.save()
# Add show to scope
new_ban.scope.add(show)
return HttpResponseRedirect('/show/%s'%(abbr))
else:
ctx['error'] = 'Invalid fields!'
return render(req, "create_ban.html", ctx)