summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Godwin2022-11-25 17:52:43 -0700
committerAndrew Godwin2022-11-25 17:52:57 -0700
commit8ca36fd95800907a1c7f3c9efedd0085b8f0ec9b (patch)
treefaf67cf203e54f5907839531112c3d5739fa5082
parent2a8cb8f8617d618c8d2777cccd823b28a3edc812 (diff)
downloadtakahe-8ca36fd95800907a1c7f3c9efedd0085b8f0ec9b.tar.gz
takahe-8ca36fd95800907a1c7f3c9efedd0085b8f0ec9b.tar.bz2
takahe-8ca36fd95800907a1c7f3c9efedd0085b8f0ec9b.zip
Add federation admin page
-rw-r--r--static/css/style.css4
-rw-r--r--takahe/urls.py10
-rw-r--r--templates/admin/federation.html24
-rw-r--r--templates/admin/federation_edit.html19
-rw-r--r--templates/settings/_menu.html3
-rw-r--r--users/models/domain.py2
-rw-r--r--users/views/admin/__init__.py1
-rw-r--r--users/views/admin/federation.py57
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,
+ }