Search code examples
djangodjango-viewsdjango-class-based-viewsdjango-permissions

Django DetailView getting access to users in M2M field to restrict access?


I am currently working with a DetailView, returning a JsonResponse of some business details. I am using the test_func and UserPassesTestMixin to make sure that only users who have is_admin=True are getting access to these admin only views.

Now in my BusinessDetail model, I have a field called owner which is a M2M field linked to users who are owners of the business. I also need to restrict views of course to make sure that self.request.user is in the BusinessDetail model's owner field.

I have tried a few things including this...

class BusinessDetailView(LoginRequiredMixin, UserPassesTestMixin, DetailView):
    model = BusinessDetail

    def test_func(self):
        return self.request.user.is_admin

    def get_object(self, queryset=None):
        business = get_object_or_404(BusinessDetail, pk=self.kwargs.get('pk'))
        serialized_obj = serializers.serialize('json', [business])
        return  serialized_obj

    def get(self, request, *args, **kwargs):
        try:
            business = self.get_object()
            logger.debug(business obj: {business}')
            if self.request.user not in business.owner.all():
                logger.debug('Error: Access not granted.')
                return JsonResponse({'Error': 'Access restricted.'})
            return JsonResponse(json.loads(business), status=200, safe=False)
        except Exception as e:
            logger.error(f'Error getting business detail with error: {e}')
            return JsonResponse({'Error': 'DB error, return to previous page'}, status=500)

My logger is looking like...

==> /var/log/app/logger/debug.log <==
DEBUG 2020-12-08 21:35:19,935 /app_site/business_admin/views.py get 379 Business obj: [{"model": "authentication.business_detail", "pk": 3, "fields": {"name": "test name", "phone_no": "(111)-111-1111",  "street": "111 5th st, "city": "Fort Lauderdale", "state": "Florida", "zip": "33087", "primary_email": "[email protected]", "owner": [4], }}]
ERROR 2020-12-08 21:35:19,935 /app_site/business_admin/views.py get 379 Error getting business detail with error: 'str' object has no attribute 'owner'

Is there a different/better way to restrict these views to users who are linked to the owner field because I am still having trouble accessing that owner field that you can see outputted in the logger? I am really having trouble accessing that owner field.

Thanks in advance for the help!


Solution

  • You can restrict this with:

    def get_object(self, queryset=None):
        business = get_object_or_404(
            BusinessDetail,
            pk=self.kwargs['pk'],
            owner=self.request.user
        )
        # …

    If the logged in user is not a member of the owners, then this will return a HTTP 404 response.

    Your test_func will however restrict the view to only admin users, and thus only admin users who are the owners will see this.