Heim > Web-Frontend > js-Tutorial > Supabase-Funktionen (nicht Kante)

Supabase-Funktionen (nicht Kante)

WBOY
Freigeben: 2024-08-29 14:00:19
Original
394 Leute haben es durchsucht

Supabase

Eine Open-Source-Alternative zum Firebase-Angebot

  • Datenbank
  • Echtzeit
  • auth
  • Funktionen
  • Kantenfunktionen

Aber Moment, wenn sie bereits Funktionen haben, warum brauchen sie Kantenfunktionen?

supabase functions (not edge)

Supabase-Funktionen: Ihre PostgreSQL-Toolbox

Supabase-Funktionen, auch Datenbankfunktionen genannt, sind im Wesentlichen gespeicherte PostgreSQL-Prozeduren. Dabei handelt es sich um ausführbare SQL-Codeblöcke, die aus SQL-Abfragen aufgerufen werden können.

Edge-Funktionen: Jenseits der Datenbank

Im Gegensatz dazu sind Edge-Funktionen serverseitige TypeScript-Funktionen, die auf der Deno-Laufzeit ausgeführt werden. Sie ähneln Firebase Cloud Functions, bieten jedoch eine flexiblere und Open-Source-Alternative.

Supabase: Eine PostgreSQL-Plattform

Über seine Rolle als Open-Source-Alternative zu Firebase hinaus hat sich Supabase zu einer umfassenden PostgreSQL-Plattform entwickelt. Es bietet erstklassige Unterstützung für PostgreSQL-Funktionen, integriert diese nahtlos in die integrierten Dienstprogramme und ermöglicht Ihnen die Erstellung und Verwaltung benutzerdefinierter Funktionen direkt über das Supabase-Dashboard.

Struktur einer grundlegenden Postgres-Funktion

CREATE FUNCTION my_function() RETURNS int AS $$
BEGIN
    RETURN 42;
END;
$$ LANGUAGE sql;
Nach dem Login kopieren

Aufschlüsselung:

  1. FUNKTION ERSTELLEN: Dieses Schlüsselwort zeigt an, dass wir eine neue Funktion definieren.
  2. my_function(): Dies ist der Name der Funktion. Sie können einen beliebigen aussagekräftigen Namen wählen, den Sie bevorzugen.
  3. RETURNS int: Dies gibt den Rückgabetyp der Funktion an. In diesem Fall gibt die Funktion einen ganzzahligen Wert zurück.
  4. AS $$: Damit beginnt der Funktionskörper, eingeschlossen in doppelte Dollarzeichen ($$), um ihn abzugrenzen.
  5. BEGIN: Dies markiert den Beginn des ausführbaren Codes der Funktion.
  6. RETURN 42;: Diese Anweisung gibt den Wert an, den die Funktion zurückgibt. In diesem Fall ist es die Ganzzahl 42.
  7. END;: Dies markiert das Ende des ausführbaren Codes der Funktion.
  8. $$ LANGUAGE sql;: Dies gibt die Sprache an, in der die Funktion geschrieben ist. In diesem Fall ist es SQL.

Zweck:

Diese Funktion definiert eine einfache SQL-Funktion namens my_function, die den ganzzahligen Wert 42 zurückgibt. Es handelt sich um ein einfaches Beispiel zur Demonstration der Struktur und Syntax einer Funktionsdefinition in PostgreSQL.

Wichtige Punkte, die Sie beachten sollten:

  • Sie können my_function durch einen beliebigen Funktionsnamen ersetzen.
  • Der Rückgabetyp kann jeder gültige Datentyp sein, z. B. Text, Boolescher Wert, Datum oder ein benutzerdefinierter Typ.
  • Der Funktionskörper kann komplexe Logik enthalten, einschließlich bedingter Anweisungen, Schleifen und Aufrufe anderer Funktionen.
  • Die $$-Trennzeichen werden verwendet, um den Funktionskörper sprachunabhängig einzuschließen.

  • Postgres-Funktionen können auch von Postgres-TRIGGERN aufgerufen werden, die wie Funktionen sind, aber auf bestimmte Ereignisse wie Einfügen, Aktualisieren oder Löschen in einer Tabelle reagieren

  • um diese Funktion auszuführen

SELECT my_function();
Nach dem Login kopieren
  • um diese Funktion aufzulisten
SELECT
    proname AS function_name,
    prokind AS function_type
FROM pg_proc
WHERE proname = 'my_function';
Nach dem Login kopieren
  • um diese Funktion zu löschen
