diff options
-rw-r--r-- | static/css/style.css | 4 | ||||
-rw-r--r-- | takahe/urls.py | 10 | ||||
-rw-r--r-- | templates/admin/federation.html | 24 | ||||
-rw-r--r-- | templates/admin/federation_edit.html | 19 | ||||
-rw-r--r-- | templates/settings/_menu.html | 3 | ||||
-rw-r--r-- | users/models/domain.py | 2 | ||||
-rw-r--r-- | users/views/admin/__init__.py | 1 | ||||
-rw-r--r-- | users/views/admin/federation.py | 57 |
8 files changed, 120 insertions, 0 deletions
diff --git a/static/css/style.css b/static/css/style.css index 737d9bf..dae2253 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -365,6 +365,10 @@ nav a i { margin: 0 5px 0 5px; } +.icon-menu .option .pill.bad { + background: var(--color-delete); +} + .handle { vertical-align: middle; display: inline-block; diff --git a/takahe/urls.py b/takahe/urls.py index ddffa68..b94f205 100644 --- a/takahe/urls.py +++ b/takahe/urls.py @@ -69,6 +69,16 @@ urlpatterns = [ admin.DomainDelete.as_view(), ), path( + "admin/federation/", + admin.FederationRoot.as_view(), + name="admin_federation", + ), + path( + "admin/federation/<domain>/", + admin.FederationEdit.as_view(), + name="admin_federation_edit", + ), + path( "admin/users/", admin.Users.as_view(), name="admin_users", diff --git a/templates/admin/federation.html b/templates/admin/federation.html new file mode 100644 index 0000000..1a48176 --- /dev/null +++ b/templates/admin/federation.html @@ -0,0 +1,24 @@ +{% extends "settings/base.html" %} + +{% block subtitle %}Federation{% endblock %} + +{% block content %} + <section class="icon-menu"> + {% for domain in domains %} + <a class="option" href="{{ domain.urls.edit_federation }}"> + <i class="fa-solid fa-globe"></i> + <span class="handle"> + {{ domain.domain }} + <small> + {{ domain.num_users }} remote identit{{ domain.num_users|pluralize:"y,ies" }} + </small> + </span> + {% if domain.blocked %} + <span class="pill bad">Blocked</span> + {% endif %} + </a> + {% empty %} + <p class="option empty">There are no federation links yet.</p> + {% endfor %} + </section> +{% endblock %} diff --git a/templates/admin/federation_edit.html b/templates/admin/federation_edit.html new file mode 100644 index 0000000..f96e7ae --- /dev/null +++ b/templates/admin/federation_edit.html @@ -0,0 +1,19 @@ +{% extends "settings/base.html" %} + +{% block subtitle %}{{ domain.domain }}{% endblock %} + +{% block content %} + <form action="." method="POST"> + {% csrf_token %} + <h1>{{ domain }}</h1> + <fieldset> + <legend>Federation Controls</legend> + {% include "forms/_field.html" with field=form.blocked %} + </fieldset> + <div class="buttons"> + <a href="{{ domain.urls.root }}" class="button secondary left">Back</a> + <a href="{{ domain.urls.delete }}" class="button delete">Delete</a> + <button>Save</button> + </div> + </form> +{% endblock %} diff --git a/templates/settings/_menu.html b/templates/settings/_menu.html index 49a5d68..531febb 100644 --- a/templates/settings/_menu.html +++ b/templates/settings/_menu.html @@ -24,6 +24,9 @@ <a href="{% url "admin_domains" %}" {% if section == "domains" %}class="selected"{% endif %} title="Domains"> <i class="fa-solid fa-globe"></i> Domains </a> + <a href="{% url "admin_federation" %}" {% if section == "federation" %}class="selected"{% endif %} title="Federation"> + <i class="fa-solid fa-diagram-project"></i> Federation + </a> <a href="{% url "admin_users" %}" {% if section == "users" %}class="selected"{% endif %} title="Users"> <i class="fa-solid fa-users"></i> Users </a> diff --git a/users/models/domain.py b/users/models/domain.py index 40a3e22..622085d 100644 --- a/users/models/domain.py +++ b/users/models/domain.py @@ -56,6 +56,8 @@ class Domain(models.Model): create = "/admin/domains/create/" edit = "/admin/domains/{self.domain}/" delete = "{edit}delete/" + root_federation = "/admin/federation/" + edit_federation = "/admin/federation/{self.domain}/" @classmethod def get_remote_domain(cls, domain: str) -> "Domain": diff --git a/users/views/admin/__init__.py b/users/views/admin/__init__.py index 231e027..d1a4db1 100644 --- a/users/views/admin/__init__.py +++ b/users/views/admin/__init__.py @@ -10,6 +10,7 @@ from users.views.admin.domains import ( # noqa DomainEdit, Domains, ) +from users.views.admin.federation import FederationEdit, FederationRoot # noqa from users.views.admin.settings import BasicSettings # noqa diff --git a/users/views/admin/federation.py b/users/views/admin/federation.py new file mode 100644 index 0000000..da8209a --- /dev/null +++ b/users/views/admin/federation.py @@ -0,0 +1,57 @@ +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, TemplateView + +from users.decorators import admin_required +from users.models import Domain + + +@method_decorator(admin_required, name="dispatch") +class FederationRoot(TemplateView): + + template_name = "admin/federation.html" + + def get_context_data(self): + return { + "domains": Domain.objects.filter(local=False) + .annotate(num_users=models.Count("identities")) + .order_by("domain"), + "section": "federation", + } + + +@method_decorator(admin_required, name="dispatch") +class FederationEdit(FormView): + + template_name = "admin/federation_edit.html" + extra_context = {"section": "federation"} + + class form_class(forms.Form): + blocked = forms.BooleanField( + help_text="If this domain is blocked from interacting with this server", + widget=forms.Select(choices=[(True, "Blocked"), (False, "Not Blocked")]), + required=False, + ) + + def dispatch(self, request, domain): + self.domain = get_object_or_404( + Domain.objects.filter(local=False), domain=domain + ) + return super().dispatch(request) + + def get_context_data(self, *args, **kwargs): + context = super().get_context_data(*args, **kwargs) + context["domain"] = self.domain + return context + + def form_valid(self, form): + self.domain.blocked = form.cleaned_data["blocked"] + self.domain.save() + return redirect(Domain.urls.root_federation) + + def get_initial(self): + return { + "blocked": self.domain.blocked, + } |