diff --git a/bookwyrm/activitypub/base_activity.py b/bookwyrm/activitypub/base_activity.py
index 90f7b0a53..f1b3ad181 100644
--- a/bookwyrm/activitypub/base_activity.py
+++ b/bookwyrm/activitypub/base_activity.py
@@ -297,6 +297,7 @@ class Link(ActivityObject):
"""for tagging a book in a status"""
href: str
+ name: str
mediaType: str = None
id: str = None
type: str = "Link"
diff --git a/bookwyrm/migrations/0126_filelink_link_linkdomain.py b/bookwyrm/migrations/0126_filelink_link_linkdomain.py
index bd261102e..98d71cc26 100644
--- a/bookwyrm/migrations/0126_filelink_link_linkdomain.py
+++ b/bookwyrm/migrations/0126_filelink_link_linkdomain.py
@@ -83,6 +83,7 @@ class Migration(migrations.Migration):
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
+ related_name="links",
to="bookwyrm.linkdomain",
),
),
diff --git a/bookwyrm/models/link.py b/bookwyrm/models/link.py
index f2b4108b6..41760cc21 100644
--- a/bookwyrm/models/link.py
+++ b/bookwyrm/models/link.py
@@ -15,7 +15,7 @@ class Link(ActivitypubMixin, BookWyrmModel):
url = fields.URLField(max_length=255, activitypub_field="href")
domain = models.ForeignKey(
- "LinkDomain", on_delete=models.CASCADE, null=True, blank=True
+ "LinkDomain", on_delete=models.CASCADE, null=True, blank=True, related_name="links"
)
activity_serializer = activitypub.Link
diff --git a/bookwyrm/templates/settings/layout.html b/bookwyrm/templates/settings/layout.html
index d7a840af5..200164ba3 100644
--- a/bookwyrm/templates/settings/layout.html
+++ b/bookwyrm/templates/settings/layout.html
@@ -62,6 +62,10 @@
{% url 'settings-ip-blocks' as url %}
{% trans "IP Address Blocklist" %}
+
+ {% url 'settings-link-domain' status='pending' as url %}
+ {% trans "Link Domains" %}
+
{% endif %}
{% if perms.bookwyrm.edit_instance_settings %}
diff --git a/bookwyrm/templates/settings/link_domains/link_domains.html b/bookwyrm/templates/settings/link_domains/link_domains.html
new file mode 100644
index 000000000..555a81a11
--- /dev/null
+++ b/bookwyrm/templates/settings/link_domains/link_domains.html
@@ -0,0 +1,95 @@
+{% extends 'settings/layout.html' %}
+{% load humanize %}
+{% load i18n %}
+
+{% block title %}{% trans "Link Domains" %}{% endblock %}
+
+{% block header %}{% trans "Link Domains" %}{% endblock %}
+
+{% block panel %}
+
+ {% trans "Link domains must be approved before they are shown on book pages. Please make sure that the domains are not hosting spam, malicious code, or deceptive links before approving." %}
+
+
+
+
+
+ {% for domain in domains %}
+
+
+
+
+ {% trans "Set name" as button_text %}
+ {% include 'snippets/toggle/open_button.html' with text=button_text icon_with_text="pencil" controls_text="edit_domain" controls_uid=domain.id focus="id_description" %}
+
+
+
+
+
+
+ {% trans "View links" %}
+ ({{ domain.links.count }})
+
+
+
+
+
+ {% for link in domain.links.all|slice:10 %}
+ -
+ {{ link.url }}
+ {% if link.filelink.filetype %}
+ ({{ link.filelink.filetype }})
+ {% endif %}
+
+ {% endfor %}
+
+
+
+
+
+
+ {% endfor %}
+
+ {% if not domains.exists %}
+ {% if status == "approved" %}
+
{% trans "No domains currently approved" %}
+ {% elif status == "pending" %}
+
{% trans "No domains currently pending" %}
+ {% else %}
+
{% trans "No domains currently blocked" %}
+ {% endif %}
+ {% endif %}
+
+
+{% endblock %}
+
diff --git a/bookwyrm/urls.py b/bookwyrm/urls.py
index 397a8a414..61ff7ffaa 100644
--- a/bookwyrm/urls.py
+++ b/bookwyrm/urls.py
@@ -96,11 +96,6 @@ urlpatterns = [
re_path(
r"^settings/users/?$", views.UserAdminList.as_view(), name="settings-users"
),
- re_path(
- r"^settings/users/(?P\d+)/?$",
- views.UserAdmin.as_view(),
- name="settings-user",
- ),
re_path(
r"^settings/federation/(?P(federated|blocked))?/?$",
views.Federation.as_view(),
@@ -158,6 +153,11 @@ urlpatterns = [
views.EmailBlocklist.as_view(),
name="settings-email-blocks-delete",
),
+ re_path(
+ r"^setting/link-domains/(?P(pending|approved|blocked))/?",
+ views.LinkDomain.as_view(),
+ name="settings-link-domain",
+ ),
re_path(
r"^settings/ip-blocklist/?$",
views.IPBlocklist.as_view(),
diff --git a/bookwyrm/views/__init__.py b/bookwyrm/views/__init__.py
index bc8ac2a3d..d3d807039 100644
--- a/bookwyrm/views/__init__.py
+++ b/bookwyrm/views/__init__.py
@@ -9,6 +9,7 @@ from .admin.email_blocklist import EmailBlocklist
from .admin.ip_blocklist import IPBlocklist
from .admin.invite import ManageInvites, Invite, InviteRequest
from .admin.invite import ManageInviteRequests, ignore_invite_request
+from .admin.link_domains import LinkDomain
from .admin.reports import (
Report,
Reports,
diff --git a/bookwyrm/views/admin/link_domains.py b/bookwyrm/views/admin/link_domains.py
new file mode 100644
index 000000000..0b662b850
--- /dev/null
+++ b/bookwyrm/views/admin/link_domains.py
@@ -0,0 +1,32 @@
+""" Manage link domains"""
+from django.contrib.auth.decorators import login_required, permission_required
+from django.template.response import TemplateResponse
+from django.utils.decorators import method_decorator
+from django.views import View
+
+from bookwyrm import forms, models
+
+# pylint: disable=no-self-use
+@method_decorator(login_required, name="dispatch")
+@method_decorator(
+ permission_required("bookwyrm.moderate_user", raise_exception=True),
+ name="dispatch",
+)
+class LinkDomain(View):
+ """Moderate links"""
+
+ def get(self, request, status="pending"):
+ """view pending domains"""
+ data = {
+ "domains": models.LinkDomain.objects.filter(
+ status=status
+ ).prefetch_related("links"),
+ "form": forms.EmailBlocklistForm(),
+ "status": status,
+ }
+ return TemplateResponse(
+ request, "settings/link_domains/link_domains.html", data
+ )
+
+ def post(self, request):
+ """post?"""