1,843 ریڈنگز
1,843 ریڈنگز

DIY Real-Time Polling اپلی کیشن Supabase اور Permit.io کے ساتھ رسائی کو بند کرتا ہے

کی طرف سے Permit.io40m2025/04/16
Read on Terminal Reader

بہت لمبا؛ پڑھنے کے لئے

ایک محفوظ، حقیقی وقت میں ووٹنگ اپلی کیشن کی تعمیر کے لئے ایک مکمل سٹاک گائیڈ، تصدیق، فی صارف کی اجازتیں، اور متحرک پالیسی چیک - Supabase + Permit.io کا استعمال کرتے ہوئے.
featured image - DIY Real-Time Polling اپلی کیشن Supabase اور Permit.io کے ساتھ رسائی کو بند کرتا ہے
Permit.io HackerNoon profile picture
0-item


سےGabriel L. Manor


Supabase آپ کے ایپ کو ای میل، OAuth، اور جادو لنکس کے لئے داخلہ کی حمایت کے ساتھ تصدیق کو شامل کرنے کے لئے آسان بناتا ہے. لیکن اگرچہ Supabase Auth آپ کے صارفین کے بارے میں کام کرتا ہے، تو آپ کو اکثر ایک تصدیق کی سطح کی ضرورت ہوتی ہے.


Supabase built-in auth and Row Level Security (RLS) کے ساتھ ایک عظیم backend پیش کرتا ہے.fine-grained permissionsخاص طور پر ان کی بنیاد پرrelationships between users and dataآسان سے دور ہے


آپ ڈیٹا کو ترمیم یا حذف کرنے جیسے کارروائیوں کو وسائل کے مالکان کو محدود کرنا چاہتے ہیں، صارفین کو ان کے اپنے مواد پر ووٹ کرنے سے روکنے، یا مختلف صارف کرداروں کے لئے مختلف اجازتوں کو نافذ کرنا چاہتے ہیں.


یہ ٹیوٹوریل چلتا ہے کہ کس طرح لاگو کرنے کے لئےSupabase authentication and authorization in a Next.jsاپلی کیشن

ہم شروع کریں گےSupabase Authلاگ ان اور سیشن کے انتظام کے لئے، پھر شامل کریںauthorization rulesاستعمال کریںروابط پر مبنی رسائی کنٹرول (ReBAC), enforced through Supabase Edge Functionsاور Alocal Policy Decision Point (PDP)کے


آخر میں، آپ کے پاس ایک حقیقی وقت کے تعاون کے سروے کے ایپ ہے جو دونوں عوامی اور محفوظ کارروائیوں کی حمایت کرتا ہے - اور ایک انعطاف پذیر لائسنس کے نظام آپ کے ایپ بڑھنے کے طور پر ترقی کر سکتے ہیں.

ہم کیا بناتے ہیں

اس گائیڈ میں، ہم ایک حقیقی وقت میں ووٹنگ اپلی کیشن کی تعمیر کریں گےSupabaseاورNext.jsیہ عمل میں تصدیق اور مجازیت دونوں کو ظاہر کرتا ہے.


اپلی کیشن صارفین کو سروے بنانے، دوسروں پر ووٹ دینے اور صرف ان کے اپنے مواد کا انتظام کرنے کی اجازت دیتا ہے.Supabase Authlogin / signup کے لئے اور کس طرح لاگو کرنے کے لئےauthorization policiesیہ کنٹرول کرتا ہے جو ووٹ، ترمیم، یا حذف کر سکتے ہیں.


ہم Supabase کے بنیادی خصوصیات کا استعمال کریں گے-Auth،Postgres،RLS،RealtimeاورEdge FunctionsA کے ساتھ مل کرRelationship-Based Access Control (ReBAC)فی صارف اور فی وسائل تک رسائی کے قوانین کو نافذ کرنے کے لئے ماڈل.

تکنیکی Stack

    کے
  • Supabase – ڈیٹا بیس، تصدیق، حقیقی وقت، اور کنج کے افعال کے لئے بیکنڈ-as-a-service
  • کے
  • Next.js – اپلی کیشن UI اور API روٹس کی تعمیر کے لئے Frontend فریم ورک
  • کے
  • Permit.io – (ReBAC کے لئے) PDP کے ذریعہ لائسنسنگ منطق کی وضاحت کرنے کے لئے
  • کے
  • Supabase CLI - مقامی طور پر اور پیداوار میں Edge Functions کا انتظام اور تنصیب کرنے کے لئے
  • کے
نوٹنگNext.جیسےکی اجازتزمرہ:CLI

Prerequisites

    کے
  • Node.js نصب کیا گیا ہے
  • کے
  • اکاؤنٹ بونس
  • کے
  • اکاؤنٹ کی اجازت
  • کے
  • React/Next.js کے بارے میں معلومات
  • کے
  • پروجیکٹ Repo
  • کے

یہ اپلی کیشن کیا کر سکتا ہے؟

ڈیمو ایپلی کیشن ایک حقیقی وقت میں ووٹنگ پلیٹ فارم ہے جو Next.js اور Supabase کے ساتھ تعمیر کیا گیا ہے، جہاں صارفین ووٹ بن سکتے ہیں اور دوسروں پر ووٹ کرسکتے ہیں.


    کے
  • کسی بھی صارف (مجاز یا نہیں) عوامی سروے کی فہرست دیکھ سکتے ہیں
  • کے
  • صرف تصدیق شدہ صارفین کو سروے بنانے اور ووٹ کر سکتے ہیں
  • کے
  • ایک صارف نے پیدا کردہ سروے پر ووٹ نہیں کر سکتے
  • کے
  • صرف ایک سروے کا تخلیق کرنے والا اسے ترمیم یا حذف کر سکتا ہے
  • کے

Tutorial کا جائزہ لیں

ہم ان عام اقدامات پر عمل کریں گے:


    کے
  1. Supabase پروجیکٹ، schema، auth، اور RLS کو قائم کریں
  2. کے
  3. ایپ کی بنیادی خصوصیات بنائیں جیسے سروے کی تخلیق اور ووٹنگ
  4. کے
  5. Permit.io میں نقشے اور قواعد کا تعین کرنے کے لئے ماڈل لائسنس کے قوانین
  6. کے
  7. صارفین کو سائن اپ کرنے کے لئے Supabase Edge Functions پیدا کریں، نقشے کا تعین کریں، اور اجازتوں کی جانچ پڑتال کریں
  8. کے
  9. اپلی کیشن کے Frontend میں پالیسیوں کو ان Edge فائلوں کا استعمال کرتے ہوئے لاگو کریں
  10. کے


شروع کریں -

