Django

⌘K
  1. Home
  2. Django
  3. library
  4. Django Guardian অবজেক্ট লেভেল পারমিশন

Django Guardian অবজেক্ট লেভেল পারমিশন

simple example

এখানে দেখানো হচ্ছে যে যখন একজন ব্যবহারকারী কোন নতুন ডেটা ইন্সার্ট করে তখন ওই ডেটার id অনুযায়ী change,delete ও view বা দেখার পারমিশন সেট করা হচ্ছে শুধু এই একটি রেকর্ড বা অবজেক্ট এর জন্য এবং যখন এই মডেল এই রেকর্ড আপডেট করা হবে তখন চেক করা হবে user এর এই ডকুমেন্ট বা রেকর্ড বা অবজেক্ট টি আপডেট করার অবজেক্ট লেভেল পারমিশন আছে কিনা যদি না থাকে তাহলে আপডেট হবে না ডিলিট এর ক্ষেত্রেও একই নিয়ম প্রযোজ্য।

কাজের প্রফেশনাল বর্ণনা:

  1. নতুন ডকুমেন্ট ইনসার্টের পর Object-Level Permission অ্যাসাইনমেন্ট:
    • যখন একজন ব্যবহারকারী নতুন ডকুমেন্ট তৈরি করে, তখন তার উপর স্বয়ংক্রিয়ভাবে change, delete, এবং view পারমিশন দেওয়া হয়।
    • পারমিশন অ্যাসাইনমেন্টটি ব্যবহারকারী এবং নির্দিষ্ট ডকুমেন্টের মধ্যে সীমাবদ্ধ। এর ফলে ইউজার শুধুমাত্র সেই নির্দিষ্ট ডকুমেন্টটির উপর কার্যক্রম পরিচালনা করতে পারে, অন্য কোনো ডকুমেন্ট নয়। এটি নিশ্চিত করে যে সিস্টেমে অবাঞ্ছিত পরিবর্তন বা অ্যাক্সেস হচ্ছে না।
  2. আপডেট করার সময় Object-Level Permission চেক:
    • যখন একজন ব্যবহারকারী কোনও ডকুমেন্ট আপডেট করতে চায়, তখন সিস্টেম প্রথমে যাচাই করে যে তার কাছে সেই ডকুমেন্টটির change_document পারমিশন আছে কিনা।
    • যদি পারমিশন না থাকে, তাহলে 403 Permission Denied রেসপন্স দেওয়া হয়, যা অবাঞ্ছিত বা অনুমোদনবিহীন পরিবর্তন প্রতিরোধ করে।
    • পারমিশন থাকলে, ডকুমেন্টটি আপডেট করার অনুমতি দেওয়া হয়।
  3. ডিলিট করার সময় Object-Level Permission চেক:
    • ডকুমেন্ট মুছে ফেলার ক্ষেত্রে একই নীতি প্রযোজ্য। সিস্টেম প্রথমে যাচাই করে যে ব্যবহারকারীর কাছে delete_document পারমিশন আছে কিনা।
    • যদি না থাকে, তাহলে সিস্টেম একটি 403 Permission Denied রেসপন্স ফিরিয়ে দেয় এবং ডকুমেন্টটি মুছে ফেলা যাবে না।
    • এই সিস্টেম নিশ্চিত করে যে ডকুমেন্ট শুধুমাত্র অনুমোদিত ব্যবহারকারীই মুছতে পারবে।
  4. ডকুমেন্ট তালিকা দেখতে Object-Level Permission চেক:
    • ডকুমেন্ট লিস্টের জন্য সিস্টেম ব্যবহারকারীর প্রোফাইলের সাথে সম্পর্কিত কোম্পানির অধীনে থাকা ডকুমেন্টগুলো দেখায়। এভাবে ইউজার শুধুমাত্র তার অনুমোদিত ডকুমেন্টগুলো দেখতে সক্ষম হয়, যা ডেটা প্রাইভেসি ও সিকিউরিটি নিশ্চিত করে।

