Taariikh cusub

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


By Gabriel L. Manor

Gabriel L. Manor


Supabase waxaa loo isticmaali karaa in la isticmaali karaa adeegyada app-ka iyo in la isticmaali karaa email, OAuth, iyo link magic.


Supabase waxaa loo isticmaali kartaa backend-ka ugu fiican oo la isticmaali karaa Auth iyo Row Level Security (RLS), xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka xanuunka.

wax yar oo dhanxisaabinta kala duwan ee user iyo data


Saacadda aad u baahan tahay si ay u qiyaastii wax soo saarka ama si ay u qiyaastii wax soo saarka, si ay u qiyaastii wax soo saarka, ama si ay u qiyaastii wax soo saarka.


Dhulka this waxaa laga yaabaa sida loo helo Supabase authentication iyo authorization ee Next.js app.

Supabase authentication iyo kharashkaDiiwaanka.js

We'll start with Supabase Auth for login and session management, then add authorization rules using Relationship-Based Access Control (ReBAC), enforced through Supabase Edge Functions and a local Policy Decision Point (PDP).

Supabase Qalabkawax yar oo dhanRelationship-Based Access Control (ReBAC)Supabase Edge Functions Local Policy Decision Point (PDP)


Waqtiga, sidoo kale waxaa laga yaabaa app-ka ah oo loo isticmaali karaa in la isticmaali karaa oo la isticmaali karaa oo la isticmaali karaa oo la isticmaali karaa oo la isticmaali karaa oo la isticmaali karaa.

What We’re Building

In dhismaha this, waxaan soo saarka app qiyaasta real-time oo loo isticmaalo Supabase iyo Next.js oo ku soo bandhigay sida xisaabinta iyo xisaabinta in xisaabinta.

Luuqadda Diiwaanka.js


The app wuxuu ku yaalaa in ay isticmaali karaa si ay u loo soo saarka macluumaadka, si ay u heli karaa dadka kale, iyo si ay u isticmaali karaa content ka badan. It demonstrates how to implement Supabase Auth for login/signup and how to enforce authorization policies that control who can vote, edit, or delete.

Supabase Qalabkawax yar oo dhan


We will use Supabase's core features—Auth, Postgres, RLS, Realtime, iyo Edge Functions—combinada iyo model Relationship-Based Access Control (ReBAC)

to enforce per-user and per-resource access rules.


Auth waxaa laga yaabaaDiiwaankaMarka: RLSWaqtiga ahFunctionada ugu badanRelationship-Based Access Control (ReBAC)

