from rest_framework.permissions import BasePermission
from .models import Menu
from django.core.cache import cache


def get_all_menu_queryset(user):
    menus = Menu.objects.none()
    if user.is_superuser:
        menus = Menu.objects.all()
    else:
        menus = Menu.objects.none()
        roles = user.roles.all()
        if roles:
            for i in roles:
                menus = menus | i.menus.all()
    return menus
    

def get_permission_list(user):
    menus = get_all_menu_queryset(user)
    perms_list = menus.values_list('method',flat=True)
    perms_list = list(perms_list)
    perms_l = []
    if perms_list:
        perms_l = perms_list
    else:
        perms_l = ['basic']
    cache.set(f'{user.id}_perms', perms_l, timeout=None)
    return perms_l
    
class RbacPermission(BasePermission):
    """
    基于角色的认证系统的权限校验类
    """

    def has_permission(self, request, view):
        """
        权限校验逻辑
        :param request:
        :param view:
        :return:
        """
        perms = []
        perms = cache.get(f'{request.user.id}_perms', None)
        if perms is None:
            perms = get_permission_list(request.user)
        if perms:
            if request.user.is_superuser:
                return True
            elif not hasattr(view, 'perms_map'):
                return True
            else:
                perms_map = view.perms_map
                _method = request._request.method.lower()
                for i in perms_map:
                    for method, alias in i.items():
                        if (_method == method or method == '*') and alias in perms:
                            return True




class RbacObjPermission(BasePermission):
    """
    对象级权限控制
    """

    def has_object_permission(self, request, view, obj):
        # if 'perms' in request.session:
        #     perms = request.session['perms']
        # else:
        #     perms = get_permission_list(request.user)
        # if 'admin' in perms:
        #     return True
        # else:
        #     return obj.owner == request.user
        return True