সারাংশ:

এই সিস্টেমটি সুনির্দিষ্ট Object-Level Permission ব্যবহার করে granular control প্রদান করে, যা প্রতিটি ডকুমেন্টের সাথে সংশ্লিষ্ট পারমিশন ভিত্তিক অ্যাক্সেস কন্ট্রোল নিশ্চিত করে। এটি একাধিক ব্যবহারকারী থাকা একটি সিস্টেমের জন্য ডেটার নিরাপত্তা এবং সঠিক ব্যবস্থাপনা নিশ্চিত করে, যেখানে একাধিক ব্যক্তি নির্দিষ্ট ডকুমেন্টে বিভিন্ন পর্যায়ে কাজ করে। সিস্টেমটি Object-Level Permission ম্যানেজমেন্টের মাধ্যমে unauthorized ডেটা অ্যাক্সেস ও পরিবর্তন প্রতিরোধ করে।

১. প্রজেক্ট স্ট্রাকচার

আমরা একটি Django প্রজেক্ট শুরু করব যেখানে আমরা Django REST Framework এবং Django Guardian ব্যবহার করব।

ধাপ ১: Django প্রজেক্ট তৈরি করা

django-admin startproject permission_system
cd permission_system
python manage.py startapp documents

ধাপ ২: প্রয়োজনীয় প্যাকেজ ইনস্টল করা

pip install djangorestframework django-guardian

ধাপ ৩: settings.py ফাইলে কনফিগারেশন যোগ করা

# Installed apps
INSTALLED_APPS = [
    # Django default apps...
    'rest_framework',
    'guardian',
    'documents',  # Our app
]

# Authentication backends for Django Guardian
AUTHENTICATION_BACKENDS = (
    'django.contrib.auth.backends.ModelBackend',  # Default backend
    'guardian.backends.ObjectPermissionBackend',  # Guardian backend for object-level permissions
)

# Guardian settings
ANONYMOUS_USER_ID = -1

ধাপ ৪: মডেল তৈরি করা

আমরা একটি Document মডেল তৈরি করব, যেখানে কোম্পানি এবং ইউজার সম্পর্ক থাকবে।

# documents/models.py
from django.db import models
from django.contrib.auth.models import User

class Company(models.Model):
    name = models.CharField(max_length=255)

    def __str__(self):
        return self.name

class Document(models.Model):
    name = models.CharField(max_length=255)
    content = models.TextField()
    company = models.ForeignKey(Company, on_delete=models.CASCADE)
    created_by = models.ForeignKey(User, on_delete=models.CASCADE)

    def __str__(self):
        return self.name

ধাপ ৫: মডেল রেজিস্ট্রেশন

# documents/admin.py
from django.contrib import admin
from .models import Document, Company

admin.site.register(Document)
admin.site.register(Company)

ধাপ ৬: মাইগ্রেশন চালানো

python manage.py makemigrations
python manage.py migrate

২. REST API তৈরি করা

ধাপ ৭: Serializer তৈরি করা

# documents/serializers.py
from rest_framework import serializers
from .models import Document

class DocumentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Document
        fields = '__all__'

ধাপ ৮: API ভিউ তৈরি করা

এখানে আমরা একজন ইউজারের উপর নির্দিষ্ট ডকুমেন্টের পারমিশন চেক করব এবং ইউজারের জন্য CRUD পারমিশন এসাইন করব।

# documents/views.py
from rest_framework import viewsets, status
from rest_framework.response import Response
from guardian.shortcuts import assign_perm, get_perms
from rest_framework.permissions import IsAuthenticated
from .models import Document
from .serializers import DocumentSerializer

class DocumentViewSet(viewsets.ModelViewSet):
    queryset = Document.objects.all()
    serializer_class = DocumentSerializer
    permission_classes = [IsAuthenticated]

    def perform_create(self, serializer):
        # নতুন ডকুমেন্ট তৈরি হলে ইউজারকে পারমিশন অ্যাসাইন করা হবে
        document = serializer.save(created_by=self.request.user)
        assign_perm('documents.view_document', self.request.user, document)
        assign_perm('documents.change_document', self.request.user, document)
        assign_perm('documents.delete_document', self.request.user, document)

    def list(self, request, *args, **kwargs):
        # ইউজারের পারমিশন চেক করা
        queryset = Document.objects.filter(company=request.user.profile.company)
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)
    
    def update(self, request, *args, **kwargs):
        document = self.get_object()
        if 'change_document' not in get_perms(request.user, document):
            return Response({'detail': 'Permission Denied'}, status=status.HTTP_403_FORBIDDEN)
        return super().update(request, *args, **kwargs)
        
    def destroy(self, request, *args, **kwargs):
        document = self.get_object()
        # Check if the user has the permission to delete the document
        if 'delete_document' not in get_perms(request.user, document):
            return Response({'detail': 'Permission Denied'}, status=status.HTTP_403_FORBIDDEN)
        return super().destroy(request, *args, **kwargs)        

ধাপ ৯: URL কনফিগার করা

# documents/urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import DocumentViewSet

router = DefaultRouter()
router.register(r'documents', DocumentViewSet)

urlpatterns = [
    path('', include(router.urls)),
]

নির্দিষ্ট user কে নির্দিষ্ট মডেল এর নির্দিষ্ট অবজেক্ট (রেকর্ড )এ এক্সেস দেয়ার api বানানো

মনেকরি আমরা api তে নিচের মতো করে রিকোয়েস্ট দেব যেখানে userid,মডেল ও অবজেক্ট এর id থাকবে এবং পারমিশন সেট হবে
Postman দিয়ে ডেটা পাঠানো

এখন আপনি Postman এর মাধ্যমে ডেটা পাঠাতে পারেন। নিচে একটি উদাহরণ দেওয়া হলো:

Body (JSON Format):

Method: POST

URL: http://127.0.0.1:8000/api/assign-permissions/

{
    "user_id": 1,
    "documents": [
        {
            "id": 101,
            "permissions": ["documents.view_document", "documents.change_document"]
        },
        {
            "id": 102,
            "permissions": ["documents.view_document", "documents.delete_document"]
        }
    ]
}

Serializers তৈরি করা

documents/serializers.py ফাইলে ডকুমেন্টের জন্য সিরিয়ালাইজার তৈরি করুন:

from rest_framework import serializers
from .models import Document

class DocumentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Document
        fields = ['id', 'title', 'content', 'company']

Views তৈরি করা

এবার API এর জন্য view তৈরি করতে হবে যা আমাদের ফ্রন্টএন্ড থেকে পাঠানো ডেটা প্রসেস করবে।

documents/views.py:

from guardian.shortcuts import assign_perm, remove_perm, get_perms
# 'guardian' লাইব্রেরি থেকে assign_perm, remove_perm, এবং get_perms ফাংশন ইমপোর্ট করা হচ্ছে
# assign_perm: নির্দিষ্ট ইউজারকে নির্দিষ্ট অবজেক্টের ওপর পারমিশন অ্যাসাইন করতে ব্যবহার হয়
# remove_perm: ইউজার থেকে নির্দিষ্ট অবজেক্টের পারমিশন রিমুভ করে
# get_perms: ইউজারের নির্দিষ্ট অবজেক্টে কোন কোন পারমিশন আছে তা বের করে

from rest_framework.response import Response
# 'Response' ক্লাসটি ইমপোর্ট করা হচ্ছে যা API রিকোয়েস্টের রেসপন্স হিসেবে ডেটা পাঠাতে ব্যবহৃত হয়

from rest_framework.views import APIView
# 'APIView' ক্লাসটি ইমপোর্ট করা হচ্ছে, যা Django Rest Framework এ API ভিউ তৈরি করতে ব্যবহৃত হয়

