1,843 akhrin
1,843 akhrin

DIY Real-Time Polling App waxay ku qiyaasta Access iyo Permit.io

by Permit.io40m2025/04/16
Read on Terminal Reader

Aad u dheer; In la akhriyo

Taageerada dhismaha iyo dhismaha dhismaha iyo dhismaha dhismaha iyo dhismaha dhismaha, dhismaha dhismaha iyo dhismaha dhismaha, dhismaha dhismaha, dhismaha dhismaha, dhismaha dhismaha, dhismaha dhismaha, dhismaha dhismaha, dhismaha dhismaha, dhismaha dhismaha dhismaha, dhismaha dhismaha dhismaha, dhismaha dhismaha dhismaha, dhismaha dhismaha dhismaha, dhismaha dhismaha dhismaha, dhismaha dhismaha dhismaha, dhismaha dhismaha dhismaha, dhismaha dhismaha dhismaha, dhismaha dhismaha dhismaha, dhismaha dhismaha dhismaha.
featured image - DIY Real-Time Polling App waxay ku qiyaasta Access iyo Permit.io
Permit.io HackerNoon profile picture
0-item


HakuGabriel L. Manor


Supabase waxaa loo isticmaali karaa in ay u isticmaali karaa macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka macluumaadka.


Su'aalaha waxaa laga yaabaa in ay ku yaalaa in ay ku yaalaa in ay ku yaalaa in ay ku yaalaa in ay ku yaalaa in ay ku yaalaa in ay ku yaalaa in ay ku yaalaa.fine-grained permissionsMarkaas ka mid ah oo ku saabsanrelationships between users and dataMarkaas oo leh.


Ma rabtaa in aad u baahan tahay si ay u isticmaali karaa macluumaad ka mid ah macluumaadka iyo macluumaadka, si ay u isticmaali karaa macluumaadka.


Tutorials waxaa loo isticmaali karaa sida loo isticmaali karaaSupabase authentication and authorizationee aNext.jsadeegyada

Waxaan ku faraxsanaySupabase AuthLogin iyo Session Management waxaa loo isticmaali karaaauthorization rulesHakuReBAC (Relationship-Based Access Control) waa mid ka mid ahSida loo isticmaali karaaSupabase Edge Functionsiyo alocal Policy Decision Point (PDP)Haku


Ka dibna, aad u baahan tahay app-ka la xiriira-gaarka ah oo loo isticmaali karaa si ay u isticmaali karaa sida macluumaadka ah iyo macluumaadka la isticmaali karaa - iyo nidaamka dhismaha caadiga ah oo aad u isticmaali karaa sida app-ka aad u isticmaali karaa.

Sidaa waxa ay u baabuurta

Sida loo yaabaa, waxaa loo isticmaali karaa macluumaadka macluumaadka iyo macluumaadka.SupabaseiyoNext.jsMarkaas oo ka mid ah authentication iyo authorization in action.


Taageerada waxaa loo isticmaali karaa in la isticmaali karaa in la isticmaali karaa in la isticmaali karaa in la isticmaali karaa in la isticmaali karaa in la isticmaali karaa in la isticmaali karaa.Supabase Authlogin/signup iyo sida loo isticmaali karaaauthorization policiesWaxaad ka mid ah ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah.


Waxaan u isticmaali karaa macluumaadka ugu weyn ee Supabase-AuthHakuPostgresHakuRLSHakuRealtimeiyoEdge FunctionsQalabka ARelationship-Based Access Control (ReBAC)Qalabka waxaa laga yaqaan "per-user and per-resource access rules".

Haku Tech

    Haku
  • Supabase – Backend-as-a-service for database, authentication, real-time, iyo macluumaadka edge
  • Haku
  • Next.js – Framework Frontend ee loo soo saarka UI iyo API routes
  • Haku
  • Permit.io – (ka ReBAC) si ay u helo logic autorization via PDP
  • Haku
  • Supabase CLI – Si loo isticmaali karaa iyo si ay u isticmaali karaa Edge Functions in la soo saarka iyo wax soo saarka
  • Haku
HakuMarka: JSHaku.eeQalabka CLI

Qalabka

    Haku
  • Node.js waxaa la aasaasay
  • Haku
  • Qalabka Account
  • Haku
  • Nala soo xiriir
  • Haku
  • Ku saabsan React/Next.js
  • Haku
  • Shirkadda Repo
  • Haku

Ma rabtaa in la isticmaalo app?

Dhismaha dhismaha waa mid ka mid ah mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah.


    Haku
  • Ma rabtaa in la soo xiriir in la soo xiriir oo la soo xiriir.
  • Haku
  • Waayo, waxaa laga yaabaa in la soo bandhigiisa in la soo bandhigiisa in la soo bandhigiisa in la soo bandhigiisa.
  • Haku
  • Waxaa la heli karaa in ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah.
  • Haku
  • Waayo, sidoo kale waxaa loo isticmaali karaa in aad u isticmaali karaa in aad isticmaali karaa.
  • Haku

Qalabka Tutorial

Waxaad ka mid ah ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah.


    Haku
  1. Set up Supabase project, schema, auth, and RLS
  2. Haku
  3. Qalabka dhismaha iyo dhismaha iyo dhismaha
  4. Haku
  5. Shuruudaha dhismaha model oo ku yaalaa roles iyo shuruudaha in Permit.io
  6. Haku
  7. Shuruudaha dhismaha iyo dhismaha dhismaha iyo dhismaha
  8. Haku
  9. Shuruudaha dhismaha ah ee macluumaadka macluumaadka iyo macluumaadka macluumaadka
  10. Haku


Waayo, waxaan bixiyaan -

Setting up Supabase in the Project

Shuruudaha ugu horeysay ee loo yaqaan "Supabase" ee Project

Ku saabsan Clone the Starter Template

Waxaan ka mid ahaysaa aQalabka TempleHakuGitHubiyo codka oo dhan oo aad u baahan tahay in ay ku faraxsanay Supabase iyo Permit.io.


Waxaad ka mid ah u baahan tahay in ay ka mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ka mid ah.


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


Ka dib markii aad cloney Project, navigate to the project directory and install the dependencies:


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

Shirkadda cusub ee Supabase

Sida loo helo:

    Haku
  • Waayo, waxaa laga yaqaan https://supabase.com oo ka soo xiriir ama loo helo account.
  • Click "Project New" iyo soo dejisan in loo yaqaan Project Name, Password, iyo Region.
  • Haku
  • Sida loo isticmaalo, go'aanshaha Project Settings → API iyo ku saabsan URL-ka Project iyo Anon Key - aad u baahan tahay in ka hor.
  • Haku

Qalabka dhismaha iyo dhismaha dhismaha ee Supabase

Waxaan isticmaali karaa email/password auth ee Supabase:

    Haku
  • Waayo, waxaa laga yaqaan Authentication → Providers.
  • Haku
  • Ku saabsan Email Provider
  • Haku
  • (Qalabka) Waayo, waxaa loo isticmaali karaa in ay ka mid ah wax soo saarka iyo wax soo saarka.
  • Haku

Qalabka dhismaha database

Taageerada waxaa loo isticmaali karaa 3 tababarka ugu weyn:pollsHakuoptionsiyovotesMarka loo isticmaaliSQL EditorKu saabsan dhismaha dhismaha dhismaha dhismaha dhismaha dhismaha dhismaha dhismaha dhismaha


-- 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)
);

Shuruudaha Role Level Security (RLS)

Enable QEEBESida loo yaqaan 'Politics' waxaa laga yaqaan 'Politics':

-- 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()
        )
    );


Sida loo isticmaali karaa macluumaadka real-time ee Supabase:

  • Sida loo yaqaan 'Table Editor'
  • Haku
  • Waayo, waxaa laga yaabaa in ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ah mid ka mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah.
  • Haku

Soo dejisan Email Authentication ee App

Marka aad u baahan tahay in aad u baahan tahay in aad u baahan tahay in aad u baahan tahay in aad u baahan tahay in aad u baahan tahay in aad u baahan tahay in aad u baahan tahay in aad u baahan tahay in aad u baahan tahay in aad u baahan tahay in aad u baahan tahay in aad u baahan tahay in aad u baahan tahay in aad u baahan tahay in aad u baahan tahay in aad u baahan yahay in aad u baahan yahay in aad u baahan yahay in aad u baahan yahay in aad u baahan yahay in aad u baahan yahay in aad u baahan yahay in aad u baahan yahay in aad u baahan yahay in aad u baahan yahay in aad u baahan yahay in aad u baahan yahay in aad u baahan yahay in aad u baahan yahay in aad u baahan yahay in aad u baahan yahay in aad u baahan yahay..env.localHaku:

NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_anon_key


Waqtiga login aad si ay u soo saarka iyo login via email / password:


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;


Sida loo isticmaali karaa Supabase'ssignInWithPasswordSida loo isticmaali karaa user iyosignUpka mid ah si ay u isticmaali karaa user cusub ee email iyo password. We are also storing the user's name inuser_nameNala soo xiriir Metadata user.


Waxaad sidoo kale isticmaali karaasupabase.auth.signOut()Waayo, waxaa loo isticmaali karaa in la isticmaali karaa in la isticmaali karaa.


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;


Sidaa waxaa loo isticmaali karaasignOutnidaamka oo ka mid ah Supabase si ay u hesho user iyo si ay u mid ah home page.

Qalabka dhismaha iyo dhismaha dhismaha iyo dhismaha

Shuruudaha ugu horeysay ee shuruudaha ugu horeysay ee shuruudaha ugu horeysay ee shuruudaha ugu horeysay ee shuruudaha ugu horeysay ee shuruudaha ugu horeysay ee shuruudaha ugu horeysay ee shuruudaha ugu horeysay ee shuruudaha ugu horeysay ee shuruudaha ugu horeysay ee shuruudaha ugu horeysay ee shuruudaha ugu horeysay ee shuruudaha ugu horeysay ee shuruudaha ugu horeysay ee shuruudaha ugu horeysay ee shuruudaha ugu horeysay ee shuruudaha ugu horeysay ee shuruudaha ugu horeysay ee shuruudaha.


  • Show/hide elements UI sida login/logout buttons
  • Haku
  • Shuruudaha dhismaha iyo dhismaha iyo dhismaha iyo dhismaha
  • Haku
  • Ensure only authenticated users can perform restricted actions
  • Haku


Waxaan u isticmaali karaasupabase.auth.onAuthStateChange() to listen to these events and update the app accordingly.


In theHakuLayout.tsxHakufile: 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;

Waayo, waxaa laga yaabaa in la soo bandhigay.

Sidaas sidapoll detailsMarkapoll managementWaxaad ka mid ka mid ah in la soo bandhigay in la soo bandhigay in la soo bandhigay in la soo bandhigay in la soo bandhigay.


Sidaa waxaa loo heli karaa inpages/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;


Sida loo isticmaali karaa inpages/polls/manage.tsx, oo isticmaalka waa in la soo xiriir oo ka mid ah wax soo saarka:


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;


These patterns ensure your UI reflects the user’s current authentication status and form the basis for the authorization checks we'll add later. For example, you’ll later use this user object when calling the checkPermissionShuruudaha Edge waa in ay u baahan tahay in ay isticmaali karaa in la heli karaa ama in la isticmaali karaa in la isticmaali karaa in la isticmaali karaa.

Qalabka Qalabka Polling

With Supabase configured and authentication working, we can now build the core functionality of the polling app. In this section, we’ll cover:


    Haku
  • Qalabka cusub
  • Qalabka dhismaha iyo dhismaha dhismaha iyo dhismaha dhismaha
  • Haku
  • Sida loo isticmaali karaa nidaamka dhismaha
  • Haku


Waxaad ku dhigi karaa in ay ku dhigi karaa in ay ka mid ah wax soo saarka ah oo ka mid ah wax soo saarka ah.

Nala soo xiriir

Users must be logged in to create polls. Each poll includes a question, an expiration date, and a set of options. We also record who created the poll so we can later use that relationship for access control.


Inside NewPoll.tsxShuruudaha dhismaha iyo dhismaha dhismaha iyo dhismaha dhismaha iyo dhismaha


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;

Waayo, waxaan ka dibna soo xiriir Function Edge ee loo yaqaan "creator" ee Permit.io.

Shuruudaha iyo wax soo saarka

Qalabka waxaa laga yaabaa inactive(wax ka mid ah) iyopast (expired). You can fetch them using Supabase queries filtered by the current timestamp, and set up real-time subscriptions to reflect changes instantly.


Example from pages/index.tsxHaku:


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 (
    ...
  );
}

Viewing and Managing User Polls