Setting up Supabase in the Project

پروجیکٹ میں Supabase کی تشکیل

اختیاری: Clone the Starter Template

I've already created a Temple کے آغازہےGitHubتمام کوڈ کے ساتھ آپ کو شروع کرنے کی ضرورت ہے تاکہ ہم Supabase اور Permit.io کو نافذ کرنے پر توجہ مرکوز کرسکتے ہیں.


آپ مندرجہ ذیل کمانڈ کو چلانے کے ذریعے منصوبہ کو کلن کرسکتے ہیں:


git clone <https://github.com/permitio/supabase-fine-grained-authorization>


ایک بار جب آپ پروجیکٹ کینسر کر چکے ہیں تو، پروجیکٹ ڈائریکٹری میں رجسٹریشن کریں اور انفرادیات کو انسٹال کریں:


cd realtime-polling-app-nextjs-supabase-permitio
npm install

Supabase میں ایک نیا منصوبہ بنائیں

شروع کرنے کے لئے:

    کے
  • https://supabase.com پر جائیں اور لاگ ان کریں یا ایک اکاؤنٹ بنائیں.
  • کے
  • "نئی پروجیکٹ" پر کلک کریں اور اپنے پروجیکٹ کا نام، پاس ورڈ اور علاقے درج کریں.
  • کے
  • ایک بار پیدا ہونے کے بعد، پروجیکٹ ترتیبات → API پر جائیں اور اپنے پروجیکٹ URL اور Anon Key کو نوٹ کریں - آپ کو بعد میں ان کی ضرورت ہوگی.
  • کے

Supabase میں تصدیق اور ڈیٹا بیس کی تشکیل

ہم Supabase کے داخلہ ای میل / پاس ورڈ auth استعمال کریں گے:

  • sidebar میں، Authentication → Providers پر جائیں
  • ای میل فراہم کرنے والے کو فعال کریں
  • کے
  • (مختصر) ٹیسٹ کے لئے ای میل کی تصدیق کو غیر فعال کریں، لیکن پیداوار کے لئے اسے فعال رکھیں
  • کے

ڈیٹا بیس کے نظام کی تخلیق

یہ اپلی کیشن تین اہم ٹیبلز کا استعمال کرتا ہے:polls،optionsاورvotesاستعمال کریں TheSQL EditorSupabase Dashboard پر اور مندرجہ ذیل کو چلائیں:


-- Create a polls table
CREATE TABLE polls (
    id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
    question TEXT NOT NULL,
    created_by UUID REFERENCES auth.users(id) NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT TIMEZONE('utc', NOW()),
    creator_name TEXT NOT NULL,
    expires_at TIMESTAMP WITH TIME ZONE NOT NULL,
);

-- Create an options table
CREATE TABLE options (
    id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
    poll_id UUID REFERENCES polls(id) ON DELETE CASCADE,
    text TEXT NOT NULL,
);

-- Create a votes table
CREATE TABLE votes (
    id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
    poll_id UUID REFERENCES polls(id) ON DELETE CASCADE,
    option_id UUID REFERENCES options(id) ON DELETE CASCADE,
    user_id UUID REFERENCES auth.users(id),
    created_at TIMESTAMP WITH TIME ZONE DEFAULT TIMEZONE('utc', NOW()),
    UNIQUE(poll_id, user_id)
);

راؤنڈ سطح کی حفاظت (RLS)

کی اجازتRLS کے for each table and define policies:

-- Polls policies
ALTER TABLE polls ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Anyone can view polls" ON polls
    FOR SELECT USING (true);

CREATE POLICY "Authenticated users can create polls" ON polls
    FOR INSERT TO authenticated
    WITH CHECK (auth.uid() = created_by);

-- Options policies
ALTER TABLE options ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Anyone can view options" ON options
    FOR SELECT USING (true);

CREATE POLICY "Poll creators can add options" ON options
    FOR INSERT TO authenticated
    WITH CHECK (
        EXISTS (
            SELECT 1 FROM polls
            WHERE id = options.poll_id
            AND created_by = auth.uid()
        )
    );

-- Votes policies
ALTER TABLE votes ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Anyone can view votes" ON votes
    FOR SELECT USING (true);

CREATE POLICY "Authenticated users can vote once" ON votes
    FOR INSERT TO authenticated
    WITH CHECK (
        auth.uid() = user_id AND
        NOT EXISTS (
            SELECT 1 FROM polls
            WHERE id = votes.poll_id
            AND created_by = auth.uid()
        )
    );


Supabase کے حقیقی وقت کی خصوصیات کا استعمال کرنے کے لئے:

    کے
  • سائیڈر میں، ٹیبل ایڈیٹر پر جائیں
  • کے
  • تین ٹیبلوں (پیلنگز، اختیارات، ووٹوں) کے لئے: تین پوائنٹس پر کلک کریں → ٹیبل Toggle کو ترمیم کریں "Realtime کو فعال کریں" تبدیلیوں کو محفوظ کریں
  • کے

اپلی کیشن میں Supabase Email Authentication

اس ڈیمو ایپ میں، کوئی بھی اپلی کیشن پر دستیاب سروے کی فہرست کو دیکھ سکتا ہے، فعال اور ختم شدہ دونوں. ایک سروے کی تفصیلات کو دیکھنے کے لئے، کسی بھی سروے پر انتظام، یا ووٹ کرنے کے لئے، صارف کو لاگ ان ہونا ضروری ہے. ہم اس منصوبے کے لئے تصدیق کے ذریعہ ای میل اور پاس ورڈ کا استعمال کریں گے..env.local: :

NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_anon_key


آپ کے لاگ ان اجزاء کو اپ ڈیٹ کریں اور ای میل / پاس ورڈ کے ذریعے سائن اپ اور لاگ ان دونوں کو منظم کریں:


import { useState } from "react";
import { createClient } from "@/utils/supabase/component";

const LogInButton = () => {
  const supabase = createClient();

  async function logIn() {
    const { error } = await supabase.auth.signInWithPassword({
      email,
      password,
    });
    if (error) {
      setError(error.message);
    } else {
      setShowModal(false);
    }
  }
  
  async function signUp() {
    const { error } = await supabase.auth.signUp({
      email,
      password,
      options: {
        data: {
          user_name: userName,
        },
      },
    });
    if (error) {
      setError(error.message);
    } else {
      setShowModal(false);
    }
  }

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    setError("");

    if (isLogin) {
      await logIn();
    } else {
      await signUp();
    }
  };

  return (
    <>
      <button
        onClick={() => setShowModal(true)}
        className="flex items-center gap-2 p-2 bg-gray-800 text-white rounded-md">
        Log In
      </button>
      ...
    </>
  );
};

