/

Django Rest Framework -4

Permissions (İzinler)

Bu eğitim modülümüzde ise permissions yani izinleri anlatacağım. Öncelikle izinlerin ne olduğunu ve ne amaçla kullanıldıklarından bahsedelim.

Güncel projemiz üzerinden anlatacak olursak kullanıcılarımız kendi makalelerini sitemiz üzerinden paylaşabiliyor. Ancak burada bir sorun var. Eğer kullanıcı sisteme giriş yapmadan makale oluşturma URL adresine giderse ve bir makale oluşturmaya çalışırsa bu makale kimin adına veritabanına kayıt olacaktır ?

Cevap basit sunucumuz hata verecektir. Bunun önüne geçmek için izinleri kullanırız. Bir başka örnek olarak 2 kullanıcı düşünelim. Bir kullanıcı kendisine ait olmayan bir makale üzerinde güncelleme yetkisine/iznine sahip olmamalıdır. Sadece kendi makalelerini güncelleyebilme ya da silme izinlerine sahip olmalıdır. Django Rest Framework ile bize hazır halde bazı permission class’ları yani sınıfları gelmektedir. Ayrıyetten istersek kendi izinlerimizi de yazabiliriz ve tabiiki de yazacağız. Ancak önce hazır halde gelen izinlerimize bakalım.

İlk önce izinleri nasıl ve nerelerde kullanabileceğimizi öğrenelim. Geçen derslerde makalelerimizi listelemek için api klasörünün içerisinde views.py dosyamızda APIView’imizi oluşturduk. Hatırlamak için tekrar buraya koyuyorum.

class PostListAPIView(ListAPIView):
    serializer_class = PostSerializer
    pagination_class = PostPagination

    def get_queryset(self):
        queryset = PostModel.objects.filter(Draft=False)
        return queryset

 

Evet view’imiz üzerinde bir liste oluşturacağım ve bu listeye vereceğim Permissions Sınıfları (class) bu view’in işlevini gerçekleştirilmesinde görev alacak. Ancak onun öncesinde bir import işlemi yapmamız gerek.

from rest_framework.permissions import IsAuthenticated

 

