diff --git a/apps/reference/docs/guides/cli/cicd-workflow.mdx b/apps/reference/docs/guides/cli/cicd-workflow.mdx
index 875d240c300..07afed16df8 100644
--- a/apps/reference/docs/guides/cli/cicd-workflow.mdx
+++ b/apps/reference/docs/guides/cli/cicd-workflow.mdx
@@ -348,6 +348,24 @@ Once pushed, check that the migration version is up to date for both local and r
supabase migration list
```
+### Permission denied on db remote commit
+
+If you have been using Supabase hosted projects for a long time, you might encounter the following permission error when executing `db remote commit`.
+
+```bash
+Error: Error running pg_dump on remote database: pg_dump: error: query failed: ERROR: permission denied for table _type
+
+pg_dump: error: query was: LOCK TABLE "graphql"."_type" IN ACCESS SHARE MODE
+```
+
+To resolve this error, you need to grant `postgres` role permissions to `graphql` schema. You can do that by running the following query from Supabase dashboard's SQL Editor.
+
+```sql
+grant all on all tables in schema graphql to postgres, anon, authenticated, service_role;
+grant all on all functions in schema graphql to postgres, anon, authenticated, service_role;
+grant all on all sequences in schema graphql to postgres, anon, authenticated, service_role;
+```
+
### Permission denied on db push
If you created a table through Supabase dashboard, and your new migration script contains `ALTER TABLE` statements, you might run into permission error when applying them on staging or production databases.
@@ -358,12 +376,14 @@ ERROR: must be owner of table employees (SQLSTATE 42501); while executing migrat
This is because tables created through Supabase dashboard are owned by `supabase_admin` role while the migration scripts executed through CLI are under `postgres` role.
-One way to solve this is to grant `postgres` role additional privileges through the SQL Editor available on Supabase dashboard. For example, the following command grants postgres permissions to alter any table in the public schema.
+One way to solve this is to reassign the owner of those tables to `postgres` role. For example, if your table is named `users` in the public schema, you can run the following command to reassign owner.
```sql
-GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO postgres;
+ALTER TABLE users OWNER TO postgres;
```
+Apart from tables, you also need to reassign owner of other entities using their respective commands, including [types](https://www.postgresql.org/docs/current/sql-alterschema.html), [functions](https://www.postgresql.org/docs/current/sql-alterroutine.html), and [schemas](https://www.postgresql.org/docs/current/sql-altertype.html).
+
### Rebasing new migrations
Sometimes your teammate may merge a new migration file to git main branch, and now you need to rebase your local schema changes on top.
diff --git a/apps/reference/docs/guides/integrations/prisma.mdx b/apps/reference/docs/guides/integrations/prisma.mdx
index 1915b3a8b9f..e7f8d517ccc 100644
--- a/apps/reference/docs/guides/integrations/prisma.mdx
+++ b/apps/reference/docs/guides/integrations/prisma.mdx
@@ -62,7 +62,7 @@ This project comes with TypeScript configured and has the following structure.
### Configuring the project to use PostgreSQL
Go ahead and delete the `prisma/dev.db` file because we will be switching to PostgreSQL.
-Next, inside the `prisma/.env` file, update the value of the `DATABASE_URL` variable to the connection string you got in **step 3**. The URL might look as follows:
+Next, inside the `prisma/.env` file, update the value of the `DATABASE_URL` variable to the connection string you got in **step 1**. The URL might look as follows:
```env
# prisma/.env
@@ -122,7 +122,7 @@ This will create a `prisma/migrations` folder inside your `prisma` directory and
If you’re working in a serverless environment (for example Node.js functions hosted on AWS Lambda, Vercel or Netlify Functions), you need to set up [connection pooling](https://www.prisma.io/docs/guides/performance-and-optimization/connection-management#serverless-environments-faas) using a tool like [PgBouncer](https://www.pgbouncer.org/). That’s because every function invocation may result in a [new connection to the database](https://www.prisma.io/docs/guides/performance-and-optimization/connection-management#the-serverless-challenge). Supabase [supports connection management using PgBouncer](https://supabase.io/blog/2021/04/02/supabase-pgbouncer#what-is-connection-pooling) and are enabled by default.
Go to the **Database** page from the sidebar in the Supabase dashboard and navigate to **connection pool** settings

-When running migrations you need to use the non pooled connection URL (like the one we used in **step 4**). However, when deploying your app, you’ll use the pooled connection URL and add the `?pgbouncer=true` flag to the PostgreSQL connection URL. To minimize the number of concurrent connections, setting the `connection_limit` to `1` is also recommended. So the URL might look as follows:
+When running migrations you need to use the non pooled connection URL (like the one we used in **step 1**). However, when deploying your app, you’ll use the pooled connection URL and add the `?pgbouncer=true` flag to the PostgreSQL connection URL. To minimize the number of concurrent connections, setting the `connection_limit` to `1` is also recommended. So the URL might look as follows:
```env
# prisma/.env
diff --git a/apps/reference/docs/guides/with-angular.mdx b/apps/reference/docs/guides/with-angular.mdx
index 93389bfc2df..2d4dc88df31 100644
--- a/apps/reference/docs/guides/with-angular.mdx
+++ b/apps/reference/docs/guides/with-angular.mdx
@@ -33,7 +33,7 @@ If you want to do it yourself, let's get started!
### GitHub
-Whenever you get stuck at any point, take a look at [this repo](https://github.com/angular-supa/supabase-angular-user-management).
+Whenever you get stuck at any point, take a look at [this repo](https://github.com/supabase/examples/tree/main/supabase-js-v2/user-management/angular-user-management).
## Project set up
@@ -180,281 +180,365 @@ export const environment = {
Now that we have the API credentials in place, let's create a **SupabaseService** with `ng g s supabase` to initialize the Supabase client and implement functions to communicate with the Supabase API.
```ts title="src/app/supabase.service.ts"
-import { Injectable } from '@angular/core'
+import { Injectable } from '@angular/core';
import {
AuthChangeEvent,
+ AuthSession,
createClient,
Session,
SupabaseClient,
-} from '@supabase/supabase-js'
-import { environment } from '../environments/environment'
+ User,
+} from '@supabase/supabase-js';
+import { environment } from 'src/environments/environment';
+import { Database } from 'src/schema';
export interface Profile {
- username: string
- website: string
- avatar_url: string
+ id?: string;
+ username: string;
+ website: string;
+ avatar_url: string;
}
@Injectable({
providedIn: 'root',
})
export class SupabaseService {
- private supabase: SupabaseClient
+ private supabase: SupabaseClient;
+ _session: AuthSession | null = null;
constructor() {
this.supabase = createClient(
environment.supabaseUrl,
environment.supabaseKey
- )
- }
-
- get user() {
- return this.supabase.auth.user()
+ );
}
get session() {
- return this.supabase.auth.session()
+ this.supabase.auth.getSession().then(({ data }) => {
+ this._session = data.session;
+ })
+ return this._session;
}
- get profile() {
+ profile(user: User) {
return this.supabase
.from('profiles')
.select(`username, website, avatar_url`)
- .eq('id', this.user?.id)
- .single()
+ .eq('id', user.id)
+ .single();
}
authChanges(
callback: (event: AuthChangeEvent, session: Session | null) => void
) {
- return this.supabase.auth.onAuthStateChange(callback)
+ return this.supabase.auth.onAuthStateChange(callback);
}
signIn(email: string) {
- return this.supabase.auth.signIn({ email })
+ return this.supabase.auth.signInWithOtp({ email });
}
signOut() {
- return this.supabase.auth.signOut()
+ return this.supabase.auth.signOut();
}
updateProfile(profile: Profile) {
const update = {
...profile,
- id: this.user?.id,
updated_at: new Date(),
- }
+ };
- return this.supabase.from('profiles').upsert(update, {
- returning: 'minimal', // Don't return the value after inserting
- })
+ return this.supabase.from('profiles').upsert(update);
}
downLoadImage(path: string) {
- return this.supabase.storage.from('avatars').download(path)
+ return this.supabase.storage.from('avatars').download(path);
}
uploadAvatar(filePath: string, file: File) {
- return this.supabase.storage.from('avatars').upload(filePath, file)
+ return this.supabase.storage.from('avatars').upload(filePath, file);
}
}
```
-And one optional step is to update the CSS file `src/index.css` to make the app look nice.
-You can find the full contents of this file [here](https://raw.githubusercontent.com/angular-supa/supabase-angular-user-management/main/src/styles.css).
+Optionally, update [src/styles.css](https://raw.githubusercontent.com/supabase/examples/main/supabase-js-v2/user-management/angular-user-management/src/styles.css) to style the app.
### Set up a Login component
Let's set up an Angular component to manage logins and sign ups. We'll use Magic Links, so users can sign in with their email without using passwords.
Create an **AuthComponent** with `ng g c auth` Angular CLI command.
-```ts title="src/app/auth.component.ts"
-import { Component } from '@angular/core'
-import { SupabaseService } from './supabase.service'
+```ts title="src/app/auth/auth.component.ts"
+import { Component, OnInit } from '@angular/core';
+import { FormBuilder } from '@angular/forms';
+import { SupabaseService } from '../supabase.service';
@Component({
selector: 'app-auth',
- template: `
-
+```
+
+`app.module.ts` also needs to be modified to include the `ReactiveFormsModule` from the `@angular/forms` package.
+
+```ts title="src/app/app.module.ts"
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+
+import { AppComponent } from './app.component';
+import { AuthComponent } from './auth/auth.component';
+import { AccountComponent } from './account/account.component';
+import { ReactiveFormsModule } from '@angular/forms';
+import { AvatarComponent } from './avatar/avatar.component';
+
+@NgModule({
+ declarations: [
+ AppComponent,
+ AuthComponent,
+ AccountComponent,
+ AvatarComponent,
+ ],
+ imports: [BrowserModule, ReactiveFormsModule],
+ providers: [],
+ bootstrap: [AppComponent],
+})
+export class AppModule {}
+```
+
Once that's done, run this in a terminal window:
```bash
@@ -474,110 +558,141 @@ Every Supabase project is configured with [Storage](/docs/guides/storage) for ma
Let's create an avatar for the user so that they can upload a profile photo.
Create an **AvatarComponent** with `ng g c avatar` Angular CLI command.
-```ts title="src/app/avatar.component.ts"
-import { Component, EventEmitter, Input, Output } from '@angular/core'
-import { SupabaseService } from './supabase.service'
-import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'
+```ts title="src/app/avatar/avatar.component.ts"
+import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { SafeResourceUrl, DomSanitizer } from '@angular/platform-browser';
+import { SupabaseService } from '../supabase.service';
@Component({
selector: 'app-avatar',
- template: `
-
+```
+
### Add the new widget
And then we can add the widget on top of the **AccountComponent** html template:
-```ts title="src/app/account.component.ts"
-template: `
-
-
+```html title="src/app/account.component.html"
+
+```
-
-`
+And add an `updateAvatar` function along with an `avatarUrl` getter to the **AccountComponent** typescript file:
+
+```ts title="src/app/account.component.ts"
+@Component({
+ selector: 'app-account',
+ templateUrl: './account.component.html',
+ styleUrls: ['./account.component.css'],
+})
+export class AccountComponent implements OnInit {
+ // ...
+ get avatarUrl() {
+ return this.updateProfileForm.value.avatar_url as string;
+ }
+
+ async updateAvatar(event: string): Promise {
+ this.updateProfileForm.patchValue({
+ avatar_url: event,
+ });
+ await this.updateProfile();
+ }
+ // ...
+}
```
## Next steps
diff --git a/apps/www/_blog/2022-10-14-postgres-full-text-search-vs-the-rest.mdx b/apps/www/_blog/2022-10-14-postgres-full-text-search-vs-the-rest.mdx
index 458a397fecf..f96545c783a 100644
--- a/apps/www/_blog/2022-10-14-postgres-full-text-search-vs-the-rest.mdx
+++ b/apps/www/_blog/2022-10-14-postgres-full-text-search-vs-the-rest.mdx
@@ -206,7 +206,7 @@ We'll focus on the end-user-centric meaning of performance here (query speed).
Postgres is capable of loading CSVs, but since we'll be using other search engines as well, let's convert to format that's much easier to use and process - [Newline Delimited JSON](https://dataprotocols.org/ndjson/).
-After a few lines of code and one `[csv2ndjson.mjs` script](https://github.com/VADOSWARE/fts-benchmark/blob/main/src/util/csv2ndjson.mjs) later, we have a `movies.ndjson.json` full of JSON documents that we can easily ingest into any search engine (or other database for that matter!).
+After a few lines of code and one [`csv2ndjson.mjs` script](https://github.com/VADOSWARE/fts-benchmark/blob/main/src/util/csv2ndjson.mjs) later, we have a `movies.ndjson.json` full of JSON documents that we can easily ingest into any search engine (or other database for that matter!).
### Inserting the data
@@ -332,7 +332,7 @@ There's a _lot_ of tuning left undone here, but a few points stand out right awa
- Postgres FTS is quite close performance-wise to many other solutions, at least in their default configuration.
- Only Typesense and MeiliSearch properly handled mis-spellings (the "suprman" query).
- Typesense was relatively strict with matches compared to other engines.
-- OpenSearch was _very_ fast with ingest, but also failed with the misspelling out of the box.
+- OpenSearch was _very_ fast with ingest, but the default configuration doesn't index misspellings.
- In-memory SQLite is by far the fastest, and PG isn't too far behind for this small data set.
## Feedback from the other products
diff --git a/apps/www/components/CaseStudies/benchmark.tsx b/apps/www/components/CaseStudies/benchmark.tsx
index 630e7b6e7cf..1e2a218bf1a 100644
--- a/apps/www/components/CaseStudies/benchmark.tsx
+++ b/apps/www/components/CaseStudies/benchmark.tsx
@@ -31,11 +31,6 @@ const Benchmark = () => {
-
)
diff --git a/apps/www/lib/redirects.js b/apps/www/lib/redirects.js
index 97e6e3bfc04..03cf6382e91 100644
--- a/apps/www/lib/redirects.js
+++ b/apps/www/lib/redirects.js
@@ -1415,4 +1415,50 @@ module.exports = [
// source: '/docs/reference/javascript/auth-api-updateuserbyid',
// destination: '/docs/reference/javascript/auth-admin-updateuserbyid',
// },
+
+ // v1 to v2 redirects
+
+ // signIn method is now split into signInWithPassword ,signInWithPasswordless ,signInWithOAuth
+ // send traffic to v1 docs instead
+ {
+ permanent: true,
+ source: '/docs/reference/javascript/auth-signin',
+ destination: '/docs/reference/javascript/v1/auth-signin',
+ },
+ // auth.session renamed to auth.getSession
+ // send to new v2 docs version
+ {
+ permanent: true,
+ source: '/docs/reference/javascript/auth-session',
+ destination: '/docs/reference/javascript/auth-getsession',
+ },
+ // Removed sendMobileOTP in favor of signInWithOtp
+ // send traffic to new v2 docs instead
+ {
+ permanent: true,
+ source: '/docs/reference/javascript/auth-api-sendmobileotp',
+ destination: '/docs/reference/javascript/auth-signinwithotp',
+ },
+ // Replaced update with updateUser
+ {
+ permanent: true,
+ source: '/docs/reference/javascript/auth-update',
+ destination: '/docs/reference/javascript/auth-updateuser',
+ },
+ // realtime methods been replaced with new names
+ {
+ permanent: true,
+ source: '/docs/reference/javascript/removesubscription',
+ destination: '/docs/reference/javascript/v1/removesubscription',
+ },
+ {
+ permanent: true,
+ source: '/docs/reference/javascript/removeallsubscriptions',
+ destination: '/docs/reference/javascript/v1/removeallsubscriptions',
+ },
+ {
+ permanent: true,
+ source: '/docs/reference/javascript/getsubscriptions',
+ destination: '/docs/reference/javascript/v1/getsubscriptions',
+ },
]
diff --git a/apps/www/pages/security.mdx b/apps/www/pages/security.mdx
index 43867d08290..372502178a4 100644
--- a/apps/www/pages/security.mdx
+++ b/apps/www/pages/security.mdx
@@ -52,7 +52,7 @@ export const Section = ({ children, icon, img }) => (
### SOC 2
-Supabase is SOC2 Type 1 compliant. Enterprise customers can request a copy of our SOC2 through our [Security Portal](https://security.supabase.com).
+Supabase is SOC2 Type 1 compliant. Enterprise customers can request a copy of our SOC2 [here](https://supabase.com/legal/soc2).
@@ -126,8 +126,7 @@ In addition to internal security reviews, we use various tools to scan our code
Security Portal
-Access Supabase’s security and compliance documents on our Security Portal, such as
-penetration testing and audit reports.
+Access more of Supabase’s security on our Security Portal, such as penetration testing and audit reports.