export default LogInButton;


یہاں، ہم Supabase کا استعمال کرتے ہیںsignInWithPasswordایک صارف پر لاگ ان کرنے کا طریقہ اورsignUpایک نیا صارف کو ان کے ای میل اور پاس ورڈ کے ساتھ رجسٹر کرنے کا طریقہ. ہم بھی صارف کے نام کو ذخیرہ کر رہے ہیںuser_nameصارف کے میٹا ڈیٹا میں.


آپ بھی استعمال کر سکتے ہیںsupabase.auth.signOut()صارفین کو لاگ ان کرنے اور ان کو ہدایت کرنے کے لئے:


import { createClient } from "@/utils/supabase/component";
import { useRouter } from "next/router";

const LogOutButton = ({ closeDropdown }: { closeDropdown: () => void }) => {
  const router = useRouter();
  const supabase = createClient();

  const handleLogOut = async () => {
    await supabase.auth.signOut();
    closeDropdown();
    router.push("/");
  };
    
  return (
  ...
  );
};

export default LogOutButton;


یہاں، ہم استعمال کرتے ہیںsignOutSupabase سے طریقہ کار صارف کو لاگ ان کرنے اور ان کو ہوم پیج پر ہدایت کرنے کے لئے.

صارف کی تصدیق کی حالت میں تبدیلیوں کے لئے سننے

Listening for changes in the user's authentication state allows us to update the UI based on the user's authentication status. This allows you to:


    کے
  • دکھائیں / login / logout بٹن جیسے UI عناصر چھپائیں
  • کے
  • محفوظ صفحات تک رسائی کو محدود کریں (مثال کے طور پر ووٹنگ یا سروے کا انتظام)
  • کے
  • یقینی بنائیں کہ صرف تصدیق شدہ صارفین محدود کارروائیوں کو انجام دے سکتے ہیں
  • کے


ہم استعمال کریں گےsupabase.auth.onAuthStateChange() to listen to these events and update the app accordingly.


In theکےLayout.tsxکےfile: Track Global Auth State


import React, { useEffect, useState } from "react";
import { createClient } from "@/utils/supabase/component";
import { User } from "@supabase/supabase-js";

const Layout = ({ children }: { children: React.ReactNode }) => {
  const [user, setUser] = useState<User | null>(null);

  useEffect(() => {
    const fetchUser = async () => {
      const supabase = createClient();
      const { data } = supabase.auth.onAuthStateChange((event, session) => {
        setUser(session?.user || null);
      });

      return () => {
        data.subscription.unsubscribe();
      };
    };

    fetchUser();
  }, []);

  return (
    ...
  );
};

export default Layout;

Restrict Access on Protected Pages

جیسے صفحاتpoll detailsیاpoll managementآپ کو بھی ان کی تصدیق کی حالت میں تبدیلیوں کو سننا چاہئے تاکہ غیر تصدیق شدہ صارفین ان تک رسائی حاصل کرنے سے روکیں.


یہ ہے کہ یہ کس طرح میں نظر آتا ہےpages/polls/[id].tsx: :

import { createClient } from "@/utils/supabase/component";
import { User } from "@supabase/supabase-js";

const Page = () => {
  const [user, setUser] = useState<User | null>(null);

  useEffect(() => {
    const fetchUser = async () => {
      const supabase = createClient();
      const { data } = supabase.auth.onAuthStateChange((event, session) => {
        setUser(session?.user || null);
        setLoading(false);
      });

      return () => {
        data.subscription.unsubscribe();
      };
    };

    fetchUser();
  }, []);

  return (
    ...
  );

export default Page;


And a similar pattern applies in pages/polls/manage.tsx, where users should only see their own polls if logged in:


import { createClient } from "@/utils/supabase/component";
import { User } from "@supabase/supabase-js";

const Page = () => {
  const [user, setUser] = useState<User | null>(null);
  
  const supabase = createClient();

  useEffect(() => {
    const fetchUser = async () => {
      const { data } = supabase.auth.onAuthStateChange((event, session) => {
        setUser(session?.user || null);
        if (!session?.user) {
          setLoading(false);
        }
      });

      return () => {
        data.subscription.unsubscribe();
      };
    };

    fetchUser();
  }, []);

  return (
    ...
  );
};

export default Page;


یہ نمونے اس بات کو یقینی بناتے ہیں کہ آپ کا UI صارف کی موجودہ تصدیق کی حیثیت کا تعین کرتا ہے اور ہم بعد میں شامل کرنے والے تصدیق چیک کے لئے بنیاد بناتا ہے.userObject جب آپ کو کال کریںcheckPermission Edge Function to determine whether a user is allowed to vote or manage a specific poll.

Polling App کی سرگرمیوں کی تعمیر

Supabase کی ترتیب اور تصدیق کے کام کے ساتھ، ہم اب ووٹنگ ایپ کے بنیادی سرگرمیوں کو تعمیر کرسکتے ہیں.


    کے
  • نئے سروے بنائیں
  • کے
  • حقیقی وقت میں سروے کی فہرست اور دکھائیں
  • کے
  • ایک ووٹنگ کا نظام
  • کے


This gives us the basic app behavior that we’ll soon protect with fine-grained permissions.

نئے سروے بنائیں

صارفین کو سروے بنانے کے لئے لاگ ان ہونا ضروری ہے. ہر سروے میں ایک سوال، ایک اختتام کی تاریخ اور ایک سیٹ اختیارات شامل ہیں. ہم یہ بھی ریکارڈ کرتے ہیں کہ کس نے سروے کو پیدا کیا تاکہ ہم بعد میں اس رشتے کو رسائی کنٹرول کے لئے استعمال کرسکتے ہیں.


اندرNewPoll.tsx, fetch the authenticated user, and use Supabase to insert the poll and its options:


import React, { useEffect, useState } from "react";
import { createClient } from "@/utils/supabase/component";
import { User } from "@supabase/supabase-js";

const NewPoll = () => {
  const [user, setUser] = useState<User | null>(null);
  
  const supabase = createClient();

  useEffect(() => {
    const fetchUser = async () => {
      const supabase = createClient();
      const { data } = supabase.auth.onAuthStateChange((event, session) => {
        setUser(session?.user || null);
      });

      return () => {
        data.subscription.unsubscribe();
      };
    };

    fetchUser();
  }, []);

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();

    if (question.trim() && options.filter(opt => opt.trim()).length < 2) {
      setErrorMessage("Please provide a question and at least two options.");
      return;
    }

     // Create the poll
     const { data: poll, error: pollError } = await supabase
      .from("polls")
      .insert({
        question,
        expires_at: new Date(expiryDate).toISOString(),
        created_by: user?.id,
        creator_name: user?.user_metadata?.user_name,
      })
      .select()
      .single();

    if (pollError) {
      console.error("Error creating poll:", pollError);
      setErrorMessage(pollError.message);
      return;
    }
    
    // Create the options
    const { error: optionsError } = await supabase.from("options").insert(
      options
        .filter(opt => opt.trim())
        .map(text => ({
          poll_id: poll.id,
          text,
        }))
    );

    if (!optionsError) {
      setSuccessMessage("Poll created successfully!");
      handleCancel();
    } else {
      console.error("Error creating options:", optionsError);
      setErrorMessage(optionsError.message);
    }
  };

  return (
     ...
  );
};

export default NewPoll;

ہم بعد میں Permit.io میں "Creator" کردار کو توسیع کرنے کے لئے یہاں ایک Edge Function کال کریں گے.

Polls کو تلاش اور دکھائیں

سروے میں تقسیم کیا گیاactive(مجھے ابھی تک نہیں مل سکا) اورpast (expired). You can fetch them using Supabase queries filtered by the current timestamp, and set up real-time subscriptions to reflect changes instantly.


مثال سےpages/index.tsx: :


import { PollProps } from "@/helpers";
import { createClient } from "@/utils/supabase/component";

export default function Home() {
  const supabase = createClient();

  useEffect(() => {
    const fetchPolls = async () => {
      setLoading(true);
      const now = new Date().toISOString();

      try {
        // Fetch active polls
        const { data: activePolls, error: activeError } = await supabase
          .from("polls")
          .select(
            `
            id,
            question,
            expires_at,
            creator_name,
            created_by,
            votes (count)
          `
          )
          .gte("expires_at", now)
          .order("created_at", { ascending: false });

        if (activeError) {
          console.error("Error fetching active polls:", activeError);
          return;
        }

        // Fetch past polls
        const { data: expiredPolls, error: pastError } = await supabase
          .from("polls")
          .select(
            `
            id,
            question,
            expires_at,
            creator_name,
            created_by,
            votes (count)
          `
          )
          .lt("expires_at", now)
          .order("created_at", { ascending: false });

        if (pastError) {
          console.error("Error fetching past polls:", pastError);
          return;
        }

        setCurrentPolls(activePolls);
        setPastPolls(expiredPolls);
      } catch (error) {
        console.error("Unexpected error fetching polls:", error);
      } finally {
        setLoading(false);
      }
    };

    fetchPolls();
    
        // Set up real-time subscription on the polls table:
    const channel = supabase
      .channel("polls")
      .on(
        "postgres_changes",
        {
          event: "*",
          schema: "public",
          table: "polls",
        },
        fetchPolls
      )
      .subscribe();

    return () => {
      supabase.removeChannel(channel);
    };
  }, []);

  return (
    ...
  );
}

صارفین کے سروے کو دیکھیں اور منظم کریں

یہاں، ہم فعال اور ماضی کے سروے سے حاصل کر رہے ہیںpollsSupabase.We are also setting up a real-time subscription to listen for changes in thepolls table so that we can update the UI with the latest poll data. To differentiate between active and past polls, we are comparing the expiry date of each poll with the current date.


اپ ڈیٹ کریںpages/manage.tsxصفحہ حاصل کرنے اور صرف صارف کی طرف سے پیدا کردہ سروے کو ظاہر کرنے کے لئے:


import { PollProps } from "@/helpers";

const Page = () => {
  
  useEffect(() => {
    if (!user?.id) return;

    const fetchPolls = async () => {
      try {
        const { data, error } = await supabase
          .from("polls")
          .select(
            `
            id,
            question,
            expires_at,
            creator_name,
            created_by,
            votes (count)
          `
          )
          .eq("created_by", user.id)
          .order("created_at", { ascending: false });

        if (error) {
          console.error("Error fetching polls:", error);
          return;
        }

        setPolls(data || []);
      } catch (error) {
        console.error("Unexpected error fetching polls:", error);
      } finally {
        setLoading(false);
      }
    };

    fetchPolls();

    // Set up real-time subscription
    const channel = supabase
      .channel(`polls_${user.id}`)
      .on(
        "postgres_changes",
        {
          event: "*",
          schema: "public",
          table: "polls",
          filter: `created_by=eq.${user.id}`,
        },
        fetchPolls
      )
      .subscribe();

    return () => {
      supabase.removeChannel(channel);
    };
  }, [user]);

   return (
    ...
  );
};

export default Page;


Here, we only fetch polls created by the user and listen for real-time updates in the polls table so that the UI is updated with the latest poll data.


اس کے علاوہ، اپ ڈیٹPollCardاس طرح، اگر ایک لاگ ان شدہ صارف سروے کی تخلیق کرنے والا ہے تو، سروے کو ترمیم اور حذف کرنے کے لئے علامتیں ان کو سروے میں دکھایا جائے گا.


import { createClient } from "@/utils/supabase/component";
import { User } from "@supabase/supabase-js";

const PollCard = ({ poll }: { poll: PollProps }) => {
  const [user, setUser] = useState<User | null>(null);
  
  useEffect(() => {
    const supabase = createClient();
    const fetchUser = async () => {
      const { data } = supabase.auth.onAuthStateChange((event, session) => {
        setUser(session?.user || null);
        setLoading(false);
      });

      return () => {
        data.subscription.unsubscribe();
      };
    };

    fetchUser();
  }, []);

  return (
    ...
      )}
    </Link>
  );
};

export default PollCard;


لہذا اب، ایک سروے کارڈ پر، اگر لاگ ان کردہ صارف سروے کا تخلیق کرنے والا ہے تو، سروے کو ترمیم اور حذف کرنے کے لئے آئکنز ان کو دکھایا جائے گا.

ووٹنگ کے نظام کا استعمال

ووٹنگ کی منطق کے مطابق:

    کے
  • ہر صارف کے لئے صرف ایک ووٹ
  • کے
  • تخلیق کار اپنے سروے پر ووٹ نہیں کرسکتے
  • کے
  • Votes are stored in the votes table
  • نتائج واقعی وقت میں دکھایا جاتا ہے اور اپ ڈیٹ کیا جاتا ہے
  • کے


ہمیں یہ بتائیں کہ یہ کس طرح کام کرتا ہےViewPoll.tsx component:


Fetch the Logged-In Userہم اس وقت کے صارف کے ID کو منتخب کرنے کے لئے ووٹنگ کی صلاحیت اور ان کی ووٹنگ کی ریکارڈ کرنے کی ضرورت ہے.


import { createClient } from "@/utils/supabase/component";
import { User } from "@supabase/supabase-js";

const ViewPoll = () => {
  const [user, setUser] = useState<User | null>(null);

  const supabase = createClient();

  useEffect(() 
    const fetchUser = async () => {
      const {
        data: { user },
      } = await supabase.auth.getUser();
      setUser(user);
    };

    fetchUser();
  }, []);


Load Poll Details and Check Voting Statusجب ہم صارف کو حاصل کرتے ہیں، ہم:

    کے
  • انٹرویو خود (مقابلہ اختیارات اور ووٹ کا حساب بھی شامل ہے)
  • کے
  • Whether this user has already voted
  • کے


ہم بھی ان کو دوبارہ بعد میں حقیقی وقت کے اپ ڈیٹس میں کال کریں گے.


  useEffect(() => {
    if (!user) {
      return;
    }
    
    const checkUserVote = async () => {
      const { data: votes } = await supabase
        .from("votes")
        .select("id")
        .eq("poll_id", query.id)
        .eq("user_id", user.id)
        .single();

      setHasVoted(!!votes);
      setVoteLoading(false);
    };
   
    const fetchPoll = async () => {
      const { data } = await supabase
        .from("polls")
        .select(
          `
          *,
          options (
            id,
            text,
            votes (count)
          )
        `
        )
        .eq("id", query.id)
        .single();

      setPoll(data);
      setPollLoading(false);

      checkUserVote();
    };

    fetchPoll();


Listen for Real-Time Updates

ہم تبدیلیوں میں شامل ہیںvotesجب ایک نیا ووٹ دیا جاتا ہے تو، ہم اپ ڈیٹ ووٹنگ ڈیٹا اور ووٹنگ کی حالت حاصل کرتے ہیں.


    const channel = supabase
      .channel(`poll-${query.id}`)
      .on(
        "postgres_changes",
        {
          event: "*",
          schema: "public",
          table: "votes",
          filter: `poll_id=eq.${query.id}`,
        },
        () => {
          fetchPoll();
          checkUserVote();
        }
      )
      .subscribe();

    return () => {
      supabase.removeChannel(channel);
    };
  }, [query.id, user]);


Handle the Vote Submission

If the user hasn’t voted and is allowed to vote (we’ll add a permission check later), we insert their vote.


  const handleVote = async (optionId: string) => {
    if (!user) return;

    try {
      const { error } = await supabase.from("votes").insert({
        poll_id: query.id,
        option_id: optionId,
        user_id: user.id,
      });

      if (!error) {
        setHasVoted(true);
      }
    } catch (error) {
      console.error("Error voting:", error);
    }
  };


Display the Poll Resultsہم تمام ووٹوں کی کل تعداد اور ختم ہونے کا وقت پر ایک بونس کی تعداد کا حساب کرتے ہیں. آپ اس کے بعد ترقی کے بارز یا اعداد و شمار کو ظاہر کرنے کے لئے اس کا استعمال کرسکتے ہیں.


  if (!poll || pollLoading || voteLoading) return <div>Loading...</div>;

  // 6. calculate total votes
  const totalVotes = calculateTotalVotes(poll.options);
  const countdown = getCountdown(poll.expires_at);

  return (
  ...
  );
};

export default ViewPoll;


اس ترتیبات کے ساتھ، آپ کا ووٹنگ سسٹم مکمل طور پر کام کرتا ہے. لیکن اب، جو بھی لاگ ان کرسکتے ہیں، تکنیکی طور پر ووٹنگ کرنے کی کوشش کرسکتے ہیں - یہاں تک کہ ان کے اپنے ووٹنگ میں بھی.authorization checksاستعمال کریںPermit.ioاورSupabase Edge Functionsان قوانین کو پورا کرنے کے لئے.


ہم ایسا کرنے سے پہلے، ہم سب سے پہلے اس قسم کی ذمہ داری کی سطح پر نظر ڈالیں جو ہم لاگو کرنے جا رہے ہیں.

ReBAC (Relationship-Based Access Control) کا استعمال کرتے ہوئے

Supabase handles authentication and basic row-level permissions well, but it doesn’t support complex rules like:

    کے
  • Preventing users from voting on their own polls
  • کے
  • ایک مخصوص سروے کے لئے "Creator" کے طور پر (مثال کے طور پر)
  • کے
  • بیرونی پالیسیوں کے ذریعے رسائی کا انتظام
  • کے


ان قسم کے رشتے پر مبنی اجازتوں کی حمایت کرنے کے لئے، ہم Permit.io کے ساتھ ReBAC کو انسٹال کریں گے.


روابط پر مبنی رسائی کنٹرول (ReBAC)صارفین اور وسائل کے درمیان تعلقات کی بنیاد پر اجازتوں کا انتظام کرنے کے لئے ایک ماڈل ہے اور صرف کرداروں یا خصوصیات پر بھروسہ کرنے کے بجائے (جیسا کہ RBAC یا ABAC میں)، ReBAC اس طریقے سے رسائی کا تعین کرتا ہے کہ ایک صارف کس طرح اس وسائل سے منسلک ہے جسے وہ رسائی حاصل کرنے کی کوشش کر رہے ہیں.

روابط پر مبنی رسائی کنٹرول (ReBAC)


In this tutorial, we apply ReBAC to a polling app:

    کے
  • ایک صارف جو ایک سروے بناتا ہے وہ صرف وہ ہے جو اس کا انتظام کر سکتا ہے (مزید / حذف)
  • کے
  • A user cannot vote on their own poll
  • دیگر تصدیق شدہ صارفین ہر سروے میں ایک بار ووٹ کر سکتے ہیں
  • کے


By modeling these relationships in Permit.io, we can define fine-grained access rules that go beyond Supabase’s built-in Row Level Security (RLS). We’ll enforce them at runtime using Supabase Edge Functions and Permit’s policy engine.


ReBAC پر مزید کے لئے، چیک کریںPermit.io کے ReBAC دستاویز.

رسائی کنٹرول ڈیزائن

For our Polling app, we will define:

    کے
  • ایک ذریعہ جس میں وسائل کی مخصوص کارروائی ہوتی ہے: سروے: پیدا کریں، پڑھیں، حذف کریں، اپ ڈیٹ کریں.
  • کے
  • Two roles for granting permission levels based on a user’s relationship with the resources:
    • authenticated: Can perform create and read actions in polls. Can not delete, or update actions in polls.
    • creator: Can create, read, delete, and update actions in polls. Can perform read and create actions in votes. Cannot use create on their own polls.
  • کے

Permit.io کو اپ لوڈ کریں

براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی براہ مہربانی.

    کے
  • Permit.io میں ایک نیا منصوبہ بنائیں اس کا نام کچھ supabase-polling کی طرح ہے
  • کے
  • Define the polls resource
    • Go to the Policy → Resources tab
    • Click “Create Resource”
    • Name it polls, and add the actions: read, create, update, delete
  • Resource کے لئے ReBAC کو فعال کریں "ReBAC اختیارات" کے تحت، مندرجہ ذیل کرداروں کو مقرر کریں: تصدیق شدہ تخلیق کار Click Save
  • کے
ایک نیا منصوبہ بنائیں

‫‪ ،‬جیسے‪ ،‬جیسے‪ ،‬جیسے‪ ،‬جیسے‪ ،‬جیسے‪ ،‬جیسے‪ ،‬جیسے‪ ،‬جیسے‪ ،‬جیسے‪ ،‬جیسے‪ ،‬جیسے‪ ،‬جیسے‪ ،‬جیسے‪ ،‬جیسے‪ ،‬جیسے‪ ،‬جیسے‪ ،‬جیسے‪ ،‬جیسے‪ ،‬جیسے‪ ،‬جیسے‪ ،‬جیسے‪ ،‬جیسے‪ ،‬جیسے‪ ،‬جیسے‪ ،‬جیسے‪ ،‬جیسے‪ ،‬جیسے‪ ،‬جیسے‪ ،‬جیسے‪ ،‬جیسے‪ ،‬جیسے‪ ،‬جیسے‪ ،‬جیسadmin،editor،user) that are unnecessary for this tutorial.


    کے
  • رسائی کی پالیسیوں کا تعین کریں پالیسیوں ٹیب پر جائیں Visual matrix کا استعمال کریں: authenticated کر سکتے ہیں پڑھنے اور پیدا کرنے کے لئے سروے کی تخلیق کر سکتے ہیں پڑھنے، اپ ڈیٹ اور حذف کرنے کے لئے سروے (مزید) آپ اس کے حصے کے طور پر ووٹ کی اجازتوں کو ترتیب دے سکتے ہیں یا ایک دوسرا وسائل کے ذریعہ اگر آپ الگ الگ الگ ووٹ ماڈل کر سکتے ہیں
  • کے
  • ذریعہ انسٹینز شامل کریں ڈائریکٹری میں جائیں → انسٹینز ذاتی سروے ایڈز کو ذریعہ انسٹینز کے طور پر شامل کریں (آپ نئے سروے بنائے جاتے وقت اس کے بعد خود کار طریقے سے کریں گے) سروے پر صارفین کو کردار ادا کریں (مثال کے طور پر، user123 سروے 456 کی تخلیق کرنے والا ہے)
  • کے

اس ساخت نے ہمیں فکسڈ رسائی کے قوانین لکھنے اور ہر صارف، ہر سروے پر ان کی اطلاق کرنے کی صلاحیت دی.


اب کہ ہم اجازت ڈسپلے پر ابتدائی تنصیب مکمل کر چکے ہیں، ہمیں اس کا استعمال ہمارے ایپلی کیشن میں کریں.کی اجازتہمارے Supabase پروجیکٹ کو Edge Functions کے ذریعے جو:

    کے
  • Sync نئے صارفین
  • کے
  • Assign creator roles
  • درخواست پر رسائی کی جانچ پڑتال
  • کے

Setting up Permit in the Polling Application

اجازت آپ کے ایپلی کیشن کے ساتھ انضمام کرنے کے کئی طریقے پیش کرتا ہے، لیکن ہم اس ٹیوٹوریل کے لئے کنٹینر PDP کا استعمال کریں گے. آپ کو اس کنٹینر کو آن لائن ہوسٹ کرنے کی ضرورت ہے تاکہ آپ اس تک رسائی حاصل کرسکتے ہیں Supabase Edge افعال.railway.comایک بار جب آپ اسے میزبان کرتے ہیں تو، اپنے کنٹینر کے لئے url محفوظ کریں.


آپ کی اجازت API کلید حاصل کرسکتے ہیں "Projects" پر کلک کرتے ہوئے اجازت ڈسپلے بیل میں، آپ کے کام کر رہے ہیں کہ منصوبہ پر سواری، تین پوائنٹس پر کلک کریں، اور "Copy API Key" کا انتخاب کریں.


Authorization کے لئے Supabase Edge Function API

Supabase Edge FunctionsPermit.io جیسے تیسرے فریق کی خدمات کو منسلک کرنے کے لئے بہترین ہیں. ہم ان کا استعمال کریں گے کہ صارفین کو سروے پر مخصوص کارروائیوں کو انجام دینے کی اجازت ہے یا نہیں کی جانچ پڑتال کرتے ہوئے چلانے کے وقت ہمارے ReBAC قوانین کو نافذ کریں.

Create Functions in Supabase

آپ کے منصوبے میں Supabase کو ابتدائی کریں اور اس کا استعمال کرتے ہوئے تین مختلف افعال بنائیںsupabase functions new command. These will be the starting point for your functions:

npx supabase init
npx supabase functions new syncUser
npx supabase functions new updateCreatorRole
npx supabase functions new checkPermission

یہ پیدا کرے گا ایکfunctionsفہرست میںsupabaseاب، ہم ہر نقطہ کے لئے کوڈ لکھیں.

زمرہ:تصویر میں زمرہ:تصویر میں زمرہ:تصویر میں زمرہ:syncUser.ts) کے

یہ فہرست Supabase's کے لئے ہےSIGNED_UPجب ایک نیا صارف لاگ ان کرتا ہے، ہم Permit.io پر ان کی شناخت سائن اپ کرتے ہیں اور ان کو معاوضہ فراہم کرتے ہیںauthenticatedنقشہ


import "jsr:@supabase/functions-js/edge-runtime.d.ts";
import { Permit } from "npm:permitio";

 const corsHeaders = {
  'Access-Control-Allow-Origin': "*",
  'Access-Control-Allow-Headers': 'Authorization, x-client-info, apikey, Content-Type',
  'Access-Control-Allow-Methods': 'POST, GET, OPTIONS, PUT, DELETE',
}

// Supabase Edge Function to sync new users with Permit.io
Deno.serve(async (req) => {

   const permit = new Permit({
    token: Deno.env.get("PERMIT_API_KEY"),
    pdp: "<https://real-time-polling-app-production.up.railway.app>",
   });
  
  try {
    const { event, user } = await req.json();

    // Only proceed if the event type is "SIGNED_UP"
    if (event === "SIGNED_UP" && user) {
      const newUser = {
        key: user.id,
        email: user.email,
        name: user.user_metadata?.name || "Someone",
      };

      // Sync the user to Permit.io
      await permit.api.createUser(newUser);
      await permit.api.assignRole({
        role: "authenticated",
        tenant: "default",
        user: user.id,
      });

      console.log(`User ${user.email} synced to Permit.io successfully.`);
    }

    // Return success response
    return new Response(
      JSON.stringify({ message: "User synced successfully!" }),
      { status: 200, headers: corsHeaders },
    );
  } catch (error) {
    console.error("Error syncing user to Permit: ", error);
    return new Response(
      JSON.stringify({
        message: "Error syncing user to Permit.",
        "error": error
      }),
      { status: 500, headers: { "Content-Type": "application/json" } },
    );
  }
});

مصنوعات کی تعمیر کا طریقہ (updateCreatorRole.ts) کے

ایک بار جب ایک صارف نے ایک سروے تخلیق کی ہے تو، اس تقریب کو کہا جاتا ہے:

    کے
  • ایک نیا Permit.io وسائل انٹرفیس کے طور پر سروے کو سائن اپ کریں
  • کے
  • ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪:‬‬ ‫‪
  • کے

چیک کریں (checkPermission.ts)

اس کا مطلب یہ ہے کہ اس کا مطلب یہ ہے کہ اس کا استعمال کرتے ہوئے کسی بھی صارف کو اس کا استعمال کرنے کی اجازت دی جاتی ہے (create،read،update،deleteایک خاص سوال میں


import "jsr:@supabase/functions-js/edge-runtime.d.ts";
import { Permit } from "npm:permitio";

const corsHeaders = {
  "Access-Control-Allow-Origin": "*",
  "Access-Control-Allow-Headers":
    "Authorization, x-client-info, apikey, Content-Type",
  "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE",
};

Deno.serve(async req => {
  const permit = new Permit({
    token: Deno.env.get("PERMIT_API_KEY"),
    pdp: "<https://real-time-polling-app-production.up.railway.app>",
  });

  try {
    const { userId, operation, key } = await req.json();

    // Validate input parameters
    if (!userId || !operation || !key) {
      return new Response(
        JSON.stringify({ error: "Missing required parameters." }),
        { status: 400, headers: { "Content-Type": "application/json" } }
      );
    }

    // Check permissions using Permit's ReBAC
    const permitted = await permit.check(userId, operation, {
      type: "polls",
      key,
      tenant: "default",
      // Include any additional attributes that Permit needs for relationship checking
      attributes: {
        createdBy: userId, // This will be used in Permit's policy rules
      },
    });

    return new Response(JSON.stringify({ permitted }), {
      status: 200,
      headers: corsHeaders,
    });
  } catch (error) {
    console.error("Error checking user permission: ", error);

    return new Response(
      JSON.stringify({
        message: "Error occurred while checking user permission.",
        error: error,
      }),
      { status: 500, headers: { "Content-Type": "application/json" } }
    );
  }
});

مقامی ٹیسٹ

مقامی طور پر افعال کا تجربہ کرنے کے لئے آپ کے Supabase ڈی وی سرور کو شروع کریں:

npx supabase start 
npx supabase functions serve

آپ اس کے بعد آپ کے افعال پر کلک کر سکتے ہیں:

<http://localhost:54321/functions/v1/><function-name>

مثال کے:

<http://localhost:54321/functions/v1/checkPermission>

UI میں لائسنس کی جانچ پڑتال

اب کہ ہم نے Permit.io کے ساتھ ہماری لائسنسنگ منطق تخلیق کی ہے اور Supabase Edge Functions کے ذریعے اسے ظاہر کیا ہے، یہ اپلی کیشن کے اجزاء میں ان چیکوں کو نافذ کرنے کا وقت ہے.


اس سیکشن میں، ہم ان افعال کو کال کرنے کے لئے اہم UI اجزاء کو اپ ڈیٹ کریں گے اور شرط سے صارفین کی کارروائیوں کو اجازت یا بلاک کریں گے جیسے ووٹنگ یا اجازت کی جانچ پڑتال پر مبنی سروے کا انتظام کریں گے.

ٹائپنگ.tsx: Creator Role Assign کے بعد Poll Creation

ٹائپنگ.tsx

ایک سروے تخلیق کرنے اور اسے Supabase میں ذخیرہ کرنے کے بعد، ہمupdateCreatorRoleکام کرنے کے لئے:

    کے
  • Sync the new poll as a resource in Permit.io

  • Assign the current user the creator role for that specific poll


    const handleSubmit = async (e: React.FormEvent) => {
      e.preventDefault();
    
      if (question.trim() && options.filter(opt => opt.trim()).length < 2) {
        setErrorMessage("Please provide a question and at least two options.");
        return;
      }
    
      try {
        // Create the poll
        const { data: poll, error: pollError } = await supabase
          .from("polls")
          .insert({
            question,
            expires_at: new Date(expiryDate).toISOString(),
            created_by: user?.id,
            creator_name: user?.user_metadata?.user_name,
          })
          .select()
          .single();
    
        if (pollError) {
          console.error("Error creating poll:", pollError);
          setErrorMessage(pollError.message);
          return;
        }
    
        // Create the options
        const { error: optionsError } = await supabase.from("options").insert(
          options
            .filter(opt => opt.trim())
            .map(text => ({
              poll_id: poll.id,
              text,
            }))
        );
    
        if (optionsError) {
          console.error("Error creating options:", optionsError);
          setErrorMessage(optionsError.message);
          return;
        }
    
        // Update the creator role in Permit.io
        const response = await fetch(
          "<http://127.0.0.1:54321/functions/v1//updateCreatorRole>",
          {
            method: "POST",
            headers: {
              "Content-Type": "application/json",
            },
            body: JSON.stringify({
              userId: user?.id,
              pollId: poll.id,
            }),
          }
        );
    
        const { success, error } = await response.json();
    
        if (!success) {
          console.error("Error updating creator role:", error);
          // Note: We don't set an error message here as the poll was still created successfully
        }
    
        setSuccessMessage("Poll created successfully!");
        handleCancel();
      } catch (error) {
        console.error("Error in poll creation process:", error);
        setErrorMessage("An unexpected error occurred while creating the poll.");
      }
    };
    
  • کے

ViewPoll.tsx: اجازت کی بنیاد پر ووٹنگ کی محدودیت

ایک صارف کو ایک سروے میں ووٹ کرنے کی اجازت دینے سے پہلے، ہمcheckPermissionاس بات کی تصدیق کرنے کے لئے کہ ان کے پاسcreateکی اجازت کے لئےvotesاس طرح ہم قواعد کو نافذ کرتے ہیں:“A creator cannot vote on their own poll.”


Check voting permission:


const [canVote, setCanVote] = useState(false);

useEffect(() => {
  const checkPermission = async () => {
    if (!user || !query.id) return;

    try {
      const response = await fetch("<http://127.0.0.1:54321/functions/v1/checkPermission>", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          userId: user.id,
          operation: "create",
          key: query.id,
        }),
      });

      const { permitted } = await response.json();
      setCanVote(permitted);
    } catch (error) {
      console.error("Error checking permission:", error);
      setCanVote(false);
    }
  };

  checkPermission();
}, [user, query.id]);


