Simplified "has permission" logic and fixed a major flow in "{resoruce}/grid" not applying correct data to _actions

Function has_resource_permission() need to live in depends.py as it cause circular dependencies if in common.py
This commit is contained in:
swevm
2021-01-21 10:48:02 +01:00
parent 861aea95ab
commit 1d79c1ff73
3 changed files with 21 additions and 28 deletions

View File

@@ -1,6 +1,7 @@
import importlib
from copy import deepcopy
from fastapi import HTTPException
from passlib.context import CryptContext
from tortoise import Tortoise

View File

@@ -10,6 +10,7 @@ from starlette.status import HTTP_401_UNAUTHORIZED, HTTP_403_FORBIDDEN, HTTP_404
from . import enums
from .factory import app
from .models import AbstractUser
auth_schema = HTTPBearer()
@@ -137,21 +138,12 @@ class HasPermission:
def __init__(self, action: enums.PermissionAction):
self.action = action
async def __call__(self, resource: str = Path(...), user=Depends(get_current_user)):
if not app.permission or user.is_superuser:
return True # Hmm. Should superuser really cirumvent all permission checks. not a good practice!?!?!?!!?!!!
if not user.is_active:
return False
has_permission = False
await user.fetch_related("roles")
for role in user.roles:
if await role.permissions.filter(model=resource, action=self.action):
return True
if not has_permission:
return False
has_read_permission = HasPermission(action=enums.PermissionAction.read)
has_create_permission = HasPermission(action=enums.PermissionAction.create)
has_update_permission = HasPermission(action=enums.PermissionAction.update)
has_delete_permission = HasPermission(action=enums.PermissionAction.delete)
async def has_resource_permission(
action: enums.PermissionAction, resource: str, user: AbstractUser
) -> bool:
try:
await PermissionsChecker(action=action)(resource, user)
return True
except HTTPException:
return False

View File

@@ -12,6 +12,7 @@ from tortoise.contrib.pydantic import pydantic_model_creator
from tortoise.exceptions import IntegrityError
from tortoise.fields import ManyToManyRelation
from .. import enums
from ..common import handle_m2m_fields_create_or_update
from ..depends import (
QueryItem,
@@ -23,10 +24,7 @@ from ..depends import (
get_current_user,
get_model,
get_query,
has_create_permission,
has_delete_permission,
has_read_permission,
has_update_permission,
has_resource_permission,
parse_body,
read_checker,
update_checker,
@@ -129,14 +127,16 @@ async def form(resource: str,):
@router.get("/{resource}/grid", dependencies=[Depends(read_checker)])
async def grid(resource: str, user=Depends(get_current_user)):
resource = await app.get_resource(resource)
resource = resource.dict(by_alias=True, exclude_unset=True)
resource["fields"]["_actions"] = {
"delete": await has_delete_permission(resource, user),
"edit": await has_update_permission(resource, user),
"toolbar": {"create": await has_create_permission(resource, user)},
fetched_resource = await app.get_resource(resource)
resource_response = fetched_resource.dict(by_alias=True, exclude_unset=True)
resource_response["fields"]["_actions"] = {
"delete": await has_resource_permission(enums.PermissionAction.delete, resource, user),
"edit": await has_resource_permission(enums.PermissionAction.update, resource, user),
"toolbar": {
"create": await has_resource_permission(enums.PermissionAction.create, resource, user)
},
}
return resource
return resource_response
@router.get("/{resource}/view", dependencies=[Depends(read_checker)])