mirror of
https://github.com/jointakahe/takahe.git
synced 2024-11-25 08:41:00 +00:00
Call it admin rather than system settings
This commit is contained in:
parent
9d97fc92d8
commit
5b34ea46c3
27 changed files with 273 additions and 111 deletions
18
activities/migrations/0006_alter_post_hashtags.py
Normal file
18
activities/migrations/0006_alter_post_hashtags.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 4.1.3 on 2022-11-17 04:18
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("activities", "0005_post_hashtags_alter_fanout_type_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="post",
|
||||
name="hashtags",
|
||||
field=models.JSONField(blank=True, null=True),
|
||||
),
|
||||
]
|
|
@ -117,7 +117,7 @@ class Post(StatorModel):
|
|||
)
|
||||
|
||||
# Hashtags in the post
|
||||
hashtags = models.JSONField(default=[])
|
||||
hashtags = models.JSONField(blank=True, null=True)
|
||||
|
||||
# When the post was originally created (as opposed to when we received it)
|
||||
published = models.DateTimeField(default=timezone.now)
|
||||
|
@ -296,36 +296,38 @@ class Post(StatorModel):
|
|||
"""
|
||||
Handles an incoming create request
|
||||
"""
|
||||
# Ensure the Create actor is the Post's attributedTo
|
||||
if data["actor"] != data["object"]["attributedTo"]:
|
||||
raise ValueError("Create actor does not match its Post object", data)
|
||||
# Create it
|
||||
post = cls.by_ap(data["object"], create=True, update=True)
|
||||
# Make timeline events for followers
|
||||
for follow in Follow.objects.filter(target=post.author, source__local=True):
|
||||
TimelineEvent.add_post(follow.source, post)
|
||||
# Make timeline events for mentions if they're local
|
||||
for mention in post.mentions.all():
|
||||
if mention.local:
|
||||
TimelineEvent.add_mentioned(mention, post)
|
||||
# Force it into fanned_out as it's not ours
|
||||
post.transition_perform(PostStates.fanned_out)
|
||||
with transaction.atomic():
|
||||
# Ensure the Create actor is the Post's attributedTo
|
||||
if data["actor"] != data["object"]["attributedTo"]:
|
||||
raise ValueError("Create actor does not match its Post object", data)
|
||||
# Create it
|
||||
post = cls.by_ap(data["object"], create=True, update=True)
|
||||
# Make timeline events for followers
|
||||
for follow in Follow.objects.filter(target=post.author, source__local=True):
|
||||
TimelineEvent.add_post(follow.source, post)
|
||||
# Make timeline events for mentions if they're local
|
||||
for mention in post.mentions.all():
|
||||
if mention.local:
|
||||
TimelineEvent.add_mentioned(mention, post)
|
||||
# Force it into fanned_out as it's not ours
|
||||
post.transition_perform(PostStates.fanned_out)
|
||||
|
||||
@classmethod
|
||||
def handle_delete_ap(cls, data):
|
||||
"""
|
||||
Handles an incoming create request
|
||||
"""
|
||||
# Find our post by ID if we have one
|
||||
try:
|
||||
post = cls.by_object_uri(data["object"]["id"])
|
||||
except cls.DoesNotExist:
|
||||
# It's already been deleted
|
||||
return
|
||||
# Ensure the actor on the request authored the post
|
||||
if not post.author.actor_uri == data["actor"]:
|
||||
raise ValueError("Actor on delete does not match object")
|
||||
post.delete()
|
||||
with transaction.atomic():
|
||||
# Find our post by ID if we have one
|
||||
try:
|
||||
post = cls.by_object_uri(data["object"]["id"])
|
||||
except cls.DoesNotExist:
|
||||
# It's already been deleted
|
||||
return
|
||||
# Ensure the actor on the request authored the post
|
||||
if not post.author.actor_uri == data["actor"]:
|
||||
raise ValueError("Actor on delete does not match object")
|
||||
post.delete()
|
||||
|
||||
def debug_fetch(self):
|
||||
"""
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from typing import Dict
|
||||
|
||||
from django.db import models
|
||||
from django.db import models, transaction
|
||||
from django.utils import timezone
|
||||
|
||||
from activities.models.fan_out import FanOut
|
||||
|
@ -272,31 +272,33 @@ class PostInteraction(StatorModel):
|
|||
"""
|
||||
Handles an incoming announce/like
|
||||
"""
|
||||
# Create it
|
||||
interaction = cls.by_ap(data, create=True)
|
||||
# Boosts (announces) go to everyone who follows locally
|
||||
if interaction.type == cls.Types.boost:
|
||||
for follow in Follow.objects.filter(
|
||||
target=interaction.identity, source__local=True
|
||||
):
|
||||
TimelineEvent.add_post_interaction(follow.source, interaction)
|
||||
# Likes go to just the author of the post
|
||||
elif interaction.type == cls.Types.like:
|
||||
TimelineEvent.add_post_interaction(interaction.post.author, interaction)
|
||||
# Force it into fanned_out as it's not ours
|
||||
interaction.transition_perform(PostInteractionStates.fanned_out)
|
||||
with transaction.atomic():
|
||||
# Create it
|
||||
interaction = cls.by_ap(data, create=True)
|
||||
# Boosts (announces) go to everyone who follows locally
|
||||
if interaction.type == cls.Types.boost:
|
||||
for follow in Follow.objects.filter(
|
||||
target=interaction.identity, source__local=True
|
||||
):
|
||||
TimelineEvent.add_post_interaction(follow.source, interaction)
|
||||
# Likes go to just the author of the post
|
||||
elif interaction.type == cls.Types.like:
|
||||
TimelineEvent.add_post_interaction(interaction.post.author, interaction)
|
||||
# Force it into fanned_out as it's not ours
|
||||
interaction.transition_perform(PostInteractionStates.fanned_out)
|
||||
|
||||
@classmethod
|
||||
def handle_undo_ap(cls, data):
|
||||
"""
|
||||
Handles an incoming undo for a announce/like
|
||||
"""
|
||||
# Find it
|
||||
interaction = cls.by_ap(data["object"])
|
||||
# Verify the actor matches
|
||||
if data["actor"] != interaction.identity.actor_uri:
|
||||
raise ValueError("Actor mismatch on interaction undo")
|
||||
# Delete all events that reference it
|
||||
interaction.timeline_events.all().delete()
|
||||
# Force it into undone_fanned_out as it's not ours
|
||||
interaction.transition_perform(PostInteractionStates.undone_fanned_out)
|
||||
with transaction.atomic():
|
||||
# Find it
|
||||
interaction = cls.by_ap(data["object"])
|
||||
# Verify the actor matches
|
||||
if data["actor"] != interaction.identity.actor_uri:
|
||||
raise ValueError("Actor mismatch on interaction undo")
|
||||
# Delete all events that reference it
|
||||
interaction.timeline_events.all().delete()
|
||||
# Force it into undone_fanned_out as it's not ours
|
||||
interaction.transition_perform(PostInteractionStates.undone_fanned_out)
|
||||
|
|
|
@ -108,7 +108,6 @@ class Boost(View):
|
|||
class Compose(FormView):
|
||||
|
||||
template_name = "activities/compose.html"
|
||||
extra_context = {"top_section": "compose"}
|
||||
|
||||
class form_class(forms.Form):
|
||||
text = forms.CharField(
|
||||
|
|
|
@ -7,4 +7,5 @@ def config_context(request):
|
|||
"config_identity": (
|
||||
Config.load_identity(request.identity) if request.identity else None
|
||||
),
|
||||
"top_section": request.path.strip("/").split("/")[0],
|
||||
}
|
||||
|
|
|
@ -58,6 +58,10 @@ a {
|
|||
text-decoration: none;
|
||||
}
|
||||
|
||||
p a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
html:focus-within {
|
||||
scroll-behavior: auto;
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
from django.contrib import admin
|
||||
from django.contrib import admin as djadmin
|
||||
from django.urls import path
|
||||
|
||||
from activities.views import posts, timelines
|
||||
from core import views as core
|
||||
from stator import views as stator
|
||||
from users.views import activitypub, auth, identity, settings_identity, settings_system
|
||||
from users.views import activitypub, admin, auth, identity, settings
|
||||
|
||||
urlpatterns = [
|
||||
path("", core.homepage),
|
||||
|
@ -13,16 +13,53 @@ urlpatterns = [
|
|||
path("notifications/", timelines.Notifications.as_view()),
|
||||
path("local/", timelines.Local.as_view()),
|
||||
path("federated/", timelines.Federated.as_view()),
|
||||
path("settings/", settings_identity.IdentitySettingsRoot.as_view()),
|
||||
path("settings/interface/", settings_identity.InterfacePage.as_view()),
|
||||
path("settings/system/", settings_system.SystemSettingsRoot.as_view()),
|
||||
path("settings/system/basic/", settings_system.BasicPage.as_view()),
|
||||
path("settings/system/domains/", settings_system.DomainsPage.as_view()),
|
||||
path("settings/system/domains/create/", settings_system.DomainCreatePage.as_view()),
|
||||
path("settings/system/domains/<domain>/", settings_system.DomainEditPage.as_view()),
|
||||
path(
|
||||
"settings/system/domains/<domain>/delete/",
|
||||
settings_system.DomainDeletePage.as_view(),
|
||||
"settings/",
|
||||
settings.SettingsRoot.as_view(),
|
||||
name="settings",
|
||||
),
|
||||
path(
|
||||
"settings/interface/",
|
||||
settings.InterfacePage.as_view(),
|
||||
name="settings_interface",
|
||||
),
|
||||
path(
|
||||
"admin/",
|
||||
admin.AdminRoot.as_view(),
|
||||
name="admin",
|
||||
),
|
||||
path(
|
||||
"admin/basic/",
|
||||
admin.BasicPage.as_view(),
|
||||
name="admin_basic",
|
||||
),
|
||||
path(
|
||||
"admin/domains/",
|
||||
admin.DomainsPage.as_view(),
|
||||
name="admin_domains",
|
||||
),
|
||||
path(
|
||||
"admin/domains/create/",
|
||||
admin.DomainCreatePage.as_view(),
|
||||
name="admin_domains_create",
|
||||
),
|
||||
path(
|
||||
"admin/domains/<domain>/",
|
||||
admin.DomainEditPage.as_view(),
|
||||
),
|
||||
path(
|
||||
"admin/domains/<domain>/delete/",
|
||||
admin.DomainDeletePage.as_view(),
|
||||
),
|
||||
path(
|
||||
"admin/users/",
|
||||
admin.UsersPage.as_view(),
|
||||
name="admin_users",
|
||||
),
|
||||
path(
|
||||
"admin/identities/",
|
||||
admin.IdentitiesPage.as_view(),
|
||||
name="admin_identities",
|
||||
),
|
||||
# Identity views
|
||||
path("@<handle>/", identity.ViewIdentity.as_view()),
|
||||
|
@ -49,5 +86,5 @@ urlpatterns = [
|
|||
# Task runner
|
||||
path(".stator/runner/", stator.RequestRunner.as_view()),
|
||||
# Django admin
|
||||
path("djadmin/", admin.site.urls),
|
||||
path("djadmin/", djadmin.site.urls),
|
||||
]
|
||||
|
|
6
templates/admin/_menu.html
Normal file
6
templates/admin/_menu.html
Normal file
|
@ -0,0 +1,6 @@
|
|||
<nav>
|
||||
<a href="{% url "admin_basic" %}" {% if section == "basic" %}class="selected"{% endif %}>Basic</a>
|
||||
<a href="{% url "admin_domains" %}" {% if section == "domains" %}class="selected"{% endif %}>Domains</a>
|
||||
<a href="{% url "admin_users" %}" {% if section == "users" %}class="selected"{% endif %}>Users</a>
|
||||
<a href="{% url "admin_identities" %}" {% if section == "identities" %}class="selected"{% endif %}>Identities</a>
|
||||
</nav>
|
|
@ -1,10 +1,10 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Add Domain - System Settings{% endblock %}
|
||||
{% block title %}Add Domain - Admin{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% block menu %}
|
||||
{% include "settings/_settings_system_menu.html" %}
|
||||
{% include "admin/_menu.html" %}
|
||||
{% endblock %}
|
||||
<form action="." method="POST">
|
||||
<h1>Add A Domain</h1>
|
|
@ -1,10 +1,10 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Delete {{ domain.domain }} - System Settings{% endblock %}
|
||||
{% block title %}Delete {{ domain.domain }} - Admin{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% block menu %}
|
||||
{% include "settings/_settings_system_menu.html" %}
|
||||
{% include "admin/_menu.html" %}
|
||||
{% endblock %}
|
||||
|
||||
<form action="." method="POST">
|
|
@ -1,10 +1,10 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}{{ domain.domain }} - System Settings{% endblock %}
|
||||
{% block title %}{{ domain.domain }} - Admin{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% block menu %}
|
||||
{% include "settings/_settings_system_menu.html" %}
|
||||
{% include "admin/_menu.html" %}
|
||||
{% endblock %}
|
||||
<form action="." method="POST">
|
||||
{% csrf_token %}
|
|
@ -1,10 +1,10 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}{{ section.title }} - System Settings{% endblock %}
|
||||
{% block title %}{{ section.title }} - Admin{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% block menu %}
|
||||
{% include "settings/_settings_system_menu.html" %}
|
||||
{% include "admin/_menu.html" %}
|
||||
{% endblock %}
|
||||
<section class="icon-menu">
|
||||
{% for domain in domains %}
|
||||
|
@ -21,7 +21,7 @@
|
|||
{% empty %}
|
||||
<p class="option empty">You have no domains set up.</p>
|
||||
{% endfor %}
|
||||
<a href="/settings/system/domains/create/" class="option new">
|
||||
<a href="{% url "admin_domains_create" %}" class="option new">
|
||||
<i class="fa-solid fa-plus"></i> Add a domain
|
||||
</a>
|
||||
</section>
|
14
templates/admin/identities.html
Normal file
14
templates/admin/identities.html
Normal file
|
@ -0,0 +1,14 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Identities - Admin{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% block menu %}
|
||||
{% include "admin/_menu.html" %}
|
||||
{% endblock %}
|
||||
<form>
|
||||
<p>
|
||||
Please use the <a href="/djadmin/users/identity/">Django Admin</a> for now.
|
||||
</p>
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -1,10 +1,10 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}{{ section.title }} - System Settings{% endblock %}
|
||||
{% block title %}{{ section.title }} - Admin{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% block menu %}
|
||||
{% include "settings/_settings_system_menu.html" %}
|
||||
{% include "admin/_menu.html" %}
|
||||
{% endblock %}
|
||||
<form action="." method="POST">
|
||||
{% csrf_token %}
|
14
templates/admin/users.html
Normal file
14
templates/admin/users.html
Normal file
|
@ -0,0 +1,14 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Users - Admin{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% block menu %}
|
||||
{% include "admin/_menu.html" %}
|
||||
{% endblock %}
|
||||
<form>
|
||||
<p>
|
||||
Please use the <a href="/djadmin/users/user/">Django Admin</a> for now.
|
||||
</p>
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -31,11 +31,11 @@
|
|||
<a href="/compose/" title="Compose" {% if top_section == "compose" %}class="selected"{% endif %}>
|
||||
<i class="fa-solid fa-feather"></i> Compose
|
||||
</a>
|
||||
<a href="/settings/" title="Settings" {% if top_section == "settings" %}class="selected"{% endif %}>
|
||||
<a href="{% url "settings" %}" title="Settings" {% if top_section == "settings" %}class="selected"{% endif %}>
|
||||
<i class="fa-solid fa-gear"></i> Settings
|
||||
</a>
|
||||
{% if request.user.admin %}
|
||||
<a href="/settings/system/" title="Admin" {% if top_section == "settings_system" %}class="selected"{% endif %}>
|
||||
<a href="{% url "admin" %}" title="Admin" {% if top_section == "admin" %}class="selected"{% endif %}>
|
||||
<i class="fa-solid fa-toolbox"></i> Admin
|
||||
</a>
|
||||
{% endif %}
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
<nav>
|
||||
<a href="/settings/system/basic/" {% if section == "basic" %}class="selected"{% endif %}>Basic</a>
|
||||
<a href="/settings/system/domains/" {% if section == "domains" %}class="selected"{% endif %}>Domains</a>
|
||||
<a href="/settings/system/users/" {% if section == "users" %}class="selected"{% endif %}>Users</a>
|
||||
</nav>
|
18
templates/settings/settings.html
Normal file
18
templates/settings/settings.html
Normal file
|
@ -0,0 +1,18 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}{{ section.title }} - Settings{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% block menu %}
|
||||
{% include "settings/_menu.html" %}
|
||||
{% endblock %}
|
||||
<form action="." method="POST">
|
||||
{% csrf_token %}
|
||||
{% for field in form %}
|
||||
{% include "forms/_field.html" %}
|
||||
{% endfor %}
|
||||
<div class="buttons">
|
||||
<button>Save</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -1,7 +0,0 @@
|
|||
{% extends "settings/settings_system.html" %}
|
||||
|
||||
{% block title %}{{ section.title }} - Settings{% endblock %}
|
||||
|
||||
{% block menu %}
|
||||
{% include "settings/_settings_identity_menu.html" %}
|
||||
{% endblock %}
|
|
@ -10,7 +10,7 @@ class DomainAdmin(admin.ModelAdmin):
|
|||
|
||||
@admin.register(User)
|
||||
class UserAdmin(admin.ModelAdmin):
|
||||
pass
|
||||
list_display = ["email", "created", "last_seen", "admin", "moderator", "banned"]
|
||||
|
||||
|
||||
@admin.register(UserEvent)
|
||||
|
@ -21,6 +21,7 @@ class UserEventAdmin(admin.ModelAdmin):
|
|||
@admin.register(Identity)
|
||||
class IdentityAdmin(admin.ModelAdmin):
|
||||
list_display = ["id", "handle", "actor_uri", "state", "local"]
|
||||
list_filter = ["local"]
|
||||
raw_id_fields = ["users"]
|
||||
actions = ["force_update"]
|
||||
readonly_fields = ["actor_json"]
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
from users.models import Identity
|
||||
from django.utils import timezone
|
||||
|
||||
from users.models import Identity, User
|
||||
|
||||
|
||||
class IdentityMiddleware:
|
||||
|
@ -17,6 +19,7 @@ class IdentityMiddleware:
|
|||
else:
|
||||
try:
|
||||
request.identity = Identity.objects.get(id=identity_id)
|
||||
User.objects.filter(pk=request.user.pk).update(last_seen=timezone.now())
|
||||
except Identity.DoesNotExist:
|
||||
request.identity = None
|
||||
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
# Generated by Django 4.1.3 on 2022-11-17 04:18
|
||||
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("users", "0002_identity_public_key_id"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="user",
|
||||
name="last_seen",
|
||||
field=models.DateTimeField(
|
||||
auto_now_add=True, default=django.utils.timezone.now
|
||||
),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="identity",
|
||||
name="domain",
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
related_name="identities",
|
||||
to="users.domain",
|
||||
),
|
||||
),
|
||||
]
|
|
@ -49,10 +49,10 @@ class Domain(models.Model):
|
|||
updated = models.DateTimeField(auto_now=True)
|
||||
|
||||
class urls(urlman.Urls):
|
||||
root = "/settings/system/domains/"
|
||||
create = "/settings/system/domains/create/"
|
||||
edit = "/settings/system/domains/{self.domain}/"
|
||||
delete = "/settings/system/domains/{self.domain}/delete/"
|
||||
root = "/admin/domains/"
|
||||
create = "/admin/domains/create/"
|
||||
edit = "/admin/domains/{self.domain}/"
|
||||
delete = "/admin/domains/{self.domain}/delete/"
|
||||
|
||||
@classmethod
|
||||
def get_remote_domain(cls, domain: str) -> "Domain":
|
||||
|
|
|
@ -38,6 +38,7 @@ class User(AbstractBaseUser):
|
|||
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
updated = models.DateTimeField(auto_now=True)
|
||||
last_seen = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
USERNAME_FIELD = "email"
|
||||
EMAIL_FIELD = "email"
|
||||
|
|
|
@ -10,28 +10,26 @@ from django.views.generic import FormView, RedirectView, TemplateView
|
|||
|
||||
from core.models import Config
|
||||
from users.decorators import admin_required
|
||||
from users.models import Domain
|
||||
from users.models import Domain, Identity, User
|
||||
|
||||
|
||||
@method_decorator(admin_required, name="dispatch")
|
||||
class SystemSettingsRoot(RedirectView):
|
||||
url = "/settings/system/basic/"
|
||||
class AdminRoot(RedirectView):
|
||||
pattern_name = "admin_basic"
|
||||
|
||||
|
||||
@method_decorator(admin_required, name="dispatch")
|
||||
class SystemSettingsPage(FormView):
|
||||
class AdminSettingsPage(FormView):
|
||||
"""
|
||||
Shows a settings page dynamically created from our settings layout
|
||||
at the bottom of the page. Don't add this to a URL directly - subclass!
|
||||
"""
|
||||
|
||||
template_name = "settings/settings_system.html"
|
||||
template_name = "admin/settings.html"
|
||||
options_class = Config.SystemOptions
|
||||
section: ClassVar[str]
|
||||
options: Dict[str, Dict[str, str]]
|
||||
|
||||
extra_context = {"top_section": "settings_system"}
|
||||
|
||||
def get_form_class(self):
|
||||
# Create the fields dict from the config object
|
||||
fields = {}
|
||||
|
@ -84,7 +82,7 @@ class SystemSettingsPage(FormView):
|
|||
return redirect(".")
|
||||
|
||||
|
||||
class BasicPage(SystemSettingsPage):
|
||||
class BasicPage(AdminSettingsPage):
|
||||
|
||||
section = "basic"
|
||||
|
||||
|
@ -103,7 +101,7 @@ class BasicPage(SystemSettingsPage):
|
|||
@method_decorator(admin_required, name="dispatch")
|
||||
class DomainsPage(TemplateView):
|
||||
|
||||
template_name = "settings/settings_system_domains.html"
|
||||
template_name = "admin/domains.html"
|
||||
|
||||
def get_context_data(self):
|
||||
return {
|
||||
|
@ -115,7 +113,7 @@ class DomainsPage(TemplateView):
|
|||
@method_decorator(admin_required, name="dispatch")
|
||||
class DomainCreatePage(FormView):
|
||||
|
||||
template_name = "settings/settings_system_domain_create.html"
|
||||
template_name = "admin/domain_create.html"
|
||||
extra_context = {"section": "domains"}
|
||||
|
||||
class form_class(forms.Form):
|
||||
|
@ -175,7 +173,7 @@ class DomainCreatePage(FormView):
|
|||
@method_decorator(admin_required, name="dispatch")
|
||||
class DomainEditPage(FormView):
|
||||
|
||||
template_name = "settings/settings_system_domain_edit.html"
|
||||
template_name = "admin/domain_edit.html"
|
||||
extra_context = {"section": "domains"}
|
||||
|
||||
class form_class(forms.Form):
|
||||
|
@ -221,7 +219,7 @@ class DomainEditPage(FormView):
|
|||
@method_decorator(admin_required, name="dispatch")
|
||||
class DomainDeletePage(TemplateView):
|
||||
|
||||
template_name = "settings/settings_system_domain_delete.html"
|
||||
template_name = "admin/domain_delete.html"
|
||||
|
||||
def dispatch(self, request, domain):
|
||||
self.domain = get_object_or_404(
|
||||
|
@ -241,3 +239,27 @@ class DomainDeletePage(TemplateView):
|
|||
raise ValueError("Tried to delete domain with identities!")
|
||||
self.domain.delete()
|
||||
return redirect("/settings/system/domains/")
|
||||
|
||||
|
||||
@method_decorator(admin_required, name="dispatch")
|
||||
class UsersPage(TemplateView):
|
||||
|
||||
template_name = "admin/users.html"
|
||||
|
||||
def get_context_data(self):
|
||||
return {
|
||||
"users": User.objects.order_by("email"),
|
||||
"section": "users",
|
||||
}
|
||||
|
||||
|
||||
@method_decorator(admin_required, name="dispatch")
|
||||
class IdentitiesPage(TemplateView):
|
||||
|
||||
template_name = "admin/identities.html"
|
||||
|
||||
def get_context_data(self):
|
||||
return {
|
||||
"identities": Identity.objects.order_by("username"),
|
||||
"section": "identities",
|
||||
}
|
|
@ -3,24 +3,22 @@ from django.views.generic import RedirectView
|
|||
|
||||
from core.models import Config
|
||||
from users.decorators import identity_required
|
||||
from users.views.settings_system import SystemSettingsPage
|
||||
from users.views.admin import AdminSettingsPage
|
||||
|
||||
|
||||
@method_decorator(identity_required, name="dispatch")
|
||||
class IdentitySettingsRoot(RedirectView):
|
||||
class SettingsRoot(RedirectView):
|
||||
url = "/settings/interface/"
|
||||
|
||||
|
||||
class IdentitySettingsPage(SystemSettingsPage):
|
||||
class SettingsPage(AdminSettingsPage):
|
||||
"""
|
||||
Shows a settings page dynamically created from our settings layout
|
||||
at the bottom of the page. Don't add this to a URL directly - subclass!
|
||||
"""
|
||||
|
||||
extra_context = {"top_section": "settings"}
|
||||
|
||||
options_class = Config.IdentityOptions
|
||||
template_name = "settings/settings_identity.html"
|
||||
template_name = "settings/settings.html"
|
||||
|
||||
def load_config(self):
|
||||
return Config.load_identity(self.request.identity)
|
||||
|
@ -29,7 +27,7 @@ class IdentitySettingsPage(SystemSettingsPage):
|
|||
Config.set_identity(self.request.identity, key, value)
|
||||
|
||||
|
||||
class InterfacePage(IdentitySettingsPage):
|
||||
class InterfacePage(SettingsPage):
|
||||
|
||||
section = "interface"
|
||||
|
Loading…
Reference in a new issue