diff --git a/api/funkwhale_api/users/admin.py b/api/funkwhale_api/users/admin.py index 303f4f9c3..c11c33bb6 100644 --- a/api/funkwhale_api/users/admin.py +++ b/api/funkwhale_api/users/admin.py @@ -33,6 +33,20 @@ class MyUserCreationForm(UserCreationForm): raise forms.ValidationError(self.error_messages["duplicate_username"]) +def disable(modeladmin, request, queryset): + queryset.exclude(pk=request.user.pk).update(is_active=False) + + +disable.short_description = "Disable login" + + +def enable(modeladmin, request, queryset): + queryset.update(is_active=True) + + +enable.short_description = "Enable login" + + @admin.register(models.User) class UserAdmin(AuthUserAdmin): form = MyUserChangeForm @@ -40,6 +54,7 @@ class UserAdmin(AuthUserAdmin): list_display = [ "username", "email", + "is_active", "date_joined", "last_login", "is_staff", @@ -53,7 +68,7 @@ class UserAdmin(AuthUserAdmin): "permission_library", "permission_moderation", ] - + actions = [disable, enable] fieldsets = ( (None, {"fields": ("username", "password", "privacy_level")}), ( diff --git a/api/funkwhale_api/users/models.py b/api/funkwhale_api/users/models.py index 8ef06c871..3748dd634 100644 --- a/api/funkwhale_api/users/models.py +++ b/api/funkwhale_api/users/models.py @@ -388,3 +388,10 @@ def warm_user_avatar(sender, instance, **kwargs): instance_or_queryset=instance, rendition_key_set="square", image_attr="avatar" ) num_created, failed_to_create = user_avatar_warmer.warm() + + +@receiver(models.signals.pre_delete, sender=User) +def delete_actor(sender, instance, **kwargs): + if not instance.actor: + return + instance.actor.delete() diff --git a/api/tests/users/test_models.py b/api/tests/users/test_models.py index 4b2f71bca..1b185e55f 100644 --- a/api/tests/users/test_models.py +++ b/api/tests/users/test_models.py @@ -219,3 +219,13 @@ def test_user_get_quota_status(factories, preferences, mocker): "errored": 3, "finished": 4, } + + +def test_deleting_users_deletes_associated_actor(factories): + actor = factories["federation.Actor"]() + user = factories["users.User"](actor=actor) + + user.delete() + + with pytest.raises(actor.DoesNotExist): + actor.refresh_from_db() diff --git a/changes/changelog.d/809.enhancement b/changes/changelog.d/809.enhancement new file mode 100644 index 000000000..92a4e57bc --- /dev/null +++ b/changes/changelog.d/809.enhancement @@ -0,0 +1 @@ +Added admin options to disable login for users, ensure related content is deleted when deleting a user account (#809) diff --git a/front/src/views/admin/moderation/AccountsDetail.vue b/front/src/views/admin/moderation/AccountsDetail.vue index d863af52d..09b5bb824 100644 --- a/front/src/views/admin/moderation/AccountsDetail.vue +++ b/front/src/views/admin/moderation/AccountsDetail.vue @@ -27,6 +27,35 @@ +
+
+ + + View in Django's admin  + + + + View in Django's admin  + + +
+