From 3a286a5bc6d97303a9589b561f99d35446d20258 Mon Sep 17 00:00:00 2001 From: Dariusz Niemczyk Date: Thu, 20 Jul 2023 14:32:38 +0200 Subject: [PATCH] Add autocomplete for users in Admin and fix perms --- docker-compose.yml | 2 +- storage/admin.py | 42 +++++++++++++++++-- storage/migrations/0011_auto_20230720_1240.py | 42 +++++++++++++++++++ storage/models.py | 20 ++++++++- 4 files changed, 100 insertions(+), 6 deletions(-) create mode 100644 storage/migrations/0011_auto_20230720_1240.py diff --git a/docker-compose.yml b/docker-compose.yml index b2e95e6..e33c60a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,7 +9,7 @@ services: - POSTGRES_DB=postgres web: - image: registry.k0.hswaw.net/palid/spejstore:1689628039 + image: registry.k0.hswaw.net/palid/spejstore:1689856372 restart: always command: bash -c "python manage.py migrate && gunicorn -b 0.0.0.0:8000 --capture-output --error-logfile - --access-logfile - spejstore.wsgi:application" volumes: diff --git a/storage/admin.py b/storage/admin.py index 3909790..621c487 100644 --- a/storage/admin.py +++ b/storage/admin.py @@ -4,7 +4,7 @@ from django.contrib import admin from django_select2.forms import Select2MultipleWidget -from .models import Item, ItemImage, Category, Label +from .models import Item, ItemImage, Category, Label, StaffProxyModel from .widgets import PropsSelectWidget @@ -41,8 +41,14 @@ class ItemAdmin(ModelAdminMixin, admin.ModelAdmin): form = ItemForm inlines = [ItemImageInline] save_on_top = True - autocomplete_fields = ["parent"] - search_fields = ["name"] + autocomplete_fields = ["parent", "owner", "taken_by"] + search_fields = ["name", "owner", "taken_by"] + + def formfield_for_foreignkey(self, db_field, request, **kwargs): + formfield = super().formfield_for_foreignkey(db_field, request, **kwargs) + if db_field.name == "owner": + formfield.queryset = formfield.queryset.order_by("username") + return formfield def _name(self, obj): return ("-" * (obj.get_level() or 0)) + "> " + obj.name @@ -89,6 +95,34 @@ from django.contrib.auth.models import Group User.add_to_class("get_short_name", User.get_username) User.add_to_class("get_full_name", User.get_username) + +from django.contrib.auth.admin import UserAdmin + + +class StaffProxyModelAdmin(UserAdmin): + def has_module_permission(self, request): + return request.user.is_superuser + + def has_add_permission(self, request, obj=None): + return request.user.is_superuser + + has_change_permission = has_add_permission + has_delete_permission = has_add_permission + has_module_permission = has_add_permission + + def get_form(self, request, obj=None, **kwargs): + form = super().get_form(request, obj, **kwargs) + is_superuser = request.user.is_superuser + + if not is_superuser: + for f in form.base_fields: + form.base_fields[f].disabled = True + + return form + + +# admin.site.register(StaffProxyModel, StaffProxyModelAdmin) + admin.site.unregister(User) admin.site.unregister(Group) @@ -97,3 +131,5 @@ from social_django.admin import UserSocialAuth, Nonce, Association admin.site.unregister(UserSocialAuth) admin.site.unregister(Nonce) admin.site.unregister(Association) + +admin.site.register(StaffProxyModel, StaffProxyModelAdmin) diff --git a/storage/migrations/0011_auto_20230720_1240.py b/storage/migrations/0011_auto_20230720_1240.py new file mode 100644 index 0000000..9d0351e --- /dev/null +++ b/storage/migrations/0011_auto_20230720_1240.py @@ -0,0 +1,42 @@ +# Generated by Django 3.2.20 on 2023-07-20 12:40 + +from django.db import migrations, models +import django.db.models.deletion +import storage.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('auth', '0012_alter_user_first_name_max_length'), + ('storage', '0010_alter_item_path'), + ] + + operations = [ + migrations.CreateModel( + name='StaffProxyModel', + fields=[ + ], + options={ + 'verbose_name': 'User', + 'verbose_name_plural': 'Users', + 'proxy': True, + 'indexes': [], + 'constraints': [], + }, + bases=('auth.user',), + managers=[ + ('objects', storage.models.StaffManager()), + ], + ), + migrations.AlterField( + model_name='item', + name='owner', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='owned_items', to='storage.staffproxymodel'), + ), + migrations.AlterField( + model_name='item', + name='taken_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='taken_items', to='storage.staffproxymodel'), + ), + ] diff --git a/storage/models.py b/storage/models.py index 91395ad..4bdb449 100644 --- a/storage/models.py +++ b/storage/models.py @@ -9,6 +9,7 @@ from django.contrib.auth.models import User from tree.fields import PathField from tree.models import TreeModelMixin from django.contrib.postgres.fields import HStoreField +from django.contrib.auth.models import UserManager import requests @@ -49,6 +50,21 @@ class Category(models.Model): # Also ID zawierające część name +class StaffManager(UserManager): + def get_queryset(self): + qs = super().get_queryset() + return qs + + +class StaffProxyModel(User): + objects = StaffManager() + + class Meta: + proxy = True + verbose_name = "User" + verbose_name_plural = "Users" + + class Item(models.Model, TreeModelMixin): uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) @@ -61,7 +77,7 @@ class Item(models.Model, TreeModelMixin): state = models.CharField(max_length=31, choices=STATES, default=STATES[0][0]) categories = models.ManyToManyField(Category, blank=True) owner = models.ForeignKey( - User, + StaffProxyModel, null=True, blank=True, related_name="owned_items", @@ -69,7 +85,7 @@ class Item(models.Model, TreeModelMixin): ) taken_by = models.ForeignKey( - User, + StaffProxyModel, null=True, blank=True, related_name="taken_items",