Browse Source

Merge pull request #756 from timunis/master

Add a link to the User list view on django admin that points to misago admin.

For future reference: let's not bother with constants for http's status codes. I know, I know, but I'm on the "http status codes ain't magic numbers" side of this debate ;)
Rafał Pitoń 8 years ago
parent
commit
75ff7c223d
3 changed files with 101 additions and 112 deletions
  1. 3 3
      misago/users/admin.py
  2. 41 85
      misago/users/djangoadmin.py
  3. 57 24
      misago/users/tests/test_djangoadmin_user.py

+ 3 - 3
misago/users/admin.py

@@ -1,8 +1,9 @@
 from django.conf.urls import url
 from django.contrib import admin as djadmin
+from django.contrib.auth import get_user_model
 from django.utils.translation import ugettext_lazy as _
 
-from .djangoadmin import UserAdmin, UserModel
+from .djangoadmin import UserAdminModel
 from .views.admin.bans import BansList, DeleteBan, EditBan, NewBan
 from .views.admin.ranks import (
     DefaultRank, DeleteRank, EditRank, MoveDownRank, MoveUpRank, NewRank, RanksList, RankUsers)
@@ -10,8 +11,7 @@ from .views.admin.users import (
     DeleteAccountStep, DeletePostsStep, DeleteThreadsStep, EditUser, NewUser, UsersList)
 
 
-# register misago user model in django admin panel
-djadmin.site.register(model_or_iterable=UserModel, admin_class=UserAdmin)
+djadmin.site.register(model_or_iterable=get_user_model(), admin_class=UserAdminModel)
 
 
 class MisagoAdminExtension(object):

+ 41 - 85
misago/users/djangoadmin.py

@@ -1,101 +1,57 @@
-"""
-Defines `UserAdminModel` for registration of Misago `User` model in django
-admin panel.
-
-The model supposed to be used for interaction of third party django apps with
-Misago `User` model, i.e. assignment to a `User` permissions or groups.
-
-Registration call is placed in :mod:`misago.users.admin`.
-
-Test for the model is placed in :mod:`misago.users.tests.test_djangoadmin_user`.
-"""
-from django import forms
-from django.contrib import admin
-from django.contrib.auth import get_user_model
+from django.contrib.admin import ModelAdmin
 from django.urls import reverse
 from django.utils.html import format_html
 from django.utils.translation import ugettext as _
 
 
-# Misago user model
-UserModel = get_user_model()
-
-
-class UserAdminForm(forms.ModelForm):
+class UserAdminModel(ModelAdmin):
     """
-    This form adds `edit_from_misago_link` pseudo-field, that renders
-    itself like an html hyperlink to a user edit page in misago admin panel.
-
-    This could be done with `User` edit template overwrite, but
-    it is kind of overkill - overwrite the whole template just to add one
-    button - isn't it?
+    The model should be used for interaction of third party django apps with
+    Misago's `User`.
+    
+    Removes `new` and `delete` actions (use Misago admin for that).
+    
+    Registration call is placed in :mod:`misago.users.admin`.
+    The tests are in :mod:`misago.users.tests.test_djangoadmin_user`.
     """
-    edit_from_misago_link = forms.Field()
-
-    def __init__(self, *args, **kwargs):
-        super(UserAdminForm, self).__init__(*args, **kwargs)
-        self.init_edit_from_misago_link_field()
-
-    def init_edit_from_misago_link_field(self):
-        """init for the pseudo-field, and replace it's widget `render`"""
-        field = self.fields['edit_from_misago_link']
-        field.required = False
-        field.label = ''
-        field.widget.render = self.render_edit_from_misago_link
-
-    def render_edit_from_misago_link(self, *args, **kwargs):
-        """composes an html hyperlink for the pseudo-field render"""
-        text = _('Edit this user in Misago admin panel')
-        link_html_template = ('<a href="{}" target="blank">' + text + '</a>')
-        link_url = reverse(
-            viewname='misago:admin:users:accounts:edit',
-            kwargs={'pk': self.instance.pk},
-        )
-        link_html = format_html(link_html_template, link_url)
-
-        return link_html
-
-    class Meta:
-        model = UserModel
-        fields = ['edit_from_misago_link']
 
+    list_display = (
+        'username', 'email', 'rank', 'is_staff', 'is_superuser', 'get_edit_from_misago_url',
+    )
+    search_fields = ('username', 'email')
+    list_filter = ('groups', 'rank', 'is_staff', 'is_superuser')
 
-class UserAdmin(admin.ModelAdmin):
-    """
-    Redeclare most of the model fields like read-only.
-    Prevents new/delete actions (users should use misago admin panel for
-    that).
-    Replaces default form with custom `UserAdminForm`.
-    """
-    list_display = ['username', 'email', 'is_staff', 'is_superuser']
-    search_fields = ['username', 'email']
-    list_filter = ['groups', 'is_staff', 'is_superuser']
-
-    form = UserAdminForm
     actions = None