Sidaalka Tech

  • Supabase – Backend-as-a-service for database, authentication, realtime, and edge functions
  • Next.js – Frontend framework for building the app UI and API routes
  • Permit.io – (for ReBAC) to define and evaluate authorization logic via PDP
  • Supabase CLI – To manage and deploy Edge Functions locally and in production
  • Supabase – Backend-as-a-service for database, authentication, realtime, and edge functions
  • SupabaseSupabase
  • Next.js – Frontend framework for building the app UI and API routes
  • Next.jsNext.js
  • Permit.io – (for ReBAC) to define and evaluate authorization logic via PDP
  • Permit.ioPermit.io
  • Supabase CLI – To manage and deploy Edge Functions locally and in production
  • Supabase CLISupabase CLI

    Qalabka ugu horeysay

  • Node.js waxaa laga yaabaa
  • Supabase account
  • Permit.io account
  • Permit.io
  • Diiwaanka React/Next.js
  • Starter project repo
  • Starter project repo

    Waa'iid ka mid ah loo isticmaali karaa?

    Demo app waa mid ka mid ah mid ah mid ka mid ah Next.js iyo Supabase, oo aad isticmaali kartaa mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid 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.


    • Dhammaan user (waxariisada ama ma ahaato) waa in ay u aragto list of public polls
    • Only authenticated users can create polls and vote
    • A user can not vote on a poll they created
    • Only the creator of a poll can edit or delete it
  • Dhammaan isticmaalka (wax yar oo dhan) waa in la soo xiriir la soo xiriir oo la soo xiriir
  • Waa'iid ka mid ah macaamiisha waxay ka heli karo oo ka mid ah ka mid ah oo ka mid ah oo ka mid ah oo ka mid ah oo ka mid ah oo ka mid ah
  • A user cannot vote on a poll they created
  • wax 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 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
  • Only the creator of a poll can edit or delete it
  • CREATOR OF A POLL

    Tutorial Ujeedada

    Waa soo xiriir oo dhan:


    1. Ganacsiga Supabase project, schema, auth, and RLS
    2. Build core app features sida loo soo saarka iyo dhismaha
    3. Rules model authorization define roles and rules in Permit.io
    4. Create Supabase Edge Functions for syncing users, allocating roles, and checking permissions
    5. Enforce policies in frontend app using those edge functions
  • Supabase Setup Project, Schema, auth, iyo RLS
  • Waaq u soo xiriir
  • Build core app features sida loo soo saarka si loo helo
  • Build key app features
  • Riixada dhismaha model loo yaqaan 'roles and rules' ee Permit.io
  • Nadiifinta dhismaha model
  • Create Supabase Edge Functions for syncing users, shahaado roles, iyo shahaado macaamiisha
  • Create Functions Calaamadda Calaamadda
  • Diiwaanka ugu fiican ee macluumaadka ee macluumaadka macluumaadka iyo macluumaadkaDiiwaanka ugu weyn


    Let’s get started -

    Waqtiisa waxaa loo yaqaan 'Supabase in the Project'

    Waqtiisa waxaa loo yaqaan "Supabase" ee Project

    Qalabka: Clone template Starter

    I've already created a starter template on GitHub with all the code you need to start so we can focus on implementing Supabase and Permit.io.

    starter templateGitHub waxaa laga yaabaa


    Saacadda waxaa loo isticmaali karaa in ay ku xiran tahay:


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


    Saacad ka hortiisa Project, navigate to the project directory and install the dependencies:


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

    Waaq u shaqeeyaan Project in Supabase

    Waqtiga ugu horeysay:

    • Go to https://supabase.com and sign in or create an account.

    • Click "New Project" and fill in your project name, password, and region.

    • Once created, go to Project Settings → API and note your Project URL and Anon Key — you’ll need them later.


  • Go to https://supabase.com and sign in or create an account.

  • Go to https://supabase.com and sign in or create an account.

    https://supabase.com
  • Click "Project New" iyo ku xiran tahay xisaabinta, password, iyo region.

  • Click "Project New" iyo ku yaalid ku saabsan name of your project, password, and region.

    "Nooqada cusub"
  • Waaq ka mid ah loo isticmaalo, ka mid ah Project Settings → API oo ka mid ah Project URL iyo Anon Key - aad u baahan yahay ka hor.


  • Koo loo soo saarka, ka mid ah Project Settings → API oo ka mid ah Project URL iyo Anon Key - aad u baahan yahay ka hor.

    Project Settings → APIWaraaqaha URLAnon Key


    Coolka dhismaha iyo Database in Supabase

    We will use Supabase’s built-in email/password auth:

    Waayo, waxaa laga yaabaa in 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 ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ka mid ah.
  • Waaq ka mid ah Authentication → Providers

  • Waaq ka mid ah Authentication → Providers

    Diiwaanka → Waqtiga
  • Waax yar Email oo ka soo xiriir

  • Waax yar Email oo ka soo saarka

    Tusaale : Tusaale : Tusaale : Tusaale : Tusaale : Tusaale : Tusaale
  • (Optional) Waayo, waxaa loo isticmaali karaa in la isticmaali karaa in la isticmaali karaa in la isticmaali karaa.


  • (Optional) Waayo, waxaa loo isticmaali karaa in aad u isticmaali karaa in aad u isticmaali karaa in aad isticmaali karaa in aad isticmaali karaa


    Shiqaalka dhismaha database

    Araacada waxaa loo isticmaali karaa 3 tababarka ugu weyn: polls, options, iyo votes.pollsoptionsvotesSql Editor waxaa laga yaabaa


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

    Row Level Security (RLS)

    Enable RLS for each table and define policies:

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


    Saacadda loo isticmaali karaa macluumaadka real-time ee Supabase:

    • In the sidebar, go to Table Editor


    • For each of the three tables (polls, options, votes):

      • Click the three dots → Edit Table

      • Toggle "Enable Realtime"

      • Save changes


  • In the sidebar, go to Table Editor


  • Waqtiisa waxaa ka mid ah Table Editor

    Table Editor waxaa laga yaabaa


  • For each of the three tables (polls, options, votes):

    • Click the three dots → Edit Table

    • Toggle "Enable Realtime"

    • Save changes


  • Waaq ka mid ah 3 tababarka (polls, options, votes):

    pollsoptionsvotes
    • Click the three dots → Edit Table

    • Toggle "Enable Realtime"

    • Save changes


  • Click the three dots → Edit Table

  • Click the three dots → Edit Table

    Waaqada Tababarka
  • Toggle "Waax yar"

  • Toggle "Waqtiga ah"

    "Diiwaanka Realtime"
  • Save changes


  • Waqtiisa waxaa laga yaabaa


    Diiwaanka Supabase Email Authentication ee App

    In this demo app, dadka waa in aad u aragto list of polls available on the app, both active and expired. To view the details of a poll, manage, or vote on any poll, user must be logged in. We will be using email and password as means of authentication for this project. In your Next.js project, guuley your Supabase credentials in .env.local:

    .env.local
    NEXT_PUBLIC_SUPABASE_URL=your_supabase_url NEXT_PUBLIC_SUPABASE_ANON_KEY=your_anon_key 
    NEXT_PUBLIC_SUPABASE_URL=your_supabase_url NEXT_PUBLIC_SUPABASE_ANON_KEY=your_anon_key


    Waaq u soo xiriir in aad login iyo login via email / password:


    Waayo, sidoo kale waxaa laga yaabaa in 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 ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid 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 ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka midimport { 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;


    In this, waxaan u isticmaali signInWithPassword ka mid ah Supabase si loo isticmaali karaa user iyo signUp ka mid ah in la isticmaali karaa user cusub ee email iyo password. We are also storing the user's name in the user_name field in user's metadata.

    signInWithPasswordsignUpuser_name


    Anda sidoo kale loo isticmaali supabase.auth.signOut() si loo isticmaali karaa users out iyo si ay u isticmaali karaa:

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


    Waa soo isticmaali signOut ka mid ah Supabase si ay u hesho user iyo si ay u soo xiriir home page.

    signOut

    Listening for Changes in User's Authentication State

    Listening for changes in the user's authentication state waxay ka heli kartaa UI ku saabsan status authentication user.


    • Show/hide UI elements such as login/logout buttons
    • Conditionally restrict access to protected pages (like voting or managing polls)
    • Sure only authenticated users can perform restricted actions
  • Show/hide elements UI sida login/logout button
  • Conditionally restrict access to protected pages (like voting or managing polls)
  • Waqtigaan oo kaliya oo isticmaalka la isticmaalaa in la isticmaalaa oo la isticmaalaa oo la isticmaalaa oo la isticmaalaa

  • We will use supabase.auth.onAuthStateChange() to listen to these events and update the app accordingly.

    supabase.auth.onAuthStateChange()


    In the Layout.tsx file: Dhammaan Dhammaan Dhammaan

    In ka mid ahLayout.tsxfile: Track Auth State oo dhan


    Waayo, waxaa laga yaabaa in 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 ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid 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 ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka midimport 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

    Waqtiga sida Details Poll ama Poll management, waxaad sidoo kale ku qiyaasta in ay ku habboonayaa wax soo saarka ah in ay ku habboonayaa isticmaalka la isticmaalaa.

    Dhammaan oo dhanGanacsiga ugu fiican


    Haddii waa mid ka mid ah pages/polls/[id].tsx:

    pages/polls/[id].tsxWaayo, sidoo kale waxaa laga yaabaa in 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 ka mid ah 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 ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid 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 ka mid ah mid ka mid ah mid ka mid ah mid ah mid ka mid ah mid ka mid ah midimport { 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:

    pages/polls/manage.tsx


    Waayo, waxaa laga yaabaa in 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 ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid 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 ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka midimport { 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;


    Diiwaanka ugu badan waxaa laga yaabaa in aad UI oo ku yaalaa xawaaraha adeegga ah ee isticmaala iyo loo yaabaa xawaaraha adeegga ah oo ay ku yaalaa in ay ka mid ah 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 ka mid ah mid 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 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 ka midusercheckPermission

    Waaqaynta shaqada App Polling

    Waa soo xiriir Supabase iyo wax soo saarka authentication, sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale:


    • Waaqadaha cusub
    • Waaqadaha real-time
    • Waaqadaha cusub
  • Waax yar oo dhan
  • Diiwaanka iyo soo bandhigay si aad u soo bandhigay
  • Waqtiga loo isticmaali karaa

  • Diiwaanka waxaa loo yaqaan 'app' ah oo loo yaqaan 'app' ah oo loo yaqaan 'app' ah oo loo yaqaan 'app' ah.

    Waaq u soo xiriir

    Wala soo xiriir in la soo xiriir in la soo xiriir in la soo xiriir in la soo xiriir in la soo xiriir in la soo xiriir in la soo xiriir in la soo xiriir in la soo xiriir in la soo xiriir

    Wala soo xiriir in la xiriir in la xiriir in la xiriir in la xiriir


    Dhabka NewPoll.tsx, ka mid ah loo isticmaali karaa, oo loo isticmaali karaa Supabase si ay u isticmaali karaa jilicsan iyo qiyaasadda:

    NewPoll.tsx


    Waayo, in aad Cudarada in aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aad Cudarada aadimport 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;

    We will later call a Edge Function here to assign the “creator” role in Permit.io.

    Diiwaanka iyo Diiwaanka Polls

    Polls waxaa laga yaabaa in active (wax yar) iyo past (wax yar). Waxaad ka heli karaa in la isticmaali karaa qiyaasadda Supabase oo ku yaalaa timestamp ah, oo ay ku yaalaa adeegga real-time in ay ku yaalaa qiyaasadda.

    Waayo, waxaa laga yaabaa in aad u baahan yahay in aad u baahan yahay.Xaabinta


    Diiwaanka of pages/index.tsx:

    pages/index.tsx


    Intixaanka waxaa laga yaabaa in 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 ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ahimport { 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 ( ... ); }

    Waqtiisa iyo Shuruudaha Shuruudaha user

    Waaq, waxaan ka mid ah 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 ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ka mid ka mid ah.

    pollspolls


    Sidaa pages/manage.tsx page si ay u qaadi karaa iyo u aragtiyo mid ka mid ah wax soo saarka isticmaalka:

    pages/manage.tsx


    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 ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka midimport { 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;


    Waaq, waxaan ka mid ah 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 ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid 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 ka mid ah.

    polls


    Waa'iid ka mid ah PollCard component in ay ka mid ka mid ah in la mid ah in la mid ah in la mid ah in la mid ah in la mid ah in la mid ah in la mid ah in la mid ah in la mid ah in la mid ah in la mid ah in la mid ah in la mid ah in la mid ah in la mid ah in la mid ah in la mid ah in la mid ah la mid ah in la mid ah in la mid ah in la mid ah in la mid ah.

    PollCard


    Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabkaimport { 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;


    Waa'iid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ka mid ah.

    Waqtiisa nidaamka Poll Vote

    Logic waxaa loo isticmaali karaa:

    • Only one vote per user per poll
    • Creators can't vote on their own polls
    • Votes waxaa ku salaysan votes table
    • Results waxaa loo soo saarka iyo si ay u adeegsan in real-time
  • Only one vote per user per poll
  • Creators waxay ka heli karaa in ka mid ah wax soo saarka ah
  • Votes waxaa laga yaqaan votes table
  • votes
  • Results waxaa loo isticmaali karaa oo loo isticmaali karaa in real-time

  • Let's break down how this works in the ViewPoll.tsx component:

    ViewPoll.tsx


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

    Fetch user-ka ah oo loo yaabaa


    Waayo, sidoo kale waxaa laga yaabaa in 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 ka mid ah 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 ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid 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 ka mid ah mid ka mid ah mid ka mid ah mid ah mid ka mid ah mid ka mid ah midimport { 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 StatusWala soo bandhigay user, waxaan ka heli:

    Load Poll Details iyo Check Voting Status
    • Qalabka ugu horeysay ee loo yaqaan 'Polling' (wax yar oo ku yaalaa options and votes counts)
    • Waax yar oo ku yaalaa
  • Qalabka dhismaha (ka mid ka mid ka mid ka mid ka mid ka mid ka mid ka mid ka mid ka mid)
  • Waax yar oo ka mid ah loo heli karaa

  • Waa soo xiriir oo dhan oo ka mid ah wax soo saarka real-time.


    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 ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid 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

    Listen for Real-time Updates

    Waa soo xiriir oo ka mid ah macluumaadka ee tababarka votes, si ay u hesho this poll.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]); 
    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]);


    Waqtiisa waxaa laga yaabaa in la soo xiriir

    Waqtiisa waxaa laga yaabaa in la soo xiriir

    If user has not voted and is allowed to vote (we will add a permit check later), we insert their vote.


     const handleVote = async (optionId: string) => { if (!user) return; try { const { error } = wait 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); }; 
    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); } };


    Show Results of PollsWaa soo qiyaastii qiyaastii dhismaha iyo qiyaastii ka mid ah waqti dhismaha.

    Show the Poll Results


     if (!pollannoo-pollLoadingannoo-pollo voteLoading) return <div>Loading...</div> // 6. xisaabinta xisaabinta totalVotes = xisaabinta TotalVotes(poll.options); xisaabinta countdown = getCountdown(poll.expires_at); xisaabinta ( ... ); }; export default ViewPoll; 
    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;


    Wala soo saarka ugu horeysay ee loo yaabaa, nidaamka lagu soo saarka waxaa laga yaqaan 'Prompt.io' iyo Supabase Edge Functions waxaa loo isticmaali karaa.

    Wala soo saarka waxaa laga yaqaan 'Prompt.io' iyo Supabase Edge Functions waxaa loo isticmaali karaa.


    wax yar oo dhanDiiwaanka.ioSupabase Edge Functions


    Wala soo bandhigiisa, ka dibna soo baxsan karaan layer qiyaastii ah oo aan la isticmaali karaa.

    Diiwaanka ReBAC (Relationship-Based Access Control)

    Supabase waxay ku dhigi karaa xisaabinta iyo xisaabinta sare leh, laakiin waxay ku dhigi karaa xisaabinta sare ah sida:

    • Preventing users from voting on their own polls
    • Assigning per-resource roles (like “creator” for a specific poll)
    • Managing access via external policies
  • Waqtigaan isticmaalka ka soo bandhigay si aad u hesho oo aad u hesho
  • Waaxinta rolka per-resource ( sida "creator" for a specific poll)
  • Ganacsiga qiyaasta ka mid ah macluumaadka kale

  • Waqtiisa in la soo saarka loo isticmaali karaa, waxaan u isticmaali karaa ReBAC iyo Permit.io.


    Relationship-Based Access Control (ReBAC) is a model for managing permissions based on the relationships between users and resources. Instead of relying solely on roles or attributes (as in RBAC or ABAC), ReBAC determines access by evaluating how a user is connected to the resource they’re trying to access.

    Relationship-Based Access Control (ReBAC)Relationship-Based Access Control (ReBAC)


    In this tutorial, waxaan loo isticmaali karaa ReBAC in la isticmaali karo app:

    • A user who created a poll is the only one who can manage (edit/delete) it
    • A user cannot vote on their own poll
    • Other authenticated users can vote once per poll
  • A user who created a survey is the only one who can manage (edit/delete) it
  • Waayo, waxaan u baahan tahay in ay u baahan tahay in ay u baahan tahay in ay u baahan tahay in ay u baahan tahay in ay u baahan yahay.
  • A user cannot vote on their own poll
  • haynKu saabsan own
  • Ganacsiga kale oo loo yaqaan 'User authenticated can vote once per poll

  • By modeling this relationships in Permit.io, waxaan sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale.


    For more on ReBAC, check out Permit.io’s ReBAC docs.

    Permit.io’s ReBAC docs

    Dajinta Access Control

    Waqtiisa waxaa loo isticmaali karaa:

    Waayo, waxaa laga yaabaa in 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 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 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 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 ka mid ah midWaayo, waxaa laga yaabaa 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 in aad u baahan yahay in aad u baahan yahay in aad u baahan yahay in aad u baahan yahay.
    • polls: create, read, delete, update.
    Waayo, waxaa laga yaabaa in 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 ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid 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 ka mid ah mid ka mid ah mid ka mid ah.Waayo, waxaa laga yaabaa in aad u baahan tahay in aad u baahan tahay in aad u baahan yahay.createreaddeleteupdateWaayo, waxaa laga yaabaa in 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 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 ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka midWaayo, waxaa laga yaabaa in ka 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 mid ka mid
  • authenticated: Waxaad ka heli karo create iyo read ka mid ah macluumaadka.Waayo, waxaa laga yaabaa in ay ku saabsan:
  • createreaddeleteupdateWaayo, sidoo kale waxaa laga yaabaa in ka 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 ah mid ka midWaqtiga: createreaddeleteupdatereadcreatecreate

    Diiwaanka Permit.io

    Waqtiisa waa in la soo xiriir in la soo xiriir.

    • Create a new project in Permit.io
      • Name it something like 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
    • Enable ReBAC for the resource
      • Under “ReBAC Options,” define the following roles:

        • authenticated
        • creator
      • Click Save


  • Create a new project in Permit.io
    • Name it something like supabase-polling
  • Create a new projectCreate a new project in Permit.io
    • Name this something like supabase-polling
  • Name it sida supabase-polling
  • supabase-pollingWaayo, sidoo kale waxaa laga yaabaa in 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 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 ka mid ah mid 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 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 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 midDefine iyopollsWaayo, waxaa laga yaabaa in aad u baahan tahay in ay u baahan yahay in ay u baahan yahay in aad u baahan yahay.Waayo, waxaa laga yaabaa in 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 ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid 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 ka mid ah mid ka mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid
  • Go to Policy → Resources tab
  • Coolaha iyo dhismaha Waayo, waxaa laga yaabaa in aad u baahan yahay in aad u baahan yahay in aad u baahan yahay in aad u baahan yahay.“Waax yar”
  • Name it polls, oo ka mid ah wax soo saarka: read, create, update, delete
  • pollsreadcreateupdatedeleteWaayo, sidoo kale waxaa laga yaabaa 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 Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada Cudarada CWaqtiga ReBAC for resourceWaayo, sidoo kale 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 ka mid ah.Waayo, sidoo kale 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 ah mid 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.

    Waqtiga "ReBAC Options" waxaa loo yaqaan 'Rolls:

  • wax yar
  • authenticated
  • gaarka
  • creatorWaayo, waxaa laga yaabaa in aad u baahan yahay in aad u baahan yahay in aad u baahan yahay in aad u baahan yahay.Waayo, waxaa laga yaabaa in aad u baahan tahay in aad Cudarada Cudarada Cudarada.Diiwaanka


    Navigate in "Roles" tab si aad u aragto roles ka mid ah mid ah midabka waxaan ka mid ah loo aasaasay. Haddii aad u aragto in la aasaasay roles default (admin, editor, user) oo aad u baahan yahay in this tutorial.

    admineditoruser


    • Define access policies

      • Go to the Policy → Policies tab
      • Use the visual matrix to define:
        • authenticated can read and create polls

        • creator can read, update, and delete polls

        • (Optional) You can configure vote permissions as part of this or via a second resource if you model votes separately



    • Add resource instances

      • Go to Directory → Instances

      • Add individual poll IDs as resource instances (you’ll automate this later when new polls are created)

      • Assign roles to users per poll (e.g. user123 is creator of poll456)


  • Define access policies

    • Go to the Policy → Policies tab
    • Use the visual matrix to define:
      • authenticated can read and create polls

      • creator can read, update, and delete polls

      • (Optional) You can configure vote permissions as part of this or via a second resource if you model votes separately



  • Diiwaanka ugu fiican ee macluumaadkaDiiwaanka warshadaha accessWaayo, sidoo kale waxaa laga yaabaa in 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 ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid 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 ka mid ah mid ka mid ah mid ka mid ah mid 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

  • Go to Policy → Policy tab
  • Coolaha iyo dhismaha
  • Use the visual matrix to define:
    • authenticated can read and create polls

    • creator can read, update, and delete polls

    • (Optional) Waxaad ka heli karaa xisaabinta xisaabinta ka mid ah mid ka mid ah this ama 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 ah mid ka mid ah mid ah mid ah mid ka mid ah mid ah

      • authenticated can read and create polls

      • creator can read, update, and delete polls

      • (Optional) Waxaad ka heli karaa xisaabinta xisaabinta ka mid ah this ama ka 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 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

      • authenticated waxaa loo isticmaali karaa read iyo create polls

      • authenticated waxaa loo isticmaali karaa read iyo create polls

        authenticatedreadcreate
      • creator waxaa laga yaabaa read, update, iyo wax yar polls

      • creator waxaa laga yaqaan read, update, iyo delete polls

        creatorreadupdatedelete
      • (Optional) Waxaad ka heli karaa xisaabtood ka mid ah this ama 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 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 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 mid ah mid ka mid ah 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 ah mid ka mid ah mid ah mid ka mid ah mid ah mid ah

        (Optional) Waxaad ka heli karaa xisaabtood ka mid ah this ama ka 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 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 ah mid ka mid ah 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 mid ah mid ka mid ah mid ah mid ka mid ah.



        Waayo, waxaa laga yaabaa in ka 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 ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid 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 ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid

        Diiwaanka ugu horeysay ee ku saabsan

        Waqtiisa ah oo ku yaala
        • Go to Directory → Instances

        • Add individual poll IDs as resource instances (you will automate this later when new polls are created)

        • Assign roles to users per poll (e.g. user123 is creator of poll456)


      • Go to Directory → Instances

      • Go to Directory → Instances

        Dhammaanada → Dhammaanada
      • Waax ka mid ah ID-ga ah oo 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 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 ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid 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 ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah mid ah mid ka mid ah.

      • Waqtiyo ID-ga ah oo ku yaalaa mid ka mid ah macluumaadka ah (wax yar u isticmaalaa 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 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 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.

      • Waax yar oo ka mid ah macluumaad ka mid ah macluumaadka (e.g. user123 waa creator of poll456)


      • Waax yar oo ka mid ah macluumaad ka mid ah macluumaadka (e.g. user123 waa creator of poll456)

        user123creatorpoll456


        Waaqada this waxay ka dhigi karaa in ay ku xiran karaa qiyaasadaha qiyaasadaha iyo si ay u isticmaalo, per poll.


        Now that we have completed the initial setup on the Permit dashboard, let's use it in our application. Next, we’ll connect Permit.io to our Supabase project via Edge Functions that:

        Permit.io
        • Sync isticmaalka cusub
        • Role creator Assign
        • Check access on demand
      • Sync isticmaalka cusub
      • Waax yar oo dhan
      • Check access on demand
      • Waqtiisa waxaa loo isticmaali karaa in la isticmaali karaa

        Waqtiisa loo yaqaan 'Polling Application'

        Permit offers multiple ways to integrate with your application, but we'll use the Container PDP for this tutorial. You have to host the container online to access it in Supabase Edge functions. You can use services like railway.com. Once you have hosted it, save the url for your container.

        railway.com


        Dhammaan API-ka Dhammaan ka mid ah "Projects" ee tababarka tababarka Dhammaan, si ay u shaqeeyaan in ay u shaqeeyaan, si ay u mid ka mid ah three dots, oo ka mid ah "Copy API Key".


        Creeing Supabase Edge Function API for Authorization

        Supabase Edge Functions waa mid ka mid ah si ay u isticmaali karaa adeegga kale sida Permit.io. Waxaan loo isticmaali karaa si ay u isticmaali karaa qiyaasta ReBAC ee la xiran tahay in ay isticmaali karaa si ay u isticmaali karaa macluumaadka gaarka ah.

        Supabase Edge Functions

        Waaq u soo xiriir oo loo isticmaali karaa

        Waaq u soo xiriir in Supabase

        Diiwaanka Supabase ee shuruudahaaga iyo loo helo 3 kala duwan oo loo isticmaalo Supabase functions new command.supabase functions new

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

        Diiwaanka waxaa loo isticmaali karaa foldera functions ee foldera supabase sida loo isticmaali karaa endpoints.

        functionssupabase

        Syncing Users to Permit.io on Signup (syncUser.ts)

        syncUser.ts

        Function this listens for Supabase's SIGNED_UP auth event. Markaad ka mid ah isticmaalka cusub waa in la soo xiriir, waxaan soo xiriir si loo isticmaalaa Permit.io iyo si ay u soo xiriir authenticated rol.

        SIGNED_UPauthenticated


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

        Diiwaanka Role Creator (updateCreatorRole.ts)

        updateCreatorRole.ts

        Wala soo saarka isticmaalka loo soo saarka, function this is called to:

        Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku:
      • Sync si aad u baahan tahay 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 ah mid ka mid ah.

        Sync 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 ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ahHaku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku: Haku:

        Waaxii isticmaalka creator rol oo ka mid ah in la helo

        creator


        Waayo, waxaa laga yaabaa in 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 ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid 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 ka mid ah mid ka mid ah mid ka mid ah mid ah mid ka mid ah mid ka mid ah midimport "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, pollId } = await req.json(); // Validate input parameters if (!userId || !pollId) { return new Response( JSON.stringify({ error: "Missing required parameters." }), { status: 400, headers: { "Content-Type": "application/json" } }, ); } // Sync the resource (poll) to Permit.io await permit.api.syncResource({ type: "polls", key: pollId, tenant: "default", attributes: { createdBy: userId } }); // Assign the creator role to the user for this specific poll await permit.api.assignRole({ role: "creator", tenant: "default", user: userId, resource: { type: "polls", key: pollId, } }); return new Response( JSON.stringify({ message: "Creator role assigned successfully", success: true }), { status: 200, headers: corsHeaders }, ); } catch (error) { console.error("Error assigning creator role: ", error); return new Response( JSON.stringify({ message: "Error occurred while assigning creator role.", error: error }), { status: 500, headers: { "Content-Type": "application/json" } }, ); } });


        Qalabka dhismaha (checkPermission.ts)

        checkPermission.ts

        Function this function acts as the gatekeeper—it checks whether a user is allowed to perform a given action (create, read, update, delete) on a particular poll.

        createreadupdatedelete


        Waayo, waxaa laga yaabaa in 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 ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid 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 ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka midimport "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" } } ); } });

        Local Testing

        Diiwaanka adeegga Supabase ee loo yaqaan 'Development Server' ee loo yaqaan 'Development Server':

        nppx supabase start nppx supabase functions serve 
        npx supabase start npx supabase functions serve

        Saacadda waxaad ka heli karaa:

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

        Integrating Authorization Checks in UI

        Wala soo saarka loo soo saarka logic autorization la Permit.io iyo loo soo saarka via Supabase Edge Functions, waxaa laga yaabaa in la qiyaasta in ay ka mid ah qiyaasta ah ee app.


        In this section, waxaan soo dejiso components UI key si ay u soo xiriir macluumaadka iyo si ay u qiyaastii karaa ama si ay u qiyaastii wax soo saarka macaamiisha sida si ay u dhiso ama si ay u qiyaastii si ay u qiyaastii qiyaastii.

        NewPoll.tsx: Dhammaan Dhammaan Dhammaan Dhammaan DhammaanNewPoll.tsx

        Saacad ka dib markii loo soo saarka oo ku salaysan in Supabase, waxaan ka heli updateCreatorRole function in:

        updateCreatorRole{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{
      • Sync si loo isticmaali karaa mid ka mid ah 'Permit.io

      • Sync si aad u soo xiriir sida resource in Permit.io

        {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{

        Waaxii isticmaalka ugu horeysay ee creator rol for that specific poll

        creator


        Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabka Qalabkaconst 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: Qalabka ugu soo saarkaViewPoll.tsx

        Wala soo bandhigay user ka soo bandhigay on a poll, waxaan soo bandhigay checkPermission function si ay u soo bandhigay create permit on the votes resource. This is how we enforce the rule: “A creator cannot vote on their own poll.”

        checkPermissioncreatevotes“A creator cannot vote on his own poll.”


        Diiwaanka xisaabinta:

        Waqtiisa loo yaabaa in la soo xiriir:


        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 ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka midconst [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]);


        Diiwaanka si aad u isticmaali karaa:

        Waax yar oo ka mid ah wax soo saarka:


        <button onClick={() => handleVote(option.id)} disabled={!user Mediateca !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> 
        <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:

        Show a message if user is not allowed to vote:


        {user && !canVote && ( <p className="mt-4 text-gray-600">Diiwaanka waxaa laga yaabaa in aad u hesho</p> )} 
        {user && !canVote && ( <p className="mt-4 text-gray-600">You cannot vote on your own poll</p> )}

        PollCard.tsx: Qalabka ugu soo saarkaPollCard.tsx

        Waa soo bandhigay ka mid ah macluumaadka loo isticmaali karaa (xirfadaha iyo xiran) by checking if the user has the update or delete permission on that poll.

        updatedelete


        Diiwaanka xisaabinta:

        Diiwaanka xanuunada xanuunada:


        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 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 mid ka mid ah mid ka mid ah mid 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 midconst [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]);


        Diiwaanka dhismaha dhismaha dhismaha:

        Ganacsiga dhismaha dhismaha dhismaha:


        Tusaale:

        Tusaale:

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


        Marka:

        With:

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

        Testing Integraasi

        Saacad ka mid ah, sidoo kale aad u soo baxsan kartaa dhismaha ugu horeysay ee app:

        Waayo, sidoo kale waxaa laga yaabaa in 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 ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid ah mid ka mid
      • Wala soo xiriir waxaa laga yaabaa in la soo xiriir oo la xiriir

      • Wala soo xiriir waxaa laga yaabaa in la soo xiriir oo la soo xiriir

      • Wala soo xiriir oo ka mid ah wax soo saarka oo ka mid ah wax soo saarka oo ka mid ah wax soo saarka oo ka mid ah wax soo saarka.

        Waxaysiinta waxaa laga yaabaa in la heli karo in ay didn't create

        Didn't waxaa laga yaabaa
      • Creators cannot vote on their own polls

      • Creators cannot vote on their own polls

        gaaxiib ah oo ku saabsan
      • Only creators see edit/delete options on their polls


      • Only creators see edit/delete options on their polls

        xirfado/xirfado


        Saacadda waxaa laga yaabaa in aad u aragto wax soo saarka ah ee app si aad u aragto browser. On screen home, users can view the list of active and past polls, whether they are logged in or not. However, when they click on a poll, they will not be able to view the poll details or vote on it. Instead, they will be prompted to log in.


        Saacad ka hor si ay u soo xiriir, isticmaalka waa in ay u aragti si ay u aragti si ay u aragti si ay u aragti si ay u aragti si ay u aragti si ay u aragti si ay u aragti si ay u aragti.

        Diiwaanka

        In this tutorials, waxaan ku yaalaa sida loo isticmaalaa Supabase authentication iyo authorization in a real-world Next.js application.

        Supabase authentication iyo kharashkaDiiwaanka.js

        Wala soo bandhigay Supabase Auth for login and signup, soo bandhigay dhismaha relational oo loo isticmaalo Row Level Security, iyo soo bandhigay dhismaha dhismaha dhismaha dhismaha dhismaha oo isticmaalo ReBAC.Wala soo bandhigay Supabase Edge Functions iyo a Policy Decision Point (PDP), sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale sidoo kale.

        Supabase QalabkaDiiwaankaSupabase Edge Functions Policy Decision Point (PDP)


        Dhammaan ka mid ah Supabase Auth iyo qiyaasta Access flexible, waxaan noqon doonaa:

        Supabase Qalabka
        • Dhammaan users via email and password
        • Restrict voting and poll management to authorized users
        • Dhammaan creators from voting on their own polls
        • Dhammaan iyo si ay u hesho role users based on relationships to data
      • Coolka isticmaalka email iyo password
      • Dhammaan oo ka mid ah shuruudaha iyo shuruudaha waxaa laga yaqaan 'Limit voting and poll management to authorized users'.
      • Diiwaanka loo isticmaali karaa in la heli karaa in la heli karo oo ka mid ah wax soo saarka.
      • Dhammaan iyo si ay u hesho user roles ku salaysan relationships to data

      • Dhammaan waxaa loo isticmaali karaa in ay u isticmaali karaa macluumaadka macluumaadka iyo macluumaadka.

        Laha soo xiriir

      • Permit.io ReBAC Guide

      • Permit.io ReBAC Guide

        Permit.io ReBAC Guide
      • Permit + Authentication Providers

      • Permit + Authentication Providers

        Permit + Authentication Providers
      • Permit Elements: Embedded UI for Role Management

      • Permit Elements: Embedded UI for Role Management

        Permit Elements: Embedded UI for Role Management
      • Data Filtering with Permit

      • Data Filtering with Permit

        Data Filtering with Permit
      • Audit Logs


      • Audit Logs

        Audit Logs


        Got questions? Join our Slack community, where hundreds of developers are building and discussing authorization.

        Slack communitySlack community
  • Trending Topics

    blockchaincryptocurrencyhackernoon-top-storyprogrammingsoftware-developmenttechnologystartuphackernoon-booksBitcoinbooks