Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error: displaying objects even the user hasn't the correct permissions. #189

Open
omargawdat opened this issue May 23, 2024 · 0 comments
Open

Comments

@omargawdat
Copy link

As you can see in the video the object permission in the admin doesn't work correctly
https://github.com/dfunckt/django-rules/assets/53629777/df5bf17e-c32c-41b3-9250-b5278cc16a60

Used package: Django rules and Django unfold
code:
from rules.contrib.admin import ObjectPermissionsModelAdminMixin
from unfold.admin import ModelAdmin

@admin.register(Worker)
class WorkerAdmin(RequestFormMixin, ObjectPermissionsModelAdminMixin, ModelAdmin):
form = WorkerForm
autocomplete_fields = [
"company",
]
filter_horizontal = ["packages"]
list_display = (
"str",
"phone_number",
"company",
"date_joined",
)
search_fields = [
"phone_number",
"company__username",
"first_name",
"last_name",
]
list_filter = (
("date_joined", RangeDateFilter),
"company",
)
list_filter_submit = True

fieldsets = (
    (
        "Personal Information",
        {
            "fields": (
                "company",
                ("first_name", "last_name"),
                "phone_number",
                "image",
                "packages",
                "date_joined",
                "is_active",
            ),
        },
    ),
)
readonly_fields = ("date_joined",)

I managed to solve the problem using the below code:
class ObjectPermissionsMixin:

def get_queryset(self, request):
    """Filter the queryset based on object-level view permissions."""
    queryset = super().get_queryset(request)
    if isinstance(request.user, StaffUser):
        return queryset
    return queryset.filter(pk__in=[item.pk for item in queryset if self.has_view_permission(request, item)])

def formfield_for_manytomany(self, db_field, request, **kwargs):
    """Filter Many-to-Many fields based on user's view permissions for the related model."""
    if db_field.many_to_many:
        model = db_field.related_model
        qs = model.objects.all()
        filtered_qs = [
            obj
            for obj in qs
            if request.user.has_perm(f"{model._meta.app_label}.view_{model._meta.model_name}", obj)
        ]
        kwargs["queryset"] = model.objects.filter(pk__in=[obj.pk for obj in filtered_qs])
    return super().formfield_for_manytomany(db_field, request, **kwargs)

def has_permission(self, request, obj, perm_type):
    """Check if permission of type `perm_type` exists and is granted to the user."""
    if isinstance(request.user, CompanyAgent):
        codename = get_permission_codename(perm_type, self.opts)
        permission = f"{self.opts.app_label}.{codename}"
        return request.user.has_perm(permission, obj)

    return request.user.has_perm(f"{self.opts.app_label}.{perm_type}_{self.opts.model_name}")

def has_view_permission(self, request, obj=None):
    """Verify user's view permission for an object."""
    return self.has_permission(request, obj, "view")

def has_change_permission(self, request, obj=None):
    """Verify user's change permission for an object."""
    return self.has_permission(request, obj, "change")

def has_delete_permission(self, request, obj=None):
    """Verify user's delete permission for an object."""
    return self.has_permission(request, obj, "delete")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant