How to save records and get records on behalf of another user

103 Views Asked by At

I'm working on a Django 1.5 Project.

The application contains the user hierarchy of

Owner
Admin
Viewer
  • Owner owns all the data in the database.
  • Admin users are created by the owner and have different login credentials. Can add/edit/delete data under Owner.
  • Viewer users are created by the owner and have different login credentials. Can view data created under the Owner.

Users model have a field is_shared (boolean) to identify main user and shared user and access_level is mapped in another model MultiUser.

I have thought of to implement it in the way

  1. Update all viewsets and put check in get_queryset.
  2. where first check will be made if user has is_shared=True
  3. then check in MultiUser model,
  4. get the user from MultiUser and then filter records on behalf of the user.

But this will require changes throughout the application viewsets.

Is there a way to do this without making changes to the whole application. May be middleware.

Edit 2: MultiUser model

class MultiUser(models.Model):
    user = models.ForeignKey(User, related_name='owner_user')
    shared_user = models.ForeignKey(User, related_name='shared_user')
    access_level = models.CharField(max_length=50)
2

There are 2 best solutions below

0
Anuj TBE On BEST ANSWER

I solved this by creating a middleware with content

class MultiUserMiddleware(object):
    def process_request(self, request):
        """
        Check if user profile is is_shared=True
        If user is a shared user, get owner user from multi user
        and assign owner user to request.user

        Any multi user profile created by the owner user will work on behalf of the owner user
        """

        user = request.user
        if not user.is_anonymous():
            # if request.path in settings.MUTLIUSER_ALLOWED_PATH:
            #     return None

            # Search using wildcard
            if any(fnmatch(request.path, p) for p in settings.MUTLIUSER_ALLOWED_PATH):
                return None

            try:
                if user.profile.get().is_shared:
                    owner = MultiUser.objects.filter(shared_user=user)[0].user
                    request.user = owner
            except:
                return None

        return None

This middleware check for if the user's account is a shared user based on is_shared and then change the request.user with the owner user object. This also prevents changing the request owner for specific paths defined in the settings file (Ex., profile, change_password, etc).

2
Sreekanth Reddy Balne On

Instead of updating all viewsets, you could use a single base class to deal with.

from django.http import HttpResponse
from django.views import View

class BaseView(View):
    def get_queryset(self, request):
        if request.user.is_shared:
            #some is_shared value
            u = MultiUser.objects.filter(user=request.user)
            if u.exists():
                return #some multiuser value
            else:
                return #some non multi user value

    class Meta:
        abstract=True

class MyView(BaseView):
    def get(self, request):
        q = self.get_queryset
        #view logic
        return HttpResponse('result')

class MyView2(BaseView):
    def get(self, request):
        q = self.get_queryset
        #view logic
        return HttpResponse('result')