from rest_framework import status
# 'status' ইমপোর্ট করা হচ্ছে, যা বিভিন্ন HTTP status কোডের জন্য ব্যবহৃত হয় (যেমন 200, 404 ইত্যাদি)

from django.contrib.auth.models import User
# Django এর বিল্ট-ইন ইউজার মডেল ইমপোর্ট করা হচ্ছে, যাতে আমরা ইউজার সম্পর্কিত কাজ করতে পারি

from .models import Document
# 'Document' মডেলটি ইমপোর্ট করা হচ্ছে, যা সম্ভবত আমাদের ডাটাবেসে ডকুমেন্ট সংরক্ষণ করে

class AssignDocumentPermissions(APIView):
    # 'AssignDocumentPermissions' নামে একটি ক্লাস তৈরি করা হয়েছে যা APIView এর ইনহেরিটেড ক্লাস
    # এই ক্লাসে POST মেথড ব্যবহার করে পারমিশন অ্যাসাইন, রিমুভ বা চেক করা হবে
    
    def post(self, request):
        # POST রিকোয়েস্টের জন্য একটি মেথড তৈরি করা হলো
        user_id = request.data.get('user_id')  
        # রিকোয়েস্ট থেকে user_id বের করা হচ্ছে
        
        documents = request.data.get('documents', [])
        # রিকোয়েস্ট থেকে documents তালিকা বের করা হচ্ছে, ডিফল্ট হচ্ছে একটি খালি তালিকা
        
        action = request.data.get('action', 'assign')
        # রিকোয়েস্ট থেকে action বের করা হচ্ছে, ডিফল্ট হচ্ছে 'assign'

        # ইউজার খুঁজে বের করা
        try:
            user = User.objects.get(id=user_id)
            # user_id দিয়ে ইউজার খুঁজছি
        except User.DoesNotExist:
            # যদি ইউজার না পাওয়া যায়
            return Response({"detail": "User not found"}, status=status.HTTP_404_NOT_FOUND)
            # 404 স্ট্যাটাস সহ 'User not found' বার্তা পাঠাচ্ছি
        
        # প্রতিটি ডকুমেন্ট এবং তার পারমিশন অ্যাসাইন বা ডিলিট করার জন্য প্রস্তুতি নিচ্ছি
        result = {}
        # পারমিশনের ফলাফল সংরক্ষণ করার জন্য একটি ডিকশনারি তৈরি করছি
        
        for doc_data in documents:
            # প্রতিটি ডকুমেন্ট ডেটার জন্য লুপ
            doc_id = doc_data.get('id')
            # ডকুমেন্টের আইডি নিয়ে আসছি
            
            permissions = doc_data.get('permissions', [])
            # ডকুমেন্টের পারমিশনগুলো নিয়ে আসছি
            
            try:
                document = Document.objects.get(id=doc_id)
                # doc_id দিয়ে ডকুমেন্ট খুঁজছি
            except Document.DoesNotExist:
                # যদি ডকুমেন্ট না পাওয়া যায়
                return Response({"detail": f"Document with ID {doc_id} not found"}, status=status.HTTP_404_NOT_FOUND)
                # 404 স্ট্যাটাস সহ ডকুমেন্ট না পাওয়ার বার্তা পাঠাচ্ছি
            
            # পারমিশন অ্যাসাইন, ডিলিট বা চেক করার জন্য
            if action == 'assign':
                # যদি অ্যাকশন 'assign' হয়
                for perm in permissions:
                    # প্রতিটি পারমিশনের জন্য লুপ
                    assign_perm(perm, user, document)
                    # ইউজার এবং ডকুমেন্টের জন্য পারমিশন অ্যাসাইন করছি
            
            elif action == 'remove':
                # যদি অ্যাকশন 'remove' হয়
                for perm in permissions:
                    # প্রতিটি পারমিশনের জন্য লুপ
                    if perm in get_perms(user, document):
                        # ইউজারের কাছে পারমিশন আছে কিনা তা চেক করছি
                        remove_perm(perm, user, document)
                        # ইউজারের কাছ থেকে পারমিশন রিমুভ করছি
            
            elif action == 'check':
                # যদি অ্যাকশন 'check' হয়
                user_perms = get_perms(user, document)
                # ইউজারের ডকুমেন্টের পারমিশন চেক করা
                result[doc_id] = user_perms
                # ফলাফল ডিকশনারিতে সংরক্ষণ করছি

        # যদি অ্যাকশন 'check' হয়
        if action == 'check':
            return Response({"detail": "Permissions fetched successfully!", "permissions": result}, status=status.HTTP_200_OK)
            # 200 স্ট্যাটাস সহ পারমিশনস পাঠাচ্ছি
        else:
            return Response({"detail": f"Permissions {action}ed successfully!"}, status=status.HTTP_200_OK)
            # 200 স্ট্যাটাস সহ সফলতার বার্তা পাঠাচ্ছি

