diff --git a/web/docs/guides/auth.mdx b/web/docs/guides/auth.mdx index 45fc7a522b7..38aa8a671b8 100644 --- a/web/docs/guides/auth.mdx +++ b/web/docs/guides/auth.mdx @@ -7,58 +7,7 @@ description: Use Supabase to Authenticate and Authorize your users. import Link from '@docusaurus/Link' import Tabs from '@theme/Tabs' import TabItem from '@theme/TabItem' -const providers = [ - { - name: 'Apple', - // logo: '/img/libraries/dart-icon.svg', - href: '/docs/guides/auth/auth-apple', - }, - { - name: 'Bitbucket', - // logo: '/img/libraries/dart-icon.svg', - href: '/docs/guides/auth/auth-bitbucket', - }, - { - name: 'Discord', - // logo: '/img/libraries/dart-icon.svg', - href: '/docs/guides/auth/auth-discord', - }, - { - name: 'Facebook', - // logo: '/img/libraries/dart-icon.svg', - href: '/docs/guides/auth/auth-facebook', - }, - { - name: 'GitHub', - // logo: '/img/libraries/dart-icon.svg', - href: '/docs/guides/auth/auth-github', - }, - { - name: 'GitLab', - // logo: '/img/libraries/dart-icon.svg', - href: '/docs/guides/auth/auth-gitlab', - }, - { - name: 'Google', - // logo: '/img/libraries/dart-icon.svg', - href: '/docs/guides/auth/auth-google', - }, - { - name: 'Twitter', - // logo: '/img/libraries/dart-icon.svg', - href: '/docs/guides/auth/auth-twitter', - }, - { - name: 'Twitch', - // logo: '/img/libraries/dart-icon.svg', - href: '/docs/guides/auth/auth-twitch', - }, - { - name: 'Twilio', - // logo: '/img/libraries/dart-icon.svg', - href: '/docs/guides/auth/auth-twilio', - }, -] +import providers from '@site/src/data/authProviders' ## User Management @@ -134,22 +83,6 @@ let user = await supabase.from('users').select('user_id, name') // Still => { id: 'd0714948', name: 'Jane' } ``` -## Policies Are Like `WHERE` Clauses - -Policies are easy to understand once you get the hang of them. You can just think of them as adding a `WHERE` clause to every query. For example if you had a policy like this: - -```sql -create policy "Individuals can view their own todos." on todos for - select using (auth.uid() = user_id); -``` - -It would translate to this whenever a user tries to select from the todos table: - -```sql -select * -from todos -where auth.uid() = todos.user_id; -- Policy is implicitly added. -``` ## How It Works @@ -161,258 +94,9 @@ where auth.uid() = todos.user_id; -- Policy is implicitly added. Supabase provides a special function in Postgres, `auth.uid()`, which extracts the user's UID from the JWT. This is especially useful when creating policies. -## Policy Examples - -Here are some examples to show you the power of PostgreSQL's RLS. Each policy is attached to a table, and the policy is executed -every time a table is accessed. - -### Allow read access - -```sql --- 1. Create table -create table profiles ( - id uuid references auth.users, - avatar_url text -); - --- 2. Enable RLS -alter table profiles - enable row level security; - --- 3. Create Policy -create policy "Public profiles are viewable by everyone." - on profiles for select using ( - true - ); -``` - -1. Creates a table called `profiles` in the public schema (default schema). -2. Enables Row Level Security. -3. Creates a policy which allows all `select` queries to run. - -### Restrict updates - -```sql --- 1. Create table -create table profiles ( - id uuid references auth.users, - avatar_url text -); - --- 2. Enable RLS -alter table profiles - enable row level security; - --- 3. Create Policy -create policy "Users can update their own profiles." - on profiles for update using ( - auth.uid() = id - ); -``` - -1. Creates a table called `profiles` in the public schema (default schema). -2. Enables RLS. -3. Creates a policy which allows logged in users to update their own data. - -### Policies with joins - -Policies can even include table joins. This example shows how you can query "external" tables to build more advanced rules. - -```sql -create table teams ( - id serial primary key, - name text -); - --- 2. Create many to many join -create table members ( - team_id bigint references teams, - user_id uuid references auth.users -); - --- 3. Enable RLS -alter table teams - enable row level security; - --- 4. Create Policy -create policy "Team members can update team details if they belong to the team." - on teams - for update using ( - auth.uid() in ( - select user_id from members - where team_id = id - ) - ); -``` - -### Policies with security definer functions - -Policies can also make use of `security definer functions`. This is useful in a many-to-many relationship where you want to restrict access to the linking table. Following the `teams` and `members` example from above, this example shows how you can use security definer function in combination with a policy to control access to the `members` table. - -```sql --- 1. Follow example for 'Policies with joins' above - --- 2. Enable RLS -alter table members - enable row level security - --- 3. Create security definer function -create or replace function get_teams_for_authenticated_user() -returns setof bigint -language sql -security definer -set search_path = public -stable -as $$ - select team_id - from members - where user_id = auth.uid() -$$; - --- 4. Create Policy -create policy "Team members can update team members if they belong to the team." - on members - for all using ( - team_id in ( - select get_teams_for_authenticated_user() - ) - ); - -``` - -### Verifying email domains - -Postgres has a function `right(string, n)` that returns the rightmost n characters of a string. -You could use this to match staff member's email domains. - -```sql --- 1. Create table -create table leaderboard ( - id uuid references auth.users, - high_score bigint -); - --- 2. Enable RLS -alter table leaderboard - enable row level security; - --- 3. Create Policy -create policy "Only Blizzard staff can update leaderboard" - on leaderboard - for update using ( - right(auth.email(), 13) = '@blizzard.com' - ); -``` - -### Time to live for rows - -Policies can also be used to implement TTL or time to live feature that you see in Instagram stories or Snapchat. -In the following example, rows of `stories` table are available only if they have been created within the last 24 hours. - -```sql --- 1. Create table -create table if not exists stories ( - id uuid not null primary key DEFAULT uuid_generate_v4(), - created_at timestamp with time zone default timezone('utc' :: text, now()) not null, - content text not null -); - --- 2. Enable RLS -alter table stories - enable row level security; - --- 3. Create Policy -create policy "Stories are live for a day" - on stories - for select using ( - created_at > (current_timestamp - interval '1 day') - ); -``` - -### Advanced policies - -Use the full power of SQL to build extremely advanced rules. - -In this example, we will create a `posts` and `comments` tables and then create a policy that depends on another policy. -(In this case, the comments policy depends on the posts policy.) - -```sql -create table posts ( - id serial primary key, - creator_id uuid not null references auth.users(id), - title text not null, - body text not null, - publish_date date not null default now(), - audience uuid[] null -- many to many table omitted for brevity -); - -create table comments ( - id serial primary key, - post_id int not null references posts(id) on delete cascade, - user_id uuid not null references auth.users(id), - body text not null, - comment_date date not null default now() -); - -create policy "Creator can see their own posts" -on posts -for select -using ( - auth.uid() = posts.creator_id -); - -create policy "Logged in users can see the posts if they belong to the post 'audience'." -on posts -for select -using ( - auth.uid() = any (posts.audience) -); - -create policy "Users can see all comments for posts they have access to." -on comments -for select -using ( - exists ( - select 1 from posts - where posts.id = comments.post_id - ) -); -``` - ## Tips -### You don't have to use policies - -You can also put your authorization rules in your middleware, similar to how you would create security rules with any other `backend <-> middleware <-> frontend` architecture. - -Policies are a tool. In the case of "serverless/Jamstack" setups, they are especially effective because you don't have to deploy any middleware at all. - -However, if you want to use another authorization method for your applications, that's also fine. Supabase is "just Postgres", so if your application -works with Postgres, then it also works with Supabase. - -Tip: Make sure to enable RLS for all your tables, so that your tables are inaccessible. Then use the "Service" which we provide, which is designed to bypass RLS. - -### Check authentication settings on Supabase - -Navigate to Authentication > Settings on [app.supabase.io](https://app.supabase.io), and you'll be able to change settings for things like: - -- SITE URL, which is used for determining where to redirect users after they confirm their email addresses or attempt to use a magic link to log in. -- Disabling email confirmations. -- Enabling external OAuth providers, such as Google and GitHub. - -### Never use a service key on the client - -Supabase provides special "Service" keys, which can be used to bypass all RLS. -These should never be used in the browser or exposed to customers, but they are useful for administrative tasks. - -### Managing User Data - -For security purposes, the `auth` schema is not exposed on the auto-generated API. -Even though Supabase provides an `auth.users` table, it can be helpful to create tables in the `public` schema for storing user data. - -You can read more about this in the [Managing User Data](/docs/guides/auth/managing-user-data) guide. - -### Disable realtime for private tables +#### Disable realtime for private tables Our realtime server doesn't provide per-user security. Until we build a more robust auth system for WebSockets, you can disable realtime functionality for any private tables. To do this, you can manage the underlying Postgres replication publication: @@ -437,9 +121,9 @@ alter publication supabase_realtime add table products; alter publication supabase_realtime add table posts; ``` -We're in the process of building enhanced realtime security. +We're in the process of building [enhanced realtime security](https://github.com/supabase/walrus). ## Next Steps -- Read more about [Row Level Security](https://www.postgresql.org/docs/current/ddl-rowsecurity.html). +- Read more about Auth in the [Guides](/docs/guides/auth/intro). - Sign in: [app.supabase.io](https://app.supabase.io) diff --git a/web/docs/guides/auth/auth-apple.mdx b/web/docs/guides/auth/auth-apple.mdx index 9ee35962e3a..0391b3d6be6 100644 --- a/web/docs/guides/auth/auth-apple.mdx +++ b/web/docs/guides/auth/auth-apple.mdx @@ -1,6 +1,6 @@ --- id: auth-apple -title: "OAuth with Apple" +title: "Login with Apple" description: Add Apple OAuth to your Supabase project --- diff --git a/web/docs/guides/auth/auth-bitbucket.mdx b/web/docs/guides/auth/auth-bitbucket.mdx index 625d9df8861..6ffc10c4760 100644 --- a/web/docs/guides/auth/auth-bitbucket.mdx +++ b/web/docs/guides/auth/auth-bitbucket.mdx @@ -1,6 +1,6 @@ --- id: auth-bitbucket -title: "OAuth with Bitbucket" +title: "Login with Bitbucket" description: Add Bitbucket OAuth to your Supabase project --- diff --git a/web/docs/guides/auth/auth-discord.mdx b/web/docs/guides/auth/auth-discord.mdx index c11ce5b1997..a76631bdae5 100644 --- a/web/docs/guides/auth/auth-discord.mdx +++ b/web/docs/guides/auth/auth-discord.mdx @@ -1,6 +1,6 @@ --- id: auth-discord -title: "OAuth with Discord" +title: "Login with Discord" description: Add Discord OAuth to your Supabase project --- diff --git a/web/docs/guides/auth/auth-facebook.mdx b/web/docs/guides/auth/auth-facebook.mdx index b0c7e7b1287..8b2c5fb8b9f 100644 --- a/web/docs/guides/auth/auth-facebook.mdx +++ b/web/docs/guides/auth/auth-facebook.mdx @@ -1,6 +1,6 @@ --- id: auth-facebook -title: "OAuth with Facebook" +title: "Login with Facebook" description: Add Facebook OAuth to your Supabase project --- diff --git a/web/docs/guides/auth/auth-github.mdx b/web/docs/guides/auth/auth-github.mdx index 065271573b1..166a78102a8 100644 --- a/web/docs/guides/auth/auth-github.mdx +++ b/web/docs/guides/auth/auth-github.mdx @@ -1,6 +1,6 @@ --- id: auth-github -title: "OAuth with GitHub" +title: "Login with GitHub" description: Add GitHub OAuth to your Supabase project --- diff --git a/web/docs/guides/auth/auth-gitlab.mdx b/web/docs/guides/auth/auth-gitlab.mdx index 350b9adf41a..eb3a9252f5f 100644 --- a/web/docs/guides/auth/auth-gitlab.mdx +++ b/web/docs/guides/auth/auth-gitlab.mdx @@ -1,6 +1,6 @@ --- id: auth-gitlab -title: "OAuth with GitLab" +title: "Login with GitLab" description: Add GitLab OAuth to your Supabase project --- diff --git a/web/docs/guides/auth/auth-google.mdx b/web/docs/guides/auth/auth-google.mdx index ea4d8f46344..481cd653cce 100644 --- a/web/docs/guides/auth/auth-google.mdx +++ b/web/docs/guides/auth/auth-google.mdx @@ -1,6 +1,6 @@ --- id: auth-google -title: "OAuth with Google" +title: "Login with Google" description: Add Google OAuth to your Supabase project --- diff --git a/web/docs/guides/auth/auth-twilio.mdx b/web/docs/guides/auth/auth-twilio.mdx index 172473afd60..a9ed349931a 100644 --- a/web/docs/guides/auth/auth-twilio.mdx +++ b/web/docs/guides/auth/auth-twilio.mdx @@ -1,6 +1,6 @@ --- id: auth-twilio -title: SMS OTP with Twilio +title: Phone Auth with Twilio description: How to set up and use Mobile OTP with Twilio and Supabase. --- diff --git a/web/docs/guides/auth/auth-twitch.mdx b/web/docs/guides/auth/auth-twitch.mdx index 98ab85cccf6..4bc9cc7ab9a 100644 --- a/web/docs/guides/auth/auth-twitch.mdx +++ b/web/docs/guides/auth/auth-twitch.mdx @@ -1,6 +1,6 @@ --- id: auth-twitch -title: 'OAuth with Twitch' +title: 'Login with Twitch' description: Add Twitch OAuth to your Supabase project --- diff --git a/web/docs/guides/auth/auth-twitter.mdx b/web/docs/guides/auth/auth-twitter.mdx index 3cc755cfd24..c422b2cc9ff 100644 --- a/web/docs/guides/auth/auth-twitter.mdx +++ b/web/docs/guides/auth/auth-twitter.mdx @@ -1,6 +1,6 @@ --- id: auth-twitter -title: "OAuth with Twitter" +title: "Login with Twitter" description: Add Twitter OAuth to your Supabase project --- diff --git a/web/docs/guides/auth/intro.mdx b/web/docs/guides/auth/intro.mdx new file mode 100644 index 00000000000..1d52730c4bf --- /dev/null +++ b/web/docs/guides/auth/intro.mdx @@ -0,0 +1,72 @@ +--- +id: intro +title: Supabase Auth +sidebar_label: Introduction +description: Use Supabase to Authenticate and Authorize your users. +# hide_table_of_contents: true +--- + +import Link from '@docusaurus/Link' +import Tabs from '@theme/Tabs' +import TabItem from '@theme/TabItem' +import providers from '@site/src/data/authProviders' + +Supabase Auth is designed to work with Postgres. There are two parts to every Auth system: + +- Authentication: should this person be allowed in? If yes, who are they? +- Authorization: once they are in, what are they allowed to do? + +## Authentication + +You can authenticate your users in several ways: + +- Email & password. +- Magic links (one-click logins). +- Social providers. +- Phone logins. + +
+
+ {providers.map((x) => ( +
+ +
+
+ {x.logo && {x.name}} +

{x.name}

+

+ {x.official ? + Official + : + + Unofficial + + } +

+
+
+
+ Platform: + {x.platform.toString()} +
+
+ Hosted: + {x.selfHosted.toString()} +
+
+
+ +
+ ))} +
+
+ + +## Authorization + + +When you need granular authorization rules, nothing beats PostgreSQL's Row Level Security (RLS). + +Policies are PostgreSQL's rule engine. They are incredibly powerful and flexible, allowing you to write complex SQL rules which fit your unique business needs. + +Get started with our [Row Level Security Guides](/docs/guides/auth/row-level-security). \ No newline at end of file diff --git a/web/docs/guides/auth/managing-user-data.mdx b/web/docs/guides/auth/managing-user-data.mdx index bf55d3d18cf..ed1e169a1da 100644 --- a/web/docs/guides/auth/managing-user-data.mdx +++ b/web/docs/guides/auth/managing-user-data.mdx @@ -76,4 +76,35 @@ const { data: profile } = await supabase If you need to fetch a full list of user profiles, we supply a `service_key` which you can use with your API and Client Libraries to bypass Row Level Security. -Make sure you _NEVER_ expose this publicly. But it can be used on the server-side to fetch all of the profiles. \ No newline at end of file +Make sure you _NEVER_ expose this publicly. But it can be used on the server-side to fetch all of the profiles. + + +## Advanced techniques + +### Using triggers + +If you want to add a row to your `public.users` table every time a user signs up, you can use triggers. +If the trigger fails however, it could block the user sign ups - so make sure that the code is well-tested. + +For example: + +```sql +-- inserts a row into public.users +create function public.handle_new_user() +returns trigger +language plpgsql +security definer +search_path = public +as $$ +begin + insert into public.users (id) + values (new.id); + return new; +end; +$$; + +-- trigger the function every time a user is created +create trigger on_auth_user_created + after insert on auth.users + for each row execute procedure public.handle_new_user(); +``` \ No newline at end of file diff --git a/web/docs/guides/auth/row-level-security.mdx b/web/docs/guides/auth/row-level-security.mdx new file mode 100644 index 00000000000..12ec835ad4d --- /dev/null +++ b/web/docs/guides/auth/row-level-security.mdx @@ -0,0 +1,313 @@ +--- +id: row-level-security +title: Row Level Security +description: Secure your data using Postgres Row Level Security. +--- + +When you need granular authorization rules, nothing beats PostgreSQL's [Row Level Security (RLS)](https://www.postgresql.org/docs/current/ddl-rowsecurity.html). + +[Policies](https://www.postgresql.org/docs/current/sql-createpolicy.html) are PostgreSQL's rule engine. They are incredibly powerful and flexible, allowing you to write complex SQL rules which fit your unique business needs. + + + + +## Policies + +Policies are easy to understand once you get the hang of them. Each policy is attached to a table, and the policy is executed +every time a table is accessed. +You can just think of them as adding a `WHERE` clause to every query. For example a policy like this ... + +```sql +create policy "Individuals can view their own todos." + on todos for select + using ( auth.uid() = user_id ); +``` + +.. would translate to this whenever a user tries to select from the todos table: + +```sql +select * +from todos +where auth.uid() = todos.user_id; -- Policy is implicitly added. +``` + +## Helper Functions + +Supabase provides you with a few easy functions that you can use with your policies. + + +### `auth.uid()` + +Returns the ID of the user making the request. + +### `auth.role()` + +Returns the role of the user making the request. In most cases this is either `authenticated` or `anon`. + +### `auth.email()` + +Retuns the email of the user making the request. + +## Examples + +Here are some examples to show you the power of PostgreSQL's RLS. + +### Allow read access + +```sql +-- 1. Create table +create table profiles ( + id uuid references auth.users, + avatar_url text +); + +-- 2. Enable RLS +alter table profiles + enable row level security; + +-- 3. Create Policy +create policy "Public profiles are viewable by everyone." + on profiles for select using ( + true + ); +``` + +1. Creates a table called `profiles` in the public schema (default schema). +2. Enables Row Level Security. +3. Creates a policy which allows all `select` queries to run. + +### Restrict updates + +```sql +-- 1. Create table +create table profiles ( + id uuid references auth.users, + avatar_url text +); + +-- 2. Enable RLS +alter table profiles + enable row level security; + +-- 3. Create Policy +create policy "Users can update their own profiles." + on profiles for update using ( + auth.uid() = id + ); +``` + +1. Creates a table called `profiles` in the public schema (default schema). +2. Enables RLS. +3. Creates a policy which allows logged in users to update their own data. + +### Policies with joins + +Policies can even include table joins. This example shows how you can query "external" tables to build more advanced rules. + +```sql +create table teams ( + id serial primary key, + name text +); + +-- 2. Create many to many join +create table members ( + team_id bigint references teams, + user_id uuid references auth.users +); + +-- 3. Enable RLS +alter table teams + enable row level security; + +-- 4. Create Policy +create policy "Team members can update team details if they belong to the team." + on teams + for update using ( + auth.uid() in ( + select user_id from members + where team_id = id + ) + ); +``` + +### Policies with security definer functions + +Policies can also make use of `security definer functions`. This is useful in a many-to-many relationship where you want to restrict access to the linking table. Following the `teams` and `members` example from above, this example shows how you can use security definer function in combination with a policy to control access to the `members` table. + +```sql +-- 1. Follow example for 'Policies with joins' above + +-- 2. Enable RLS +alter table members + enable row level security + +-- 3. Create security definer function +create or replace function get_teams_for_authenticated_user() +returns setof bigint +language sql +security definer +set search_path = public +stable +as $$ + select team_id + from members + where user_id = auth.uid() +$$; + +-- 4. Create Policy +create policy "Team members can update team members if they belong to the team." + on members + for all using ( + team_id in ( + select get_teams_for_authenticated_user() + ) + ); + +``` + +### Verifying email domains + +Postgres has a function `right(string, n)` that returns the rightmost n characters of a string. +You could use this to match staff member's email domains. + +```sql +-- 1. Create table +create table leaderboard ( + id uuid references auth.users, + high_score bigint +); + +-- 2. Enable RLS +alter table leaderboard + enable row level security; + +-- 3. Create Policy +create policy "Only Blizzard staff can update leaderboard" + on leaderboard + for update using ( + right(auth.email(), 13) = '@blizzard.com' + ); +``` + +### Time to live for rows + +Policies can also be used to implement TTL or time to live feature that you see in Instagram stories or Snapchat. +In the following example, rows of `stories` table are available only if they have been created within the last 24 hours. + +```sql +-- 1. Create table +create table if not exists stories ( + id uuid not null primary key DEFAULT uuid_generate_v4(), + created_at timestamp with time zone default timezone('utc' :: text, now()) not null, + content text not null +); + +-- 2. Enable RLS +alter table stories + enable row level security; + +-- 3. Create Policy +create policy "Stories are live for a day" + on stories + for select using ( + created_at > (current_timestamp - interval '1 day') + ); +``` + +### Advanced policies + +Use the full power of SQL to build extremely advanced rules. + +In this example, we will create a `posts` and `comments` tables and then create a policy that depends on another policy. +(In this case, the comments policy depends on the posts policy.) + +```sql +create table posts ( + id serial primary key, + creator_id uuid not null references auth.users(id), + title text not null, + body text not null, + publish_date date not null default now(), + audience uuid[] null -- many to many table omitted for brevity +); + +create table comments ( + id serial primary key, + post_id int not null references posts(id) on delete cascade, + user_id uuid not null references auth.users(id), + body text not null, + comment_date date not null default now() +); + +create policy "Creator can see their own posts" +on posts +for select +using ( + auth.uid() = posts.creator_id +); + +create policy "Logged in users can see the posts if they belong to the post 'audience'." +on posts +for select +using ( + auth.uid() = any (posts.audience) +); + +create policy "Users can see all comments for posts they have access to." +on comments +for select +using ( + exists ( + select 1 from posts + where posts.id = comments.post_id + ) +); +``` + + +## Tips + +### Disable realtime for private tables + +Our realtime server doesn't provide per-user security. Until we build a more robust auth system for WebSockets, you can disable realtime functionality for any private tables. To do this, you can manage the underlying Postgres replication publication: + +```sql +/** + * REALTIME SUBSCRIPTIONS + * Only allow realtime listening on public tables. + */ + +begin; + -- remove the realtime publication + drop publication if exists supabase_realtime; + + -- re-create the publication but don't enable it for any tables + create publication supabase_realtime; +commit; + +-- add a table to the publication +alter publication supabase_realtime add table products; + +-- add other tables to the publication +alter publication supabase_realtime add table posts; +``` + +We're in the process of building [enhanced realtime security](https://github.com/supabase/walrus). + +### You don't have to use policies + +You can also put your authorization rules in your middleware, similar to how you would create security rules with any other `backend <-> middleware <-> frontend` architecture. + +Policies are a tool. In the case of "serverless/Jamstack" setups, they are especially effective because you don't have to deploy any middleware at all. + +However, if you want to use another authorization method for your applications, that's also fine. Supabase is "just Postgres", so if your application +works with Postgres, then it also works with Supabase. + +Tip: Make sure to enable RLS for all your tables, so that your tables are inaccessible. Then use the "Service" which we provide, which is designed to bypass RLS. + + +### Never use a service key on the client + +Supabase provides special "Service" keys, which can be used to bypass all RLS. +These should never be used in the browser or exposed to customers, but they are useful for administrative tasks. diff --git a/web/sidebars.js b/web/sidebars.js index 174de26686b..1676df931b6 100755 --- a/web/sidebars.js +++ b/web/sidebars.js @@ -136,10 +136,10 @@ module.exports = { label: 'Auth', collapsed: false, items: [ - 'guides/auth/managing-user-data', + 'guides/auth/intro', { type: 'category', - label: 'External Providers', + label: 'Authentication', collapsed: true, items: [ 'guides/auth/auth-apple', @@ -154,6 +154,12 @@ module.exports = { 'guides/auth/auth-twilio', ], }, + { + type: 'category', + label: 'Authorization', + collapsed: true, + items: ['guides/auth/row-level-security', 'guides/auth/managing-user-data'], + }, { type: 'category', label: 'Deep Dive', diff --git a/web/src/css/custom.css b/web/src/css/custom.css index 405599e4ef1..ac98141f03c 100755 --- a/web/src/css/custom.css +++ b/web/src/css/custom.css @@ -61,6 +61,8 @@ --custom-primary-light: #65d9a5; --custom-primary-lighter: #9fe7c7; --custom-primary-lightest: #c5f1dd; + --custom-primary-rgba: RGBA(36, 180, 126, 1); + --custom-primary-rgb: 36, 180, 126; --custom-background-color: #1f1f1f; --custom-background-color-highlight: #fff; --custom-background-color-diff: #f5f6f7; @@ -1297,3 +1299,35 @@ h4.method-list-item-label .method-list-item-validation { overflow: hidden; border: 2px solid var(--custom-border-color); } + +.badge--official { + border-radius: 3px; + font-size: 0.6rem; + font-weight: 400; + text-transform: uppercase; + border-color: var(--custom-primary); + background-color: rgba(var(--custom-primary-rgb), 0.8); +} +.badge--unofficial { + border-radius: 3px; + font-size: 0.6rem; + font-weight: 400; + text-transform: uppercase; + color: var(--custom-content-color-lightest); + background: rgba(0, 0, 0, 0.1); + border-color: rgba(0, 0, 0, 0.05); +} + +:root[data-theme='dark'] .badge--official { + background-color: rgba(var(--custom-primary-rgb), 0.5); +} +:root[data-theme='dark'] .badge--unofficial { + border-color: rgba(255, 255, 255, 0.1); + background: rgba(255, 255, 255, 0.05); +} +.code-block { + border-radius: 3px; + font-family: 'office code pro'; + border: 1px solid var(--custom-border-color); + padding: 2px 6px; +} \ No newline at end of file diff --git a/web/src/data/authProviders.js b/web/src/data/authProviders.js new file mode 100644 index 00000000000..047b2744fe1 --- /dev/null +++ b/web/src/data/authProviders.js @@ -0,0 +1,130 @@ +const authProviders = [ + // { + // name: 'Email', + // // logo: '/img/libraries/dart-icon.svg', + // href: '/docs/guides/auth/auth-apple', + // official: true, + // supporter: 'Supabase', + // platform: true, + // selfHosted: true, + // }, + // { + // name: 'Magic Links', + // // logo: '/img/libraries/dart-icon.svg', + // href: '/docs/guides/auth/auth-apple', + // official: true, + // supporter: 'Supabase', + // platform: true, + // selfHosted: true, + // }, + { + name: 'Apple', + // logo: '/img/libraries/dart-icon.svg', + href: '/docs/guides/auth/auth-apple', + official: true, + supporter: 'Supabase', + platform: true, + selfHosted: true, + }, + { + name: 'Azure', + // logo: '/img/libraries/dart-icon.svg', + href: '/docs/guides/auth/auth-apple', + official: false, + supporter: 'TBD', + platform: false, + selfHosted: true, + }, + { + name: 'Bitbucket', + // logo: '/img/libraries/dart-icon.svg', + href: '/docs/guides/auth/auth-bitbucket', + official: true, + supporter: 'Supabase', + platform: true, + selfHosted: true, + }, + { + name: 'Discord', + // logo: '/img/libraries/dart-icon.svg', + href: '/docs/guides/auth/auth-discord', + official: true, + supporter: 'Supabase', + platform: true, + selfHosted: true, + }, + { + name: 'Facebook', + // logo: '/img/libraries/dart-icon.svg', + href: '/docs/guides/auth/auth-facebook', + official: true, + supporter: 'Supabase', + platform: true, + selfHosted: true, + }, + { + name: 'GitHub', + // logo: '/img/libraries/dart-icon.svg', + href: '/docs/guides/auth/auth-github', + official: true, + supporter: 'Supabase', + platform: true, + selfHosted: true, + }, + { + name: 'GitLab', + // logo: '/img/libraries/dart-icon.svg', + href: '/docs/guides/auth/auth-gitlab', + official: true, + supporter: 'Supabase', + platform: true, + selfHosted: true, + }, + { + name: 'Google', + // logo: '/img/libraries/dart-icon.svg', + href: '/docs/guides/auth/auth-google', + official: true, + supporter: 'Supabase', + platform: true, + selfHosted: true, + }, + // { + // name: 'MessageBird', + // // logo: '/img/libraries/dart-icon.svg', + // href: '/docs/guides/auth/auth-twilio', + // official: false, + // supporter: 'Messagebird', + // platform: false, + // selfHosted: true, + // }, + { + name: 'Twitter', + // logo: '/img/libraries/dart-icon.svg', + href: '/docs/guides/auth/auth-twitter', + official: true, + supporter: 'Supabase', + platform: true, + selfHosted: true, + }, + { + name: 'Twitch', + // logo: '/img/libraries/dart-icon.svg', + href: '/docs/guides/auth/auth-twitch', + official: true, + supporter: 'Supabase', + platform: true, + selfHosted: true, + }, + { + name: 'Twilio', + // logo: '/img/libraries/dart-icon.svg', + href: '/docs/guides/auth/auth-twilio', + official: true, + supporter: 'Supabase', + platform: true, + selfHosted: true, + }, +] + +export default authProviders \ No newline at end of file