DROP FUNCTION my_function();
Nach dem Login kopieren

Supabase-Postgres-Funktionen

Eingebaute Funktionen

Supabase nutzt Postgres-Funktionen, um bestimmte Aufgaben in Ihrer Datenbank auszuführen.

Eine kurze Liste mit Beispielen enthält

--  list all the supabase functions
SELECT
    proname AS function_name,
    prokind AS function_type
FROM pg_proc;

--  filter for the session supabase functions function
SELECT
    proname AS function_name,
    prokind AS function_type
FROM pg_proc
WHERE proname ILIKE '%session%';

--  selects the curremt jwt
select auth.jwt()

-- select what role is callig the function (anon or authenticated)
select auth.role();

-- select the session user
select session_use;
Nach dem Login kopieren

Supabase-Funktionsansicht im Dashboard
Um einige dieser Funktionen in Supabase anzuzeigen, können Sie unter Datenbank > Funktionen

supabase functions (not edge)

Nützliche Supabase PostgreSQL-Funktionen

Erstellen einer user_profile-Tabelle bei der Benutzeranmeldung

Supabase speichert Benutzerdaten in der Tabelle auth.users, die privat ist und nicht direkt aufgerufen oder geändert werden sollte. Ein empfohlener Ansatz besteht darin, eine öffentliche Benutzer- oder user_profiles-Tabelle zu erstellen und diese mit der auth.users-Tabelle zu verknüpfen.

Während dies mithilfe clientseitiger SDKs durch Verketten einer Anforderung zum Erstellen eines Benutzers mit einer erfolgreichen Anmeldeanforderung erfolgen kann, ist es zuverlässiger und effizienter, dies auf der Supabase-Seite zu verarbeiten. Dies kann durch eine Kombination aus einem TRIGGER und einer FUNKTION erreicht werden.

--   create the user_profiles table
CREATE TABLE user_profiles (
  id uuid PRIMARY KEY,
  FOREIGN KEY (id) REFERENCES auth.users(id),
  name text,
  email text
);

-- create a function that returns a trigger on auth.users
CREATE 
OR REPLACE FUNCTION public.create_public_user_profile_table() 
RETURNS TRIGGER AS $$ 
BEGIN INSERT INTO public.user_profiles (id,name,email) 
VALUES 
  (
    NEW.id,
    NEW.raw_user_meta_data ->> 'name',
    NEW.raw_user_meta_data ->> 'email'
    -- other fields accessible here 
--     NEW.raw_user_meta_data ->> 'name',
-- NEW.raw_user_meta_data ->> 'picture',

);
RETURN NEW;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- create the trigger that executes the function on every new user rowcteation(signup)
CREATE TRIGGER create_public_user_profiles_trigger 
AFTER INSERT ON auth.users FOR EACH ROW WHEN (
        NEW.raw_user_meta_data IS NOT NULL
    )
EXECUTE FUNCTION public.create_public_user_profile_table ();

Nach dem Login kopieren
let { data: user_profiles, error } = await supabase
  .from('user_profiles')
  .select('*')
Nach dem Login kopieren
  • Benutzerdefinierte Ansprüche zur JWT-Erstellung hinzufügen (RBAC) supabse hat einen ausführlichen Artikel und ein Video dazu.

wir brauchen 2 Tische

  • public.roles und public.role_permissions
-- Custom types
create type public.app_permission as enum ('channels.delete', 'channels.update', 'messages.update', 'messages.delete');
create type public.app_role as enum ('admin', 'moderator');

-- USER ROLES
create table public.user_roles (
  id        bigint generated by default as identity primary key,
  user_id   uuid references public.users on delete cascade not null,
  role      app_role not null,
  unique (user_id, role)
);
comment on table public.user_roles is 'Application roles for each user.';

-- ROLE PERMISSIONS
create table public.role_permissions (
  id           bigint generated by default as identity primary key,
  role         app_role not null,
  permission   app_permission not null,
  unique (role, permission)
);
comment on table public.role_permissions is 'Application permissions for each role.';
Nach dem Login kopieren

Beispiel für eine Benutzerrolle

id user_id role
1 user-1 admin
2 user-2 moderator

example of a role permission table

id role permission
1 admin channels.update
2 admin messages.update
3 admin messages.delete
4 admin messages.delete
5 moderator channels.update
6 moderator messages.update

user with user_id = user-1 will have admin and moderator roles and can delete channels and messages

users with user_id = user-2 can only update channels and messages with the moderator role