Sida loo yaabaa, waxaa loo yaabaa in ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah.pollsWaxaan sidoo kale ku habboonay in ay ku habboonay in ay ku habboonay in ay ku habboonay in ay ku habboonaypolls 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.


Update the pages/manage.tsx page to fetch and display only polls created by the user:


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;


Sidaa, waxaan ka mid ah ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah.pollsTaageerada waxaa laga yaabaa in la soo xiriir in ay ku saabsan macluumaadka macluumaadka macluumaadka.


Sida loo updatePollCard component so that if a logged-in user is the poll creator, icons for editing and deleting the poll will be displayed to them on the poll.


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;


Sida loo yaabaa, waxaa loo yaabaa in ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ah mid ka mid ah mid ka mid ah mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ah mid ka mid ah mid ka mid ah mid ka mid ah.

Sida loo isticmaalo nidaamka Poll Voting

The voting logic enforces:

    Haku
  • Only one vote per user per poll
  • Haku
  • Creators cannot vote on their own polls
  • Haku
  • Haku waxay ku salaysan tababarka dhismaha
  • Haku
  • Results are displayed and updated in real time
  • Haku


Sida loo isticmaali karaa in ay loo isticmaali karaaViewPoll.tsxHaku:


Fetch the Logged-In UserWe need the current user’s ID to determine voting eligibility and record their vote.


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 StatusOnce we have the user, we fetch:

    Haku
  • Qalabka dhismaha (ka mid ka mid ka mid ka mid ka mid ka mid ka mid ka mid ah)
  • Haku
  • Whether this user has already voted
  • Haku


Waxaan sidoo kale soo xiriir in uu ku saabsan updates real-time.


  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

Waayo, waxaan ka soo bandhigay in ay ka mid ah wax soo saarka.votes table, scoped to this poll. When a new vote is cast, we fetch updated poll data and voting status.


    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 user has not voted and is allowed to vote (we’ll add a permission check later), we’ll insert his 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 ResultsWaayo, waxaa loo isticmaali karaa in ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah.


  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;


Sida loo isticmaali karaa, nidaamka ka mid ah nidaamka ka mid ah nidaamka ka mid ah nidaamka ka mid ah nidaamka ka mid ah nidaamka ka mid ah nidaamka ka mid ah nidaamka ka mid ah.authorization checksHakuPermit.io and Supabase Edge FunctionsWaayo, waxaa loo yaabaa in la taabto.


Before we do that, let’s first look at the type of authorization layer we are going to implement.

Understanding ReBAC (Relationship-Based Access Control)

Su'aalaha dhismaha iyo dhismaha baska ah ee kala duwan oo ka mid ah dhismaha iyo dhismaha iyo dhismaha.

    Haku
  • Shuruudaha waxaa laga yaabaa in la soo bandhigiisa in la soo bandhigiisa.
  • Haku
  • Assigning per-resource roles (like “creator” for a specific poll)
  • Haku
  • Managing access via external policies
  • Haku


Waayo, waxaa loo yaqaan 'Relationship-based permissions', waxaan u isticmaali karaa ReBAC iyo Permit.io.


ReBAC (Relationship-Based Access Control) waa mid ka mid ahReBAC waa mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ah mid ka mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah.

ReBAC (Relationship-Based Access Control) waa mid ka mid ah


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

    Haku
  • A user who created a poll is the only one who can manage (edit/delete) it
  • Waxaa la heli karaa in la soo bandhigiisa.
  • Haku
  • Muuqaalka macaamiisha waxaa laga heli karaa 1 toddobaad per 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.


Ma rabtaa in uu ku saabsan ReBAC, check outHaku.io oo ku saabsan ReBACHaku

Qalabka Access Control

Sida loo isticmaali karaa app, waxaan loo isticmaali karaa:

  • Sida loo yaabaa in ay ka mid ah mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah.
  • Dhammaan waxaa laga yaabaa in ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid
  • Haku

Nala soo xiriir Permit.io

Waayo, sidoo kale waxaa laga yaabaa in la soo saarka model autorization ee Permit.

    Haku
  • Shirkadda cusub ee Permit.io Name it something like supabase-polling
  • Haku
  • Waayo, waxaa loo isticmaali karaa in ay ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ah mid ka mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah.
  • Haku
  • ReBAC waxaa laga yaqaan "ReBAC Options" oo loo yaqaan "Role creator authenticated".
Nala soo xiriir

Navigate to the "Roles" tab to view the roles from the resources we just created. Note that Permit created the default roles (adminHakueditor, user) that are unnecessary for this tutorial.


    Haku
  • Shuruudaha dhismaha Access Go to Policy → Policies Use the visual matrix to define: authenticated can read and create polls creator can read, update, and delete polls (Optional) Waxaad loo isticmaali karaa xisaabooyinka dhismaha sida ka mid ah this ama via a resource second if you model votes separately
  • Haku
  • Add resource instances Go to Directory → Instances Add individual poll IDs as resource instances (wax yar u isticmaali karaa in uu ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ah mid ka mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ah mid
  • Haku

Dhismaha ugu fiican ee loo isticmaali karaa waa in la isticmaali karaa si ay u isticmaali karaa in ay u isticmaali karaa.


Sida loo yaabaa in ay ka mid ah wax soo saarka ugu horeysay ee dhismaha Permit, si loo isticmaali karaa in our application. Next, we will connectHaku.ee to our Supabase project via Edge Functions that:

    Haku
  • Shiinaha user
  • Haku
  • Shuruudaha Creator
  • Haku
  • Qalabka Access on Demand

Setting up Permit in the Polling Application

Dhammaan waxaa loo isticmaali karaa in ka mid ah macluumaadka, laakiin waxaan loo isticmaali karaa Container PDP for this tutorial.You must host the container online to access it in Supabase Edge functions.You can use services such asHaku: RailwaySida loo soo saarka, aad u soo saarka url for your container.


Waayo, waxaa laga yaabaa in ay ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ah mid ka mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah.


Soo dejisan Supabase Edge Function API for Authorization

Supabase Edge FunctionsWaayo, waxaa loo isticmaali karaa in la isticmaali karaa adeegga ReBAC oo ka mid ah loo isticmaali karaa si ay u isticmaali karaa si ay u isticmaali karaa si ay u isticmaali karaa si ay u isticmaali karaa.

Create Functions in Supabase

Initialise Supabase in your project and create three different functions using the 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

This will create a functionsFollower eesupabaseMarka aad u baahan tahay in aad u baahan tahay in aad u baahan tahay in aad u baahan tahay in aad u baahan tahay in aad u baahan tahay in aad u baahan tahay in aad u baahan tahay in aad u baahan tahay in aad u baahan tahay in aad u baahan tahay in aad u baahan tahay in aad u baahan tahay.

Syncing Users to Permit.io on Signup (syncUser.tsQEEBE

This function listens for Supabase’s SIGNED_UPXisaabinta auth.Wala soo bandhigay user cusub, waxaan soo bandhigi karaa identity-ga Permit.io iyo soo bandhigiisa default.authenticated role.


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" } },
    );
  }
});

Qalabka Qalabka Qalabka Qalabka Qalabka (updateCreatorRole.ts)

Ka dib markii isticmaalka loo loo soo saarka, function this is called to:

    Haku
  • Qalabka dhismaha iyo dhismaha dhismaha iyo dhismaha
  • Shuruudaha ugu horeysay ee ay ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah
  • Haku

Qalabka Qalabka (checkPermission.tsQEEBE

Marka aad u baahan tahay in aad u baahan tahay in aad u baahan tahay in aad u isticmaali karaa (create, read, updateHakudelete(Haddii loo yaqaan 'Poll' waa mid ka mid ah wax soo saarka.


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" } }
    );
  }
});

Qalabka Local

Start your Supabase dev server to test the functions locally:

npx supabase start 
npx supabase functions serve

Waxaad ka mid ah u shaqeeyaan:

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

Haku:

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

Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka

Tani oo aan loo isticmaali karaa logic autorization ee Permit.io iyo loo isticmaali karaa via Supabase Edge Functions, waxaa laga yaabaa in la isticmaali karaa wax soo saarka ah ee app.


In this section, waxaan soo dejiso components UI key si ay u soo xiriir macluumaadka iyo si ay u isticmaali karaa ama si ay u isticmaali karaa macluumaadka user sida si ay u heli karaa ama si ay u isticmaali karaa macluumaadka.

NewPoll.tsxRole Creator (Role Creator) ka dib markii loo helo

NewPoll.tsx

