2016-04-11 17 views
3

入れ子構造のAPIを実装しています。それは動物園だと私はGET /api/cage/ケージIDの1を得るGET /api/cage/1/ケージのリストを取得することができますが、私はGET /api/cage/1/animals/ケージの動物のリストを取得することができます。私が持っている問題はパーミッションです。私はケージ自体を見ることができればケージ内の動物を見ることができます。 has_object_permission()が関連するパーミッションクラスでTrueを返すと、私はケージ自体を見ることができます。何らかの理由で、私がGET/api/cage/1 /を実行したときにhas_object_permission()が呼び出されますが、GET /api/cage/1/animals/を呼び出したときにhas_permission()が呼び出されます。また、has_permission()を使用して、アクセス権をチェックするオブジェクトにアクセスすることはできません。何か不足していますか?これはどうすればいいですか?多かれ少なかれ、このDRFビューセットの権限チェックが正しく機能していません

 
class CageViewSet(ModelViewSet): 
    queryset = Cage.objects.all() 
    serializer_class = CageSerializer 
    permission_classes = [GeneralZooPermissions, ] 
    authentication_classes = [ZooTicketCheck, ] 

    def get_queryset(self): 
     ... code to only list cages you have permission to see ... 

    @detail_route(methods=['GET']) 
    def animals(self, request, pk=None): 
     return Request(AnimalSerializer(Animal.objects.filter(cage_id=pk), many=True).data) 

のように見えるビューセット

マイケージ私GeneralZooPermissionsクラスは、この(現時点では)

 
class GeneralZooPermissions(BasePermission): 
    def has_permission(self, request, view): 
     return True 

    def has_object_permission(self, request, view, obj): 
     return request.user.has_perm('view_cage', obj) 

更新#1のようになります。これはバグであるように思えますDRF。詳細ルートは、正しい権限チェックを呼び出さない。私はこの問題をDRF開発者に報告しようとしましたが、私の報告書は消えたようです。次に何をすべきかわからない。アイデア?

更新#2:DRFで投稿した問題が戻ってきて、私は応答を得ました。 has_permission()だけをチェックし、has_object_permission()はチェックしないように見えます。私を助けないので、私はまだ解決策を探しています。この時点では、このようなものは、DRFコードの束を読み、DRFチームで問題を投稿した後に、あなたのビューがGET_OBJECTを呼び出す場合has_object_permissionは()のみ呼び出されると思われるので、

 
class CustomPermission(BasePermission): 
    def has_permission(self, request, view): 
     """we need to do all permission checking here, since has_object_permission() is not guaranteed to be called""" 
     if 'pk' in view.kwargs and view.kwargs['pk']: 
      obj = view.get_queryset()[0] 
      # check object permissions here 
     else: 
      # check model permissions here 

    def has_object_permission(self, request, view, obj): 
     """ nothing to do here, we already checked everything """ 
     return True 

答えて

8

OKを行わなければなりません()を使用して操作対象のオブジェクトを取得します。とにかくアクセス権をチェックするオブジェクトを取得する必要があるため、透過的に行うと追加のデータベースクエリが追加されるため、意味があります。私のレポートに答えた人は、これを反映するためにドキュメントを更新する必要があると言いました。したがって、カスタムディテールルートを作成し、必要な権限を適切にチェックしたい場合は、

 
class MyViewSet(ModelViewSet): 
    queryset = MyModel.objects.all() 
    .... 
    permission_classes = (MyCustomPermissions,)

@detail_route(methods=['GET', ]) def custom(self, request, pk=None): my_obj = self.get_object() # do this and your permissions shall be checked return Response('whatever')
関連する問題