views.py dosyamızın en üstüne rest framework ile birlikte gelen IsAuthenticated sınıfımızı import ediyoruz. IsAuthenticated sınıfı ne işe yarar bunu kısaca özetleyelim. Bu izini herhangi bir view’e verdiğiniz zaman o view’in bir kullanıcı tarafından işlevini yerine getirilmesi için GİRİŞ YAPMIŞ olması gerekir. Yani kullanıcının giriş yapıp yapmadığını kontrol eder. Eğer kullanıcı giriş yapmadıysa bilgileri istek yapan kullanıcıya vermez. (Şuan GET methodu üzerinden anlatıyorum. Tabii ki de POST methodu gibi izinleri de bu sınıf ile engelleyebiliriz.

İlk önce bu iznimizi view’imiz üzerinden kontrol edelim. Ancak ilk başta kullanıcı çıkışı yapmamız gerekmektedir. Admin panelimizden çıkış işlemimizi gerçekleştirdikten sonra makalelerimizin API yolu ile bizlere veritabanından çekilip verilen API’ye GET isteği atalım.

Bizim isteğimiz çıkış yapmış olan kullanıcının herhangi bir şekilde bu makaleleri görememesi. Ama bakalım izin olmadan ve giriş yapmamış bir kullanıcı makalelerimizi görebiliyor mu…

Gördüğünüz gibi bilgiler geliyor. Şimdi bu iznimizi view’imize ekleyelim.

class PostListAPIView(ListAPIView):
    serializer_class = PostSerializer
    pagination_class = PostPagination

    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        queryset = PostModel.objects.filter(Draft=False)
        return queryset

 

permission_class listesine oluşturmuş olduğumuz ya da rest framework ile bize hazır halde gelen izinlerimizi verebiliyoruz. Şimdi bunu yaptıktan sonra tekrardan çıkış yapmış bir şekilde GET isteği deneyelim.

Gördüğünüz gibi giriş bilgileri verilmedi olarak uyarımızı aldık. Bu ve bunun gibi sınıflar ile izinlerimizi kontrol altında tutabiliyoruz. Ancak bize bunlar yeterli olmayacaktır. Kendi izinlerimizi de yazmamız gerekecek. Örnek olarak bir makaleyi sadece o makaleyi oluşturan kullanıcı silebilmeli. Başka bir kullanıcı silememeli. Hadi gelin bunu gerçekleştirelim.

İlk başta makale silme view’ımıza gelelim ve oluşturacağımız permission sınıfının ismini verelim.

class PostDeleteAPIView(DestroyAPIView):
    queryset           = PostModel.objects.all()
    serializer_class   = PostSerializer
    permission_classes = [IsOwner,IsAuthenticated]
    lookup_field       = 'Slug'

 

Evet burada hem rest framework ile birlikte hazır halde gelen IsAuthenticated iznini kullandım. Hem de birazdan oluşturacak olduğumuz IsOwner sınıfını kullandım. Burada 2 farklı permissions sınıfı kullanırsak her iki izinden de geçmiş olması gerekmektedir.

Şimdi bu sınıfı api klasörümüz adı altında permissions.py adında dosya açıp içerisine yazacağız.Yani şu şekilde:

Oluşturmuş olduğumuz dosyaya gelelim.

Oluşturacağımız sınıf rest framework’ten BasePermission sınıfından miras almalıdır. Hemen gerekli import işlemini gerçekleştirelim.

from rest_framework.permissions import BasePermission

 

Şimdi ise sınıfımızı oluşturalım yavaş yavaş.

class IsOwner(BasePermission):
    message = "Bu objenin sahibi Siz Değilsiniz"

 

İlk başta message değişkeni ile izinsiz bir yetki denenirse hangi mesajı göstereceğimizi belirttik.Şimdi ise bir method yazacağız sınıfımız içerisine.

class IsOwner(BasePermission):
    message = "Bu objenin sahibi Siz Değilsiniz"
    def has_object_permission(self, request, view, obj):
        return (obj.Author == request.user
) or request.user.is_superuser

 

Şimdi burada yaptıklarımızı anlatalım. Bu method ile izin işleminin kontrolünü yazıyoruz ve bu methodtan True değeri döndürürsek izinden geçtiği anlamına gelir. Eğer False döndürürsek izinden geçemediği anlamına gelir.

obj.Author==request.user diyerek o anki nesnemizin giriş yapmış kullanıcıya eşit olup olmadığını sorguladım. Eğer eşitse buradan True dönecektir. Ancak or ile request.user.is_superuser ile de bu isteği ADMİN kullanıcısı mı yani bir superuser mı yaptı diye kontrol ettim. Sonuçta sitenin admini kimin makalesi olursa olsun müdahale edebilme yetkisine sahip olmalıdır.

Bu yazdığımızı sınıfı özetleyecek olursak , makalemizin yazarı o an giriş yapmış kullanıcı ise YADA bu silme isteğini bir superuser yani Admin yaptıysa GERÇEKLEŞTİR yani fonksiyondan True sonucu döndür diye kodladık.

Test etmeden önce veritabanımıza iki adet makale ekleyeceğim. Biri admin kullanıcısının makalesi biri de yetkisiz bir kullanıcının makalesi olacak.

Şimdi YETKİSİZ bir kullanıcı ile başka bir kullanıcının (admin) makalesini silmeye çalışalım.

URL adresine gittiğimizde bu sayfada sadece DELETE methoduna izin verildiği,GET methoduna izin verilmediği yazıyor. Yazdığımız izni bir katman daha güvenlikli kılmak için farklı bir method daha yazabiliriz sınıfımıza.Ona birazdan geleceğiz. Şimdi ise sağ üstten DELETE butonuna basarak silme işlemini gerçekleştirmeye çalışalım.

Gördüğünüz gibi “Bu objenin sahibi siz değilsiniz” olarak yetkisiz olduğumuzu gördük. Ancak fark edeceğiniz üzere biz bu sayfaya çıkış yapmış olsak da istek atabiliyoruz yine de. Bunun da önüne geçebilmek için ,araya bir katman daha koymak için şu methodu sınıfımıza yazacağız.

class IsOwner(BasePermission):
    message = "Bu objenin sahibi Siz Değilsiniz"
    def has_object_permission(self, request, view, obj):
        return (obj.Author == request.user) or request.user.is_superuser

    def has_permission(self, request, view):  
        return request.user and request.user.is_authenticated

 

has_object_permission methodu ile has_permission methodunun farkını açıklayalım. has_object_permission methodu sadece o view üzerinde çalışan istekler geldiğinde kontrol işlemi yapar. Yani bizim view’imiz sadece DELETE methoduna izin verdiğinden dolayı sadece DELETE methodu ile bir istek geldiği zaman bu method tetiklenir.has_permission methodu ise bu view’imize hangi istek gelirse gelsin tetiklenir ve ona göre True ya da False cevabı döndürür.

Comments

    There are no comments yet.

Comment