aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/migrations/0031_nomination.py26
-rw-r--r--api/models.py29
-rw-r--r--api/serializers.py21
-rw-r--r--api/urls.py15
-rw-r--r--api/viewsets.py40
5 files changed, 111 insertions, 20 deletions
diff --git a/api/migrations/0031_nomination.py b/api/migrations/0031_nomination.py
new file mode 100644
index 00000000..b739d5cb
--- /dev/null
+++ b/api/migrations/0031_nomination.py
@@ -0,0 +1,26 @@
+# Generated by Django 2.1.5 on 2019-01-27 11:01
+
+import api.models
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('api', '0030_reminder'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Nomination',
+ fields=[
+ ('active', models.BooleanField(default=True, help_text='Whether this nomination is still relevant.')),
+ ('reason', models.TextField(help_text='Why this user was nominated.')),
+ ('user', models.OneToOneField(help_text='The nominated user.', on_delete=django.db.models.deletion.CASCADE, primary_key=True, related_name='nomination', serialize=False, to='api.User')),
+ ('inserted_at', models.DateTimeField(auto_now_add=True, help_text='The creation date of this nomination.')),
+ ('author', models.ForeignKey(help_text='The staff member that nominated this user.', on_delete=django.db.models.deletion.CASCADE, related_name='nomination_set', to='api.User')),
+ ],
+ bases=(api.models.ModelReprMixin, models.Model),
+ ),
+ ]
diff --git a/api/models.py b/api/models.py
index 5ca274ce..fa68f31c 100644
--- a/api/models.py
+++ b/api/models.py
@@ -408,3 +408,32 @@ class Reminder(ModelReprMixin, models.Model):
def __str__(self):
return f"{self.content} on {self.expiration} by {self.author}"
+
+
+class Nomination(ModelReprMixin, models.Model):
+ """A helper nomination created by staff."""
+
+ active = models.BooleanField(
+ default=True,
+ help_text="Whether this nomination is still relevant."
+ )
+ author = models.ForeignKey(
+ User,
+ on_delete=models.CASCADE,
+ help_text="The staff member that nominated this user.",
+ related_name='nomination_set'
+ )
+ reason = models.TextField(
+ help_text="Why this user was nominated."
+ )
+ user = models.OneToOneField(
+ User,
+ on_delete=models.CASCADE,
+ help_text="The nominated user.",
+ primary_key=True,
+ related_name='nomination'
+ )
+ inserted_at = models.DateTimeField(
+ auto_now_add=True,
+ help_text="The creation date of this nomination."
+ )
diff --git a/api/serializers.py b/api/serializers.py
index fca8008f..97c4a60c 100644
--- a/api/serializers.py
+++ b/api/serializers.py
@@ -1,14 +1,15 @@
from rest_framework.serializers import ModelSerializer, PrimaryKeyRelatedField, ValidationError
+from rest_framework.validators import UniqueValidator
from rest_framework_bulk import BulkSerializerMixin
from .models import (
DeletedMessage, DocumentationLink,
Infraction, MessageDeletionContext,
- OffTopicChannelName, Reminder,
- Role, SnakeFact,
- SnakeIdiom, SnakeName,
- SpecialSnake, Tag,
- User
+ Nomination, OffTopicChannelName,
+ Reminder, Role,
+ SnakeFact, SnakeIdiom,
+ SnakeName, SpecialSnake,
+ Tag, User
)
@@ -154,3 +155,13 @@ class UserSerializer(BulkSerializerMixin, ModelSerializer):
model = User
fields = ('id', 'avatar_hash', 'name', 'discriminator', 'roles', 'in_guild')
depth = 1
+
+
+class NominationSerializer(ModelSerializer):
+ author = PrimaryKeyRelatedField(queryset=User.objects.all())
+ user = PrimaryKeyRelatedField(queryset=User.objects.all())
+
+ class Meta:
+ model = Nomination
+ fields = ('active', 'author', 'reason', 'user', 'inserted_at')
+ depth = 1
diff --git a/api/urls.py b/api/urls.py
index c8548df1..5db89e67 100644
--- a/api/urls.py
+++ b/api/urls.py
@@ -4,11 +4,12 @@ from rest_framework.routers import DefaultRouter
from .views import HealthcheckView, RulesView
from .viewsets import (
DeletedMessageViewSet, DocumentationLinkViewSet,
- InfractionViewSet, OffTopicChannelNameViewSet,
- ReminderViewSet, RoleViewSet,
- SnakeFactViewSet, SnakeIdiomViewSet,
- SnakeNameViewSet, SpecialSnakeViewSet,
- TagViewSet, UserViewSet
+ InfractionViewSet, NominationViewSet,
+ OffTopicChannelNameViewSet, ReminderViewSet,
+ RoleViewSet, SnakeFactViewSet,
+ SnakeIdiomViewSet, SnakeNameViewSet,
+ SpecialSnakeViewSet, TagViewSet,
+ UserViewSet
)
@@ -27,6 +28,10 @@ bot_router.register(
InfractionViewSet
)
bot_router.register(
+ 'nominations',
+ NominationViewSet
+)
+bot_router.register(
'off-topic-channel-names',
OffTopicChannelNameViewSet,
base_name='offtopicchannelname'
diff --git a/api/viewsets.py b/api/viewsets.py
index 83945fe8..7ef1ba98 100644
--- a/api/viewsets.py
+++ b/api/viewsets.py
@@ -14,20 +14,21 @@ from rest_framework_bulk import BulkCreateModelMixin
from .models import (
DocumentationLink, Infraction,
- MessageDeletionContext, OffTopicChannelName,
- Reminder, Role,
- SnakeFact, SnakeIdiom,
- SnakeName, SpecialSnake,
- Tag, User
+ MessageDeletionContext, Nomination,
+ OffTopicChannelName, Reminder,
+ Role, SnakeFact,
+ SnakeIdiom, SnakeName,
+ SpecialSnake, Tag,
+ User
)
from .serializers import (
DocumentationLinkSerializer, ExpandedInfractionSerializer,
InfractionSerializer, MessageDeletionContextSerializer,
- OffTopicChannelNameSerializer, ReminderSerializer,
- RoleSerializer, SnakeFactSerializer,
- SnakeIdiomSerializer, SnakeNameSerializer,
- SpecialSnakeSerializer, TagSerializer,
- UserSerializer
+ NominationSerializer, OffTopicChannelNameSerializer,
+ ReminderSerializer, RoleSerializer,
+ SnakeFactSerializer, SnakeIdiomSerializer,
+ SnakeNameSerializer, SpecialSnakeSerializer,
+ TagSerializer, UserSerializer
)
@@ -857,3 +858,22 @@ class UserViewSet(BulkCreateModelMixin, ModelViewSet):
serializer_class = UserSerializer
queryset = User.objects.prefetch_related('roles')
+
+
+class NominationViewSet(ModelViewSet):
+ # TODO: doc me
+ serializer_class = NominationSerializer
+ queryset = Nomination.objects.prefetch_related('author', 'user')
+ frozen_fields = ('author', 'inserted_at', 'user')
+
+ def partial_update(self, request, *args, **kwargs):
+ for field in request.data:
+ if field in self.frozen_fields:
+ raise ValidationError({field: ['This field cannot be updated.']})
+
+ instance = self.get_object()
+ serializer = self.get_serializer(instance, data=request.data, partial=True)
+ serializer.is_valid(raise_exception=True)
+ serializer.save()
+
+ return Response(serializer.data)