From 12567f6891ad591390cbd74c0e7b77a4a024a24e Mon Sep 17 00:00:00 2001 From: Andrew Godwin Date: Fri, 16 Dec 2022 19:42:48 -0700 Subject: Identity admin/moderation --- users/views/activitypub.py | 9 +++-- users/views/admin/__init__.py | 16 +------- users/views/admin/identities.py | 90 +++++++++++++++++++++++++++++++++++++++++ users/views/admin/users.py | 2 +- 4 files changed, 99 insertions(+), 18 deletions(-) create mode 100644 users/views/admin/identities.py (limited to 'users/views') diff --git a/users/views/activitypub.py b/users/views/activitypub.py index b44edfb..d80a1c8 100644 --- a/users/views/activitypub.py +++ b/users/views/activitypub.py @@ -165,11 +165,12 @@ class Inbox(View): f"Inbox error: cannot fetch actor {document['actor']}" ) return HttpResponseBadRequest("Cannot retrieve actor") - # See if it's from a blocked domain - if identity.domain.blocked: + + # See if it's from a blocked user or domain + if identity.blocked or identity.domain.blocked: # I love to lie! Throw it away! exceptions.capture_message( - f"Inbox: Discarded message from {identity.domain}" + f"Inbox: Discarded message from {identity.actor_uri}" ) return HttpResponse(status=202) @@ -185,6 +186,7 @@ class Inbox(View): except VerificationError: exceptions.capture_message("Inbox error: Bad LD signature") return HttpResponseUnauthorized("Bad signature") + # Otherwise, verify against the header (assuming it's the same actor) else: try: @@ -200,6 +202,7 @@ class Inbox(View): except VerificationError: exceptions.capture_message("Inbox error: Bad HTTP signature") return HttpResponseUnauthorized("Bad signature") + # Hand off the item to be processed by the queue InboxMessage.objects.create(message=document) return HttpResponse(status=202) diff --git a/users/views/admin/__init__.py b/users/views/admin/__init__.py index 5ace04d..d923f80 100644 --- a/users/views/admin/__init__.py +++ b/users/views/admin/__init__.py @@ -1,9 +1,8 @@ from django import forms from django.utils.decorators import method_decorator -from django.views.generic import FormView, RedirectView, TemplateView +from django.views.generic import FormView, RedirectView from users.decorators import admin_required -from users.models import Identity from users.views.admin.domains import ( # noqa DomainCreate, DomainDelete, @@ -17,6 +16,7 @@ from users.views.admin.hashtags import ( # noqa HashtagEdit, Hashtags, ) +from users.views.admin.identities import IdentitiesRoot, IdentityEdit # noqa from users.views.admin.settings import ( # noqa BasicSettings, PoliciesSettings, @@ -31,18 +31,6 @@ class AdminRoot(RedirectView): pattern_name = "admin_basic" -@method_decorator(admin_required, name="dispatch") -class Identities(TemplateView): - - template_name = "admin/identities.html" - - def get_context_data(self): - return { - "identities": Identity.objects.order_by("username"), - "section": "identities", - } - - @method_decorator(admin_required, name="dispatch") class Invites(FormView): diff --git a/users/views/admin/identities.py b/users/views/admin/identities.py new file mode 100644 index 0000000..d094978 --- /dev/null +++ b/users/views/admin/identities.py @@ -0,0 +1,90 @@ +from django import forms +from django.db import models +from django.shortcuts import get_object_or_404, redirect +from django.utils.decorators import method_decorator +from django.views.generic import FormView, ListView + +from users.decorators import admin_required +from users.models import Identity, IdentityStates + + +@method_decorator(admin_required, name="dispatch") +class IdentitiesRoot(ListView): + + template_name = "admin/identities.html" + paginate_by = 30 + + def get(self, request, *args, **kwargs): + self.query = request.GET.get("query") + self.local_only = request.GET.get("local_only") + self.extra_context = { + "section": "identities", + "query": self.query or "", + "local_only": self.local_only, + } + return super().get(request, *args, **kwargs) + + def get_queryset(self): + identities = Identity.objects.annotate( + num_users=models.Count("users") + ).order_by("created") + if self.local_only: + identities = identities.filter(local=True) + if self.query: + query = self.query.lower().strip().lstrip("@") + if "@" in query: + username, domain = query.split("@", 1) + identities = identities.filter( + username=username, + domain__domain__istartswith=domain, + ) + else: + identities = identities.filter( + models.Q(username__icontains=self.query) + | models.Q(name__icontains=self.query) + ) + return identities + + +@method_decorator(admin_required, name="dispatch") +class IdentityEdit(FormView): + + template_name = "admin/identity_edit.html" + extra_context = { + "section": "identities", + } + + class form_class(forms.Form): + notes = forms.CharField(widget=forms.Textarea, required=False) + + def dispatch(self, request, id, *args, **kwargs): + self.identity = get_object_or_404(Identity, id=id) + return super().dispatch(request, *args, **kwargs) + + def post(self, request, *args, **kwargs): + if "fetch" in request.POST: + self.identity.transition_perform(IdentityStates.outdated) + self.identity = Identity.objects.get(pk=self.identity.pk) + if "limit" in request.POST: + self.identity.restriction = Identity.Restriction.limited + self.identity.save() + if "block" in request.POST: + self.identity.restriction = Identity.Restriction.blocked + self.identity.save() + if "unlimit" in request.POST or "unblock" in request.POST: + self.identity.restriction = Identity.Restriction.none + self.identity.save() + return super().post(request, *args, **kwargs) + + def get_initial(self): + return {"notes": self.identity.admin_notes} + + def form_valid(self, form): + self.identity.admin_notes = form.cleaned_data["notes"] + self.identity.save() + return redirect(".") + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["identity"] = self.identity + return context diff --git a/users/views/admin/users.py b/users/views/admin/users.py index fab4616..5921de2 100644 --- a/users/views/admin/users.py +++ b/users/views/admin/users.py @@ -12,7 +12,7 @@ from users.models import User class UsersRoot(ListView): template_name = "admin/users.html" - paginate_by = 50 + paginate_by = 30 def get(self, request, *args, **kwargs): self.query = request.GET.get("query") -- cgit v1.2.3