-    readonly_fields = [
-        'username', 'email', 'rank', 'last_login', 'joined_on', 'is_staff', 'is_superuser'
-    ]
-    fieldsets = [
-        [
-            _('Misago user data'),
-            {
-                'fields': (
-                    'username', 'email', 'rank', 'last_login', 'joined_on', 'is_staff',
-                    'is_superuser', 'edit_from_misago_link',
-                )
-            },
-        ],
-        [
-            _('Edit permissions and groups'),
-            {
-                'fields': ('groups', 'user_permissions', )
-            },
-        ],
-    ]
+    readonly_fields = (
+        'username', 'email', 'joined_on', 'last_login', 'rank', 'is_staff', 'is_superuser',
+        'get_edit_from_misago_url',
+    )
+    fieldsets = ((
+        _("Misago user data"), {
+            'fields': (
+                'username', 'email', 'joined_on', 'last_login', 'rank', 'is_staff', 'is_superuser',
+                'get_edit_from_misago_url',
+            )
+        },
+    ), (_("Edit permissions and groups"), {
+        'fields': ('groups', 'user_permissions', )
+    }, ), )
 
     def has_add_permission(self, request):
         return False
 
     def has_delete_permission(self, request, obj=None):
         return False
+
+    def get_edit_from_misago_url(self, user_instance):
+        return format_html(
+            '<a href="{link}" class="{cls}" target="blank">{text}</a>',
+            link=reverse(
+                viewname='misago:admin:users:accounts:edit',
+                kwargs={'pk': user_instance.pk},
+            ),
+            cls='changelink',
+            text=_("Edit"),
+        )
+
+    get_edit_from_misago_url.short_description = _("Edit the user from Misago admin panel")

+ 57 - 24
misago/users/tests/test_djangoadmin_user.py

@@ -1,3 +1,5 @@
+from rest_framework import status
+
 from django.contrib.auth import get_user_model
 from django.contrib.auth.models import Permission
 from django.test import override_settings
@@ -5,44 +7,75 @@ from django.urls import reverse
 from django.utils import formats
 
 from misago.admin.testutils import AdminTestCase
-
-
-UserModel = get_user_model()
+from misago.users.djangoadmin import UserAdminModel
 
 
 @override_settings(ROOT_URLCONF='misago.core.testproject.urls')
 class TestDjangoAdminUserForm(AdminTestCase):
-    def test_edit_page_content(self):
-        """assert that edit-view of `test_user` contains expected content."""
-        test_user = UserModel.objects.create_user(
+    def setUp(self):
+        super(TestDjangoAdminUserForm, self).setUp()
+        self.test_user = get_user_model().objects.create_user(
             username='Bob',
             email='bob@test.com',
             password='Pass.123',
         )
-
-        test_user_edit_view = reverse(
-            viewname='admin:misago_users_user_change',
-            args=[test_user.id],
+        self.edit_test_user_in_django_url = reverse(
+            'admin:misago_users_user_change',
+            args=[self.test_user.pk],
         )
-        response = self.client.get(test_user_edit_view)
+        self.edit_test_user_in_misago_url = reverse(
+            'misago:admin:users:accounts:edit',
+            args=[self.test_user.pk],
+        )
+
+    def test_user_edit_view_content(self):
+        """basic data about a user is present in Django admin"""
+        response = self.client.get(self.edit_test_user_in_django_url)
 
-        self.assertEqual(response.status_code, 200)
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
 
-        self.assertContains(response, test_user.username)
-        self.assertContains(response, test_user.email)
-        self.assertContains(response, test_user.rank)
+        self.assertContains(response, self.test_user.username)
+        self.assertContains(response, self.test_user.email)
+        self.assertContains(response, self.test_user.rank)
 
-        last_login_date = formats.date_format(test_user.last_login)
-        register_date = formats.date_format(test_user.joined_on)
+        last_login_date = formats.date_format(self.test_user.last_login)
         self.assertContains(response, last_login_date)
+
+        register_date = formats.date_format(self.test_user.joined_on)
         self.assertContains(response, register_date)
 
-        edit_from_misago_admin_link = reverse(
-            viewname='misago:admin:users:accounts:edit',
-            kwargs={'pk': test_user.pk},
+        user_permissions = Permission.objects.all()
+        for permission in user_permissions:
+            self.assertContains(response, permission)
+
+    def test_user_edit_view_post(self):
+        """a user's permissions are editable through Django admin"""
+        perms_all = Permission.objects.all()
+        perms_all_pks = []
+        for perm in perms_all:
+            perms_all_pks.append(perm.pk)
+
+        response = self.client.post(
+            self.edit_test_user_in_django_url,
+            data={'user_permissions': perms_all_pks},
         )
-        self.assertContains(response, edit_from_misago_admin_link)
+        self.assertEqual(response.status_code, status.HTTP_302_FOUND)
 
-        user_perms_form_data = Permission.objects.all()
-        for permission in user_perms_form_data:
-            self.assertContains(response, permission)
+        user_perms = self.test_user.user_permissions.all()
+        for perm_pk in perms_all_pks:
+            is_user_has_perm = user_perms.filter(pk=perm_pk).exists()
+            self.assertTrue(is_user_has_perm)
+
+    def test_misago_admin_url_presence_in_user_edit_view(self):
+        """the url to Misago admin is present in Django admin user edit view"""
+        response = self.client.get(self.edit_test_user_in_django_url)
+        self.assertContains(response, self.edit_test_user_in_misago_url)
+        edit_from_misago_short_desc = UserAdminModel.get_edit_from_misago_url.short_description
+        self.assertContains(response, edit_from_misago_short_desc)
+
+    def test_misago_admin_url_presence_in_user_list_view(self):
+        """the url to Misago admin is present in Django admin user list view"""
+        response = self.client.get(
+            reverse('admin:misago_users_user_changelist'),
+        )
+        self.assertContains(response, self.edit_test_user_in_misago_url)