Add admin capcodes
Sometimes, it is necessary for an admin or other moderator to reveal themselves. Capcodes allow them to do so by appending a special colored portion at the end of their name on a post. This adds object-level permissions, so if you have a moderator who shouldn't be able to use the "admin" capcode, you can give them permission only to the "moderator" capcode. Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -1,15 +1,10 @@
|
||||
from django.contrib import admin
|
||||
from django.urls import reverse
|
||||
from django.utils.safestring import mark_safe
|
||||
from board.models import (
|
||||
Ban,
|
||||
BanTemplate,
|
||||
Board,
|
||||
Post,
|
||||
RangeBan,
|
||||
ReportReason,
|
||||
ReportRecord,
|
||||
)
|
||||
|
||||
from guardian.admin import GuardedModelAdmin
|
||||
|
||||
from board.models import *
|
||||
|
||||
#
|
||||
# Admin sites
|
||||
@@ -82,3 +77,8 @@ class BanAdmin(admin.ModelAdmin):
|
||||
@admin.register(BanTemplate)
|
||||
class BanTemplateAdmin(admin.ModelAdmin):
|
||||
ordering = ("board__url", "name")
|
||||
|
||||
|
||||
@admin.register(Capcode)
|
||||
class CapcodeAdmin(GuardedModelAdmin):
|
||||
pass
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.conf import settings
|
||||
from django.db import transaction
|
||||
from django.db.models import Q
|
||||
@@ -39,12 +40,21 @@ class ReplyForm(PostForm):
|
||||
|
||||
class Meta:
|
||||
model = Post
|
||||
fields = ["name", "text", "bump", "image"]
|
||||
fields = ["name", "text", "bump", "capcode", "image"]
|
||||
|
||||
def __init__(self, *args, op, reply, **kwargs):
|
||||
def __init__(self, *args, user, op, **kwargs):
|
||||
super(ReplyForm, self).__init__(*args, **kwargs)
|
||||
self.instance.op = op
|
||||
self.instance.reply = reply
|
||||
self.user = user
|
||||
|
||||
def clean(self):
|
||||
super().clean()
|
||||
# TODO
|
||||
# Check if the user has the right permissions to use the selected capcode
|
||||
capcode = self.cleaned_data["capcode"]
|
||||
if capcode:
|
||||
if not self.user or not self.user.has_perm("board.use_capcode", capcode):
|
||||
raise ValidationError("Could not create post")
|
||||
|
||||
|
||||
class ReportForm(ModelForm):
|
||||
|
||||
@@ -2,17 +2,21 @@ from datetime import timedelta
|
||||
import os
|
||||
from pathlib import Path
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.files.base import ContentFile
|
||||
from django.db import models
|
||||
from django.db.models import signals
|
||||
from django.db.models.deletion import SET_NULL
|
||||
from django.dispatch import receiver
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext as _
|
||||
from PIL import Image
|
||||
from io import BytesIO
|
||||
|
||||
from colorfield.fields import ColorField
|
||||
from PIL import Image
|
||||
|
||||
|
||||
def image_upload(instance, filename):
|
||||
op_id = instance.op.id if instance.op else instance.id
|
||||
@@ -36,6 +40,9 @@ def thumbs_upload(instance, filename):
|
||||
return f"{instance.board.url}/{now_sec}t{ext}"
|
||||
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
class Board(models.Model):
|
||||
# The short URL name for the board
|
||||
url = models.CharField(max_length=255, null=False, blank=False, unique=True)
|
||||
@@ -84,6 +91,8 @@ class Post(models.Model):
|
||||
text = models.TextField(max_length=10000, null=False, blank=True)
|
||||
# The IP address of the user that made this post
|
||||
ip = models.GenericIPAddressField()
|
||||
# Capcode
|
||||
capcode = models.ForeignKey("Capcode", null=True, blank=True, on_delete=SET_NULL)
|
||||
# Creation time
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
# Last bump time
|
||||
@@ -334,7 +343,12 @@ class BanTemplate(models.Model):
|
||||
|
||||
|
||||
class Capcode(models.Model):
|
||||
# Content to display *before* the capcoded user's name.
|
||||
prefix = models.CharField(max_length=100)
|
||||
# Content to display *after* the capcoded user's name.
|
||||
suffix = models.CharField(max_length=100)
|
||||
color = ColorField()
|
||||
|
||||
class Meta:
|
||||
permissions = (("use_capcode", "Can use capcode"),)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.suffix
|
||||
|
||||
@@ -30,9 +30,14 @@
|
||||
{% if post.subject %}
|
||||
<span class="post_subject">{{post.subject}}</span>
|
||||
{% endif %}
|
||||
{% blocktranslate with post_name=post.name|default:"Anonymous" post_created=post.created %}
|
||||
{% blocktranslate with post_name=post.name|default:"Anonymous" %}
|
||||
by
|
||||
<span class="post_name">{{post_name}}</span>
|
||||
{% endblocktranslate %}
|
||||
{% if post.capcode %}
|
||||
<span class="post_capcode" style="color: {{post.capcode.color}};">{{post.capcode}}</span>
|
||||
{% endif %}
|
||||
{% blocktranslate with post_created=post.created %}
|
||||
at {{post_created}}
|
||||
{% endblocktranslate %}
|
||||
{% if reply_link %}
|
||||
|
||||
@@ -5,7 +5,23 @@
|
||||
<form method="post" action="{% url 'board:reply_create' url=board.url id=post.id %}" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
<table>
|
||||
{{ form.as_table }}
|
||||
{# {{ form.as_table }} #}
|
||||
{% for field in form %}
|
||||
{% if field.name != "capcode" %}
|
||||
<tr>
|
||||
<th>{{field.label_tag}}</th>
|
||||
<td>{{field}}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if capcodes %}
|
||||
<tr>
|
||||
<th>{{form.capcode.label_tag}}</th>
|
||||
<td>
|
||||
{{form.capcode}}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
<tr>
|
||||
<th> </th>
|
||||
<td>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from typing import Any, Dict
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import get_user_model, get_user
|
||||
from django.contrib.auth.mixins import PermissionRequiredMixin
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.db.models import Q
|
||||
@@ -9,6 +10,9 @@ from django.views.generic.base import TemplateView
|
||||
from django.views.generic import edit
|
||||
from django.urls import reverse, reverse_lazy
|
||||
from django.utils import timezone
|
||||
|
||||
from guardian.shortcuts import get_objects_for_user
|
||||
|
||||
from board.forms import BanForm, PostForm, ReplyForm, ReportForm
|
||||
from board.models import Ban, BanTemplate, Board, Post, Report
|
||||
from board.utils import *
|
||||
@@ -26,6 +30,9 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
class BannedView(TemplateView):
|
||||
template_name = "board/banned.html"
|
||||
|
||||
@@ -121,7 +128,9 @@ class ReplyCreateView(CreateView):
|
||||
post_id = self.kwargs["id"]
|
||||
context["post"] = get_object_or_404(Post, id=post_id)
|
||||
context["max_upload_size"] = settings.MAX_UPLOAD_SIZE
|
||||
print(context["board"])
|
||||
context["capcodes"] = get_objects_for_user(
|
||||
get_user(self.request), "board.use_capcode"
|
||||
)
|
||||
return context
|
||||
|
||||
def get_form_kwargs(self):
|
||||
@@ -129,7 +138,7 @@ class ReplyCreateView(CreateView):
|
||||
post_id = self.kwargs["id"]
|
||||
post = get_object_or_404(Post, id=post_id)
|
||||
kwargs["op"] = post
|
||||
kwargs["reply"] = post
|
||||
kwargs["user"] = self.request.user
|
||||
return kwargs
|
||||
|
||||
|
||||
@@ -154,7 +163,7 @@ class PostView(CreateView):
|
||||
post_id = self.kwargs["id"]
|
||||
post = get_object_or_404(Post, id=post_id)
|
||||
kwargs["op"] = post
|
||||
kwargs["reply"] = post
|
||||
kwargs["user"] = self.request.user
|
||||
return kwargs
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user