modelviewset은 각 action별로 처리한다.
create ( POST ) - 생성
list ( GET ) - 조회
retrieve ( GET ) - 개별 조회
update - ( PUT ) - 수정
partial_update ( PATCH ) - 부분 수정
destroy ( DELETE ) - 삭제
즉, 권한이 필요한 특정 액션에게 별도의 권한 설정을 해야한다.
...
...
# from ... import constants as app_name_const
"""
하드 코딩하는 것이 아니라 원래는
constants.py 또는 .env를 통해 하는 것이 좋다.
"""
# GET_ACTIONS = [os.enviorn.get("LIST"), os.enviorn.get("RETRIEVE")]
# GET_ACTIONS = [app_name_const.LIST, app_name_const.RETRIEVE]
GET_ACTIONS = ["list", "retrieve"]
NEED_AUTH_ACTIONS = ["update", "partial_update", "destroy"]
def get_permissions(self):
if self.action in NEED_AUTH_ACTIONS:
self.permission_classes = [OwnerOnly, ]
else:
self.permission_classes = [AllowAny, ]
return super().get_permissions()
from rest_framework.permissions import BasePermission
class AllowAny(BasePermission):
def has_permission(self, request, view):
return True
class OwnerOnly(BasePermission):
def has_object_permission(self, request, view, obj, user):
logged_in_user = user
owner = obj.owner
return True if logged_in_user == owner else False
has_permission 메서드는 로그인된 사용자만을 가지고 권한여부를 체크한다.
has_object_permission은 로그인한 사용자가 다른 객체에 접근할 권한이 있는지 체크하는 용도이다.
has_object_permission 메서드는 자동으로 호출되지 않기 때문에
별도로 호출해야하는데, 그 역할을 check_object_permissions()가 한다.
def check_object_permissions(self, request, obj, logged_in_user):
for permission in self.get_permissions():
if not permission.has_object_permission(request, self, obj, logged_in_user):
self.permission_denied(
request,
message=getattr(permission, 'message', None),
code=getattr(permission, 'code', None)
)
def retrieve(self):
...
...
"""
여기서 호출하여 권한 체크
"""
self.check_object_permissions(request, obj, logged_in_user)
...
return Response(.....)