After creating a poll and saving it to Supabase, we call the updateCreatorRoleQalabka 2:

    Haku
  • Sida loo yaqaan 'Poll' waa mid ka mid ah 'Permit.io'.
  • Haku
  • Ma rabtaa in aad Cudarada in aad Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada

ViewPoll.tsx: Waayo, waxaa laga yaabaa in la soo bandhigay in la soo bandhigay

Ka dib markii loo isticmaali karaa in la soo bandhigiisa, waxaan la soo bandhigiisacheckPermissionQalabka waa in ay u heshocreateQalabka QalabkavotesHaku: Sida loo isticmaali karaa loo isticmaali karaa:“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.tsx: Control Access si aad u soo saarka Edit/Delete

Waxaan sidoo kale ku raaxo xanuunka xanuunka xanuunka (xanuunka iyo xanuunka) by checking if user has theupdateMarkadeleteQiyaasta oo ku saabsan this poll.


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:


Haku:

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


Marka:

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

Testing the Integration

Sida loo isticmaali karaa, sidoo kale loo isticmaali karaa in la isticmaali karaa in la isticmaali karaa in la isticmaali karaa.

    Haku
  • Waayo, waxaa loo isticmaali karaa mid ka mid ah macluumaadka iyo mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah.
  • Haku
  • Waayo, waxaa laga yaabaa in la soo bandhigiisa in la soo bandhigiisa in la soo bandhigiisa.
  • Haku
  • Waayo, waxaa lagu soo bandhigay in la soo bandhigay.
  • Only creators see edit/delete options on their polls.
  • Haku

Ma rabtaa in aad si aad u aragto wax soo saarka ah oo aad u aragto in aad u aragto in aad u aragto in aad u aragto.


Marka aad u isticmaali kartaa in aad u isticmaali kartaa in aad u isticmaali kartaa in aad isticmaali kartaa in aad isticmaali kartaa in aad isticmaali kartaa in aad isticmaali kartaa in aad isticmaali kartaa in aad isticmaali kartaa in aad isticmaali kartaa in aad isticmaali kartaa in aad isticmaali kartaa in aad isticmaali kartaa in aad isticmaali kartaa in aad isticmaali kartaa in aad isticmaali karaa.

Qalabka

In this tutorial, waxaan ka heli karaa sida loo isticmaali karaaSupabase authentication and authorizationWaayo, waxaa loo yaqaan 'real world'Next.jsadeegyada

Waayo, waxaan ka soo bandhigaySupabase AuthWaayo, waxaa loo yaqaan 'Relational Scheme' iyo 'Row Level Security' iyo 'Dynamic Authorization Logic'.ReBACSida loo isticmaali karaaSupabase Edge Functionsiyo aPolicy Decision Point (PDP)Markaas oo ka mid ah wax soo saarka ah, waxaan ka mid ah wax soo saarka iyo wax soo saarka iyo wax soo saarka.


Sida loo isticmaali karaaSupabase AuthSida loo isticmaali karaa qalabka flexible, waxaan noqon doonaa:

    Haku
  • Waayo, waxaa loo isticmaali karaa in ay u isticmaali karaa email iyo password.
  • Shuruudaha dhismaha iyo shuruudaha dhismaha ka mid ah macaamiisha
  • Haku
  • Waayo, waxaa loo yaabaa in la soo bandhigiisa in la soo bandhigiisa in la soo bandhigiisa.
  • Haku
  • Assign and evaluate user roles based on relationships to data
  • Haku


Sida loo yaabaa, waxaa laga yaabaa in ay ka mid ah wax soo saarka iyo wax soo saarka, oo ka mid ah wax soo saarka iyo wax soo saarka.

Qalabka

    Haku
  • Haku: ReBAC Guide
  • Haku
  • Shuruudaha Qalabka + Authentication
  • Haku
  • Shuruudaha Xirfadiga: Xirfadiga Xirfadiga Xirfadiga
  • Haku
  • Filter dhismaha
  • Haku
  • Qalabka
  • Haku

Ma rabtaa wax soo saarka?Slack community, oo hundred ka mid ah shuruudaha waa la aasaasay iyo dib u hesho autorization.

Slack community

Trending Topics

blockchaincryptocurrencyhackernoon-top-storyprogrammingsoftware-developmenttechnologystartuphackernoon-booksBitcoinbooks