-- Create the auth hook function
create or replace function public.custom_access_token_hook(event jsonb)
returns jsonb
language plpgsql
stable
as $$
  declare
    claims jsonb;
    user_role public.app_role;
  begin
    -- Fetch the user role in the user_roles table
    select role into user_role from public.user_roles where user_id = (event->>'user_id')::uuid;

    claims := event->'claims';

    if user_role is not null then
      -- Set the claim
      claims := jsonb_set(claims, '{user_role}', to_jsonb(user_role));
    else
      claims := jsonb_set(claims, '{user_role}', 'null');
    end if;

    -- Update the 'claims' object in the original event
    event := jsonb_set(event, '{claims}', claims);

    -- Return the modified or original event
    return event;
  end;
$$;

grant usage on schema public to supabase_auth_admin;

grant execute
  on function public.custom_access_token_hook
  to supabase_auth_admin;

revoke execute
  on function public.custom_access_token_hook
  from authenticated, anon, public;

grant all
  on table public.user_roles
to supabase_auth_admin;

revoke all
  on table public.user_roles
  from authenticated, anon, public;

create policy "Allow auth admin to read user roles" ON public.user_roles
as permissive for select
to supabase_auth_admin
using (true)

Nach dem Login kopieren

then create a function that will be called to authorize on RLS policies

create or replace function public.authorize(
  requested_permission app_permission
)
returns boolean as $$
declare
  bind_permissions int;
  user_role public.app_role;
begin
  -- Fetch user role once and store it to reduce number of calls
  select (auth.jwt() ->> 'user_role')::public.app_role into user_role;

  select count(*)
  into bind_permissions
  from public.role_permissions
  where role_permissions.permission = requested_permission
    and role_permissions.role = user_role;

  return bind_permissions > 0;
end;
$$ language plpgsql stable security definer set search_path = '';

--  example RLS policies
create policy "Allow authorized delete access" on public.channels for delete using ( (SELECT authorize('channels.delete')) );
create policy "Allow authorized delete access" on public.messages for delete using ( (SELECT authorize('messages.delete')) );


Nach dem Login kopieren

Improved Text:

Creating RPC Endpoints

Supabase functions can be invoked using the rpc function. This is especially useful for writing custom SQL queries when the built-in PostgreSQL APIs are insufficient, such as calculating vector cosine similarity using pg_vector.

create or replace function match_documents (
  query_embedding vector(384),
  match_threshold float,
  match_count int
)
returns table (
  id bigint,
  title text,
  body text,
  similarity float
)
language sql stable
as $$
  select
    documents.id,
    documents.title,
    documents.body,
    1 - (documents.embedding <=> query_embedding) as similarity
  from documents
  where 1 - (documents.embedding <=> query_embedding) > match_threshold
  order by (documents.embedding <=> query_embedding) asc
  limit match_count;
$$;

Nach dem Login kopieren

and call it client side

const { data: documents } = await supabaseClient.rpc('match_documents', {
  query_embedding: embedding, // Pass the embedding you want to compare
  match_threshold: 0.78, // Choose an appropriate threshold for your data
  match_count: 10, // Choose the number of matches
})
Nach dem Login kopieren

Improved Text:

Filtering Out Columns

To prevent certain columns from being modified on the client, create a simple function that triggers on every insert. This function can omit any extra fields the user might send in the request.

-- check if user with roles authenticated or anon submitted an updatedat column and replace it with the current time , if not (thta is an admin) allow it
CREATE
or REPLACE function public.omit_updated__at () returns trigger as 
$$ BEGIN 
IF auth.role() IS NOT NULL AND auth.role() IN ('anon', 'authenticated') 
THEN NEW.updated_at = now();
END IF; 
RETURN NEW; 
END; $$ language plpgsql;
Nach dem Login kopieren

Summary

With a little experimentation, you can unlock the power of Supabase functions and their AI-powered SQL editor. This lowers the barrier to entry for the niche knowledge required to get this working.

Why choose Supabase functions?

  • Extend Supabase's API: Supabase can only expose so much through its API. Postgres, however, is a powerful database. Any action you can perform with SQL statements can be wrapped in a function and called from the client or by a trigger.
  • Reduce the need for dedicated backends: Supabase functions can fill the simple gaps left by the client SDKs, allowing you to focus on shipping.
  • Avoid vendor lock-in: Supabase functions are just Postgres. If you ever need to move to another hosting provider, these functionalities will continue to work.

Das obige ist der detaillierte Inhalt vonSupabase-Funktionen (nicht Kante). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage