English is not my native language, i hope to be able to explain my problem adequately anyways! If not, please ask and let me try again!
I have very unequal user know-how levels and created multiple admin sites for the different levels. My custom user model has an “is_expert” boolean for the users between “is_staff” and “is_superuser”.
Some of the users use my easyadminsite via URL /easyadmin/, others use the expertadminsite via /expertadmin/
This works but some of the non-experts THINK they are experts and use the /expertadmin/ and mess things up.
How do i restrict users without the “is_expert” flag to use the whole expertadminsite but still allow access to the easyadminsite? They all work on the same models / instances so the standard permissions don’t help. Of course i could override the four has_xxx_permissions in all modeladmin classes but it would be better to restrict access to the whole site all together.
Create a custom middleware that will redirect the user to a specific URL. You can use this documentation to guide you.
Here’s a snippet that i used when i implemented this exact feature.
from typing import Union
from django.http import HttpRequest
from django.shortcuts import redirect
from rest_framework.request import Request as RestHttpRequest
from users.models import User
from utils.consts.users import UserType
class AdminRedirectMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request: Union[HttpRequest, RestHttpRequest]):
path = request.get_full_path()
if self.is_authenticated_admin_get_request(request):
admin_url_for_user_type = self.get_url_for_user_type(request.user)
if admin_url_for_user_type == path:
return self.get_response(request)
if admin_url_for_user_type not in path:
return redirect(admin_url_for_user_type)
return self.get_response(request)
@staticmethod
def is_authenticated_admin_get_request(request):
path = request.get_full_path()
return (
request.method == "GET"
and "admin/" in path
and "static/" not in path
and "jsi18n/" not in path
and request.user.is_authenticated
)
def get_url_for_user_type(self, user: User):
urls = {
UserType.CUSTOMER: "/",
UserType.ADMIN: "/la-admin/",
UserType.COMPANY: "/cmp-admin/",
UserType.FRANCHISEE: "/frn-admin/",
}
return urls[user.user_type]
You can handle it on the site level.
See AdminSite.has_permission
You can create your ExpertAdminSite with a custom has_permission
function that checks the is_expert
flag.
1 Like
Didn’t know about that!
That solution is way cleaner.
I feel so stupid right now! It is that simple and i did not find it in weeks? Ouch!
Thank you for the Hint!