URLs সেটআপ করা

documents/urls.py:

from django.urls import path
from .views import AssignDocumentPermissions

urlpatterns = [
    # অ্যাসাইন/রিমুভ/চেক করার জন্য API URL
    path('permissions/', AssignDocumentPermissions.as_view(), name='assign_permissions'),
]

এখানে permissions/ নামে একটি URL রেজিস্টার করা হয়েছে, যা AssignDocumentPermissions ভিউ-এ রিকোয়েস্ট পাঠাবে।

রিকোয়েস্ট তৈরি করুন

আপনার API-এর URL প্রবেশ করান। যেমন:

HTTP মেথড নির্বাচন করুন:

POST নির্বাচন করুন। এটি API-তে নতুন ডেটা পাঠাতে ব্যবহৃত হয়।

URL প্রবেশ করান:

http://localhost:8000/api/assign-permissions/ 
  • (এটি আপনার Django সার্ভারের ঠিকানা হতে পারে। নিশ্চিত করুন যে সার্ভার চলমান আছে।)

Headers সেট করুন:

  • Headers ট্যাব নির্বাচন করুন এবং নতুন একটি header যোগ করুন:
    • Key: Content-Type
    • Value: application/json

Body সেট করুন:

  • Body ট্যাব নির্বাচন করুন এবং raw নির্বাচন করুন। তারপর JSON ফরম্যাটে আপনার ডেটা প্রবেশ করান। যেমন:
{
    "user_id": 1,
    "documents": [
        {
            "id": 101,
            "permissions": ["document.view_document", "document.change_document", "document.delete_document"] 
        },
        {
            "id": 102,
            "permissions": ["document.view_document"]
        }
    ],
    "action": "assign"
}
    • খানে user_id, documents, এবং action এর মান আপনার প্রয়োজন অনুযায়ী পরিবর্তন করুন।

পদক্ষেপ ৪: রিকোয়েস্ট পাঠান

  • সবকিছু ঠিকমত পূরণ করার পর, Send বোতামে ক্লিক করুন।

পদক্ষেপ ৫: রেসপন্স পরীক্ষা করুন

  • রিকোয়েস্ট সফল হলে, আপনি রেসপন্সে একটি JSON অবজেক্ট পাবেন যা বলবে “Permissions assigned successfully!” অথবা যদি কোনো সমস্যা হয় তবে আপনি তাও দেখতে পাবেন।

উদাহরণ রেসপন্স

সফল হলে রেসপন্সটি এরকম হতে পারে:

{
    "detail": "Permissions assigned successfully!"
}

এভাবে আপনি পোস্টম্যান ব্যবহার করে আপনার Django API তে রিকোয়েস্ট পাঠাতে পারবেন। যদি কোনো প্রশ্ন থাকে, বা কিছু বুঝতে অসুবিধা হয়, তাহলে জানাতে পারেন!

How can we help?