Disable vote buttons if user isn’t allowed:


<button
  onClick={() => handleVote(option.id)}
  disabled={!user || !canVote}}
  className="w-full text-left p-4 rounded-md hover:bg-slate-100 transition-colors disabled:opacity-50 disabled:cursor-not-allowed">
  {option.text}
</button>


Show a message if the user is not allowed to vote:


{user && !canVote && (
  <p className="mt-4 text-gray-600">You cannot vote on your own poll</p>
)}

PollCard.tsxControl Access to Edit/Delete کا استعمال کریں

ہم سائن اپ مینجمنٹ کارروائیوں کو بھی محدود کرتے ہیں (معدل کریں اور حذف کریں) اس بات کو چیک کرتے ہوئے کہ کیا صارف نےupdateیاdeleteاس درخواست کے لئے اجازت


Check management permissions:


const [canManagePoll, setCanManagePoll] = useState(false);

useEffect(() => {
  const checkPollPermissions = async () => {
    if (!user || !poll.id) return;

    try {
      // Check for both edit and delete permissions
      const [editResponse, deleteResponse] = await Promise.all([
        fetch("<http://127.0.0.1:54321/functions/v1/checkPermission>", {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify({
            userId: user.id,
            operation: "update",
            key: poll.id,
          }),
        }),
        fetch("/api/checkPermission", {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify({
            userId: user.id,
            operation: "delete",
            key: poll.id,
          }),
        }),
      ]);

      const [{ permitted: canEdit }, { permitted: canDelete }] =
        await Promise.all([editResponse.json(), deleteResponse.json()]);

      // User can manage poll if they have either edit or delete permission
      setCanManagePoll(canEdit || canDelete);
    } catch (error) {
      console.error("Error checking permissions:", error);
      setCanManagePoll(false);
    }
  };

  checkPollPermissions();
}, [user, poll.id]);


Conditionally show management buttons:


تبدیل کریں :

{user?.id === poll?.created_by && (


کے ساتھ:

{canManagePoll && (
  <div className="flex justify-start gap-4 mt-4">
    <button type="button" onClick={handleEdit}>
    </button>
    <button type="button" onClick={handleDelete}>
    </button>
  </div>
)}

انضمام کا تجربہ

ایک بار انضمام، آپ کو اپلی کیشن میں مندرجہ ذیل رویے دیکھنا چاہئے:

    کے
  • لاگ ان شدہ صارفین سروے کو دیکھ سکتے ہیں لیکن بات چیت نہیں کرسکتے
  • کے
  • تصدیق شدہ صارفین ان سروے پر ووٹ کر سکتے ہیں جو وہ پیدا نہیں کرتے ہیں
  • کے
  • تخلیق کار اپنے سروے پر ووٹ نہیں کرسکتے
  • کے
  • صرف تخلیق کاروں کو ان کے سروے میں ترمیم / حذف کے اختیارات دیکھیں

آپ کو براؤزر پر جانے کے ذریعے ایپلی کیشن کی تبدیلیوں کو دیکھنے کے قابل ہونا چاہئے. ہوم سکرین پر، صارفین کو موجودہ اور ماضی کے سروے کی فہرست دیکھی جا سکتی ہے، چاہے وہ لاگ ان کر رہے ہیں یا نہیں. تاہم، جب وہ ایک سروے پر کلک کرتے ہیں تو، وہ سروے کی تفصیلات کو دیکھنے یا اس پر ووٹ کرنے کے قابل نہیں ہوں گے.


ایک بار لاگ ان کرنے کے بعد، صارف نے سروے کی تفصیلات کو دیکھنے اور اس پر ووٹ کر سکتے ہیں. تاہم، اگر صارف نے سروے کا تخلیق کیا ہے تو، وہ اس پر ووٹ نہیں کرسکتے ہیں. وہ ایک پیغام دیکھیں گے کہ وہ اپنے سروے پر ووٹ نہیں کرسکتے ہیں.

نتیجہ

اس ٹیوٹوریل میں، ہم نے استعمال کرنے کے لئے کس طرح کا تجربہ کیاSupabase authentication and authorizationایک حقیقی دنیا میںNext.jsاپلی کیشن

ہم نے قائم کرنے سے شروع کیاSupabase Authلاگ ان اور رجسٹریشن کے لئے، راؤنڈ سطح سیکورٹی کے ساتھ ایک رسیلیٹ شیڈول بنائی گئی، اور ڈینمک لائسنسنگ منطق کا استعمال کرتے ہوئے شامل کیا گیاReBAC• مدد کے ساتھSupabase Edge Functionsاور APolicy Decision Point (PDP)ہم نے براہ راست frontend سے اجازت چیک کی.


ترکیب کے ذریعےSupabase Authانعطاف پذیر رسائی کنٹرول کے ساتھ، ہم کر سکتے ہیں:

    کے
  • ای میل اور پاس ورڈ کے ذریعے صارفین کی تصدیق
  • کے
  • ووٹنگ اور سروے کے انتظام کو مجاز صارفین کو محدود کریں
  • کے
  • تخلیق کاروں کو اپنے سروے پر ووٹ دینے سے روکنے
  • کے
  • اعداد و شمار کے ساتھ تعلقات کی بنیاد پر صارفوں کی کرداروں کا تعین اور تجزیہ


This setup gives you a scalable foundation for building apps that require both authentication and fine-grained authorization.

مزید پڑھیں

    کے
  • Permit.io ReBAC گائیڈ
  • کے
  • لائسنس + تصدیق فراہم کرنے والے
  • کے
  • Permit Elements: Role Management کے لئے Embedded UI
  • کے
  • اجازت کے ساتھ ڈیٹا فلٹرنگ
  • کے
  • Audit Logs


  • کے

کوئی سوالات ہیں؟ ہمارے ساتھ شامل رہیںSlack communityجہاں سینکڑوں ڈویلپرز تعمیر کر رہے ہیں اور اجازت کے بارے میں بات کر رہے ہیں.

Slack community

Trending Topics

blockchaincryptocurrencyhackernoon-top-storyprogrammingsoftware-developmenttechnologystartuphackernoon-booksBitcoinbooks