Keith Hickman
11/21/2025, 6:24 PMAsk Inkeep
11/21/2025, 6:24 PMAsk Inkeep
11/21/2025, 6:24 PMdef check_course_attributes(action) :
def decorator(view_func) :
@wraps(view_func)
def _wrapped_view(view_instance, request, *args, **kwargs) :
course_id = kwargs.get('pk')
course = Course.objects.get(id=course_id)
enrollment = StudentEnrollment.objects.filter(
student=request.user,
course=course
) .first()
context = {
"user": {
"key": str(request.user.id) ,
"attributes": {
"level": course.level,
"progress": enrollment.progress if enrollment else 0,
"prerequisites_required": course.prerequisites.exists() ,
"location": request.headers.get('X-User-Location')
}
},
"action": action,
"resource": {
"type": "Course",
"instance": f"Course:{course.id}",
"attributes": {
"level": course.level,
"region_restrictions": course.region_restrictions
}
}
}
permitted = async_to_sync(permit.check) (**context)
if not permitted:
return HttpResponseForbidden("Access denied")
return view_func(view_instance, request, *args, **kwargs)
return _wrapped_view
return decorator
(1)
Direct permit.check() Calls
The Permit SDK simplifies policy decisions to a single function call (2) :
permit.check('user', 'read', 'resource')
However, as noted in the Python best practices guide, middleware frameworks can have limitations including limited function scope where you may need to check additional context mid-function, like billing status :
@roles_required('admin')
def enable_workflow(user_id) :
user = User.get(user_id)
paid_tier = billing_service.get_user_tier(user_id) == 'paid'
if not paid_tier:
raise Exception('User is not on the paid tier')
Best Practice Recommendation
The documentation recommends keeping your enforcement layer model-agnostic and using a declarative approach . Your authorization service should be generic and capable of adapting to various frameworks . The enforcement logic should remain the same regardless of whether you're using RBAC, ABAC, or other models .
The key is maintaining centralized authorization logic while keeping it separate from your business code, whether you achieve that through decorators or direct calls depends on your specific use case and framework.Ask Inkeep
11/21/2025, 6:25 PMOr Weis
11/21/2025, 6:28 PMAsk Inkeep
11/22/2025, 9:04 AMKeith Hickman
11/22/2025, 9:05 AM