From 48a140c9e445dfdb19c6385fa9ddf13de8fcc714 Mon Sep 17 00:00:00 2001 From: awalias Date: Tue, 16 Mar 2021 09:56:17 +0800 Subject: [PATCH 01/70] chore: adds repl example to jwt doc --- web/docs/learn/auth-deep-dive/jwts.md | 158 +++++++++++++++++++++++++- 1 file changed, 154 insertions(+), 4 deletions(-) diff --git a/web/docs/learn/auth-deep-dive/jwts.md b/web/docs/learn/auth-deep-dive/jwts.md index a2c2d7d1c4d..783dcc83d10 100644 --- a/web/docs/learn/auth-deep-dive/jwts.md +++ b/web/docs/learn/auth-deep-dive/jwts.md @@ -13,6 +13,156 @@ An introduction to JWTs and how they are used in Supabase Auth +### What are JSON Web Tokens (JWTs)? + +JWTs are JSON objects that are encoded and signed and sent around as a string. They are distributed to users of a service or website, who can later show the JWT to the website or service, as proof that they have the right to access certain content. + +What exactly do we mean when we say 'encoded' and 'signed'? + +Well, the JSON object starts out looking something like this: + +```js +{ + "sub": "0001", + "name": "Sam Vimes", + "iat": 1516239022, + "exp": 1518239022 +} +``` + +`sub` is the "subject", which is usually the uuid of the user. `name` is self explanitory, and `iat` is the unix timestamp at which the token was created. Many JWTs will also have an `exp` which is the data at which the token is set to expire, and can no longer be used. These are some of the standard fields you may find in a JWT, but you can pretty much store whatever you want in there, for example: + +```js +{ + "sub": "0002", + "name": "Věra Hrabánková", + "iat": 1516239022, + "exp": 1518239022, + "theme": { + "primary" : "#D80C14", + "secondary" : "#FFFFFF" + } +} +``` + +Just note that, the more data you store in your token, the longer the encoded string will be. + +When we want to send the JWT to the user, we first encode the data using an algorithm such as `HS256`, there are many libraries (and several different algorithms) that can be used to do this encoding/decoding such as [jsonwebtoken](https://www.npmjs.com/package/jsonwebtoken). I made a repl [here](https://replit.com/@awalias/jsonwebtokens#index.js) so you can try it for yourself. The signing is as simple as: + +```js +// from https://replit.com/@awalias/jsonwebtokens#index.js +let token = jwt.sign({ name: 'Sam Vimes' }, 'some-secret'); +``` + +And the resulting string will look like this: + +```js +eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIwMDAxIiwibmFtZSI6IlNhbSBWaW1lcyIsImlhdCI6MTUxNjIzOTAyMiwiZXhwIjoxNTE4MjM5MDIyfQ.zMcHjKlkGhuVsiPIkyAkB2rjXzyzJsMMgpvEGvGtjvA +``` + +You will notice that the string is actually made up of three components which we'll address one-by-one: + +The first segment `eyJhbGciOiJIUzI1NiJ9` is known as the "header" and when decoded just tells us which algorithm was used to do the encoding: + +```js +{ + "alg": "HS256" +} +``` + +The second segment `eyJzdWIiOiIwMDAxIiwibmFtZSI6IlNhbSBWaW1lcyIsImlhdCI6MTUxNjIzOTAyMiwiZXhwIjoxNTE4MjM5MDIyfQ` contains our original payload: + +```js +{ + "sub": "0001", + "name": "Sam Vimes", + "iat": 1516239022, + "exp": 1518239022 +} +``` + +Now the last segment `zMcHjKlkGhuVsiPIkyAkB2rjXzyzJsMMgpvEGvGtjvA` is the signature itself. Which is the part used by the website or service provider to verify that a token sent by some user is legitimate. It is produced in the first instance by running the cryptographic function HS256 on the following input: + +```js +HMACSHA256( + base64UrlEncode(header) + "." + + base64UrlEncode(payload) + +) +``` + +You can test out minting your own tokens on https://jwt.io/ + +It is important to note that anyone who possesses the `jwt_secret` here can create new tokens, and also verify existing ones. More advanced JWT algorithms use two secrets, one for the creation of tokens, and a separate one to verify the validity of signed tokens. + +You may ask yourself why JWTs are so popular all of a sudden? The answer is that with the mass adoption of microservice architecture, we were in a situation where several distinct microservices (APIs, websites, servers etc.) want to easily validate that a user is who they say they are, or are in other words a "logged-in" user. Traditional session tokens are no use here, they would require each microservice to either maintain a record of currently valid session tokens, or query a central database each time a user wants to access a resource, to check the validity of the session token. Very inefficient indeed. JWT based auth in this sense is decentralised, since anyone with the `jwt_secret` can verify a token, without needing access to a centralised database. + +Note: one downside of JWTs is that they are not easily voidable, like session tokens. If a JWT is leaked to a malicious actor, they will be able to redeem it anywhere until the expiry date is reached. Unless of course the system owner updates the `jwt_secret` (which will of course invalidate *everyone's* existing tokens). + +### JWTs in Supabase + +In Supabase we issue JWTs for three different purposes. + +1. `anon key`: this key is used to bypass the Supabase API gateway and can be used in your client side code +2. `service role key`: this key has super admin rights, and can bypass your Row Level Security, do not put it in your client side code. Keep it private. +3. `user specific jwts`: these are tokens we issue to users who log into your project/service/website. It's the modern equivilent of a session token, and can be used by a user to access content or permissions specific to them. + +The first token here, the `anon key` token is for developers to send along with their API requests whenever they want to interact with their Supabase database. + +Let's say you want to read the names of all the rows in a table `colors`, we would make a request like: + +```bash +curl 'https://xscduanzzfseqszwzhcy.supabase.co/rest/v1/colors?select=name' \ +-H "apikey: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYW5vbiIsImlhdCI6MTYxNDIwNTE3NCwiZXhwIjoxOTI5NzgxMTc0fQ.-NBR1WnZyQGpRLdXJfgfpszoZ0EeE6KHatJsDPLIX8c" +``` + +if we put this token into https://jwt.io we see it decodes to: + +```js +{ + "role": "anon", + "iat": 1614205174, + "exp": 1929781174 +} +``` + +This JWT is signed by a `jwt_secret` specific to the developer's Supabase token (you can find this secret alongside this encoded "anon key" on your Dashboard under Settings > API page) and is required to get past the Supabase API gateway and access the developer's project. + +The idea with this particular key is that it's safe to put into your client, meaning it's ok if your end user's see this key. *But* only if you first enable Row Level Security, which is the topic of [Part Two](/docs/learn/auth-deep-dive/auth-row-level-security) in this series. + +The second key `service role key`, should only ever be used on one of your own servers or environments, and should never be shared with end users. You might use this token to do things like make batch inserts of data. + +The `user access token` is the JWT issued when you call for example: + +```js +supabase.auth.signIn({ email: 'lao.gimmie@gov.sg', password: 'They_Live_1988!' }) +``` + +This token should be passed in addition to the `apikey` header as an `Authorization Bearer` header like: + +```bash +curl 'https://xscduanzzfseqszwzhcy.supabase.co/rest/v1/colors?select=name' \ +-H "apikey: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYW5vbiIsImlhdCI6MTYxNDIwNTE3NCwiZXhwIjoxOTI5NzgxMTc0fQ.-NBR1WnZyQGpRLdXJfgfpszoZ0EeE6KHatJsDPLIX8c" \ +-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJhdXRoZW50aWNhdGVkIiwiZXhwIjoxNjE1ODI0Mzg4LCJzdWIiOiIwMzM0NzQ0YS1mMmEyLTRhYmEtOGM4YS02ZTc0OGY2MmExNzIiLCJlbWFpbCI6InNvbWVvbmVAZW1haWwuY29tIiwiYXBwX21ldGFkYXRhIjp7InByb3ZpZGVyIjoiZW1haWwifSwidXNlcl9tZXRhZGF0YSI6bnVsbCwicm9sZSI6ImF1dGhlbnRpY2F0ZWQifQ.I-_oSsJamtinGxniPETBf-ezAUwDW2sY9bJIThvdX9s" +``` + +You'll notice that this token is quite a bit longer since it contains information specific to the user such as: + +```js +{ + "aud": "authenticated", + "exp": 1615824388, + "sub": "0334744a-f2a2-4aba-8c8a-6e748f62a172", + "email": "d.l.solove@gmail.com", + "app_metadata": { + "provider": "email" + }, + "user_metadata": null, + "role": "authenticated" +} +``` + +Now that you understand what JWTs are and where they're used in Supabase, you can explore how to use them in combination with Row Level Security to start restricting access to certain tables, rows, and columns, in your postgres database: [Part Two: Row Level Security](/docs/learn/auth-deep-dive/auth-row-level-security) ### Resources @@ -22,8 +172,8 @@ An introduction to JWTs and how they are used in Supabase Auth ### Next steps -- Watch [Part Two: Row Level Security](/docs/learn/auth-deep-dive/auth-row-level-security) -- Watch [Part Three: Policies](/docs/learn/auth-deep-dive/auth-policies) -- Watch [Part Four: GoTrue](/docs/learn/auth-deep-dive/auth-gotrue) -- Watch [Part Five: Google Oauth](/docs/learn/auth-deep-dive/auth-google-oauth) +- [Part Two: Row Level Security](/docs/learn/auth-deep-dive/auth-row-level-security) +- [Part Three: Policies](/docs/learn/auth-deep-dive/auth-policies) +- [Part Four: GoTrue](/docs/learn/auth-deep-dive/auth-gotrue) +- [Part Five: Google Oauth](/docs/learn/auth-deep-dive/auth-google-oauth) - Sign up for Supabase: [app.supabase.io](https://app.supabase.io) \ No newline at end of file From 07549d35db2dae75396aaeca64624c51dae5a5ff Mon Sep 17 00:00:00 2001 From: awalias Date: Wed, 17 Mar 2021 09:53:00 +0800 Subject: [PATCH 02/70] fix: too awesome --- web/blog/2021-03-11-using-supabase-replit.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/blog/2021-03-11-using-supabase-replit.md b/web/blog/2021-03-11-using-supabase-replit.md index 725e34510a5..a1d357feec5 100644 --- a/web/blog/2021-03-11-using-supabase-replit.md +++ b/web/blog/2021-03-11-using-supabase-replit.md @@ -13,7 +13,7 @@ tags: - Postgres --- -[Replit.com](http://replit.com) is an awesome new browser based IDE where you can code alone or collaboratively with friends using their awesome multiplayer features! It's particularly useful for education, and sharing code examples with others. +[Replit.com](http://replit.com) is an awesome new browser based IDE where you can code alone or collaboratively with friends using their amazing multiplayer features! It's particularly useful for education, and sharing code examples with others. They support a ton of different languages and execution environments and even recently introduced a simple key value store you can use to persist data. From 0b91685aea5d92e8e571c0306fd877e0f7ccad27 Mon Sep 17 00:00:00 2001 From: awalias Date: Wed, 17 Mar 2021 09:54:56 +0800 Subject: [PATCH 03/70] fix: not comment list --- web/blog/2021-03-11-using-supabase-replit.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/web/blog/2021-03-11-using-supabase-replit.md b/web/blog/2021-03-11-using-supabase-replit.md index a1d357feec5..55bba8ee526 100644 --- a/web/blog/2021-03-11-using-supabase-replit.md +++ b/web/blog/2021-03-11-using-supabase-replit.md @@ -91,12 +91,12 @@ main() Once this is working, if you want to learn more about the [query interface](https://supabase.io/docs/client/filter) you might want to try some of these challenges: -```jsx -// 1. List all the countries in Antarctica -// 2. Fetch the iso3 code of the country with ID 3 -// 3. List the countries with 'Island' in the name -// 4. Count the number of countries that start with 'Z' or 'Q' -// 5. Fetch all the Countries where continents is null +``` + 1. List all the countries in Antarctica + 2. Fetch the iso3 code of the country with ID 3 + 3. List the countries with 'Island' in the name + 4. Count the number of countries that start with 'Z' or 'Q' + 5. Fetch all the Countries where continents is null ``` There are full solutions provided in the video version of this blog, but some examples you may find useful are: From 272355f679669dec5a5b9e940d9b8aef1eb5c6ff Mon Sep 17 00:00:00 2001 From: Paul Copplestone Date: Wed, 17 Mar 2021 16:44:44 +0800 Subject: [PATCH 04/70] Adds a bunch of extensions --- web/docs/guides/database.mdx | 29 +- web/src/components/Extensions.js | 66 ++++ web/src/data/extensions.json | 506 +++++++++++++++++++++++++++++++ 3 files changed, 593 insertions(+), 8 deletions(-) create mode 100644 web/src/components/Extensions.js create mode 100644 web/src/data/extensions.json diff --git a/web/docs/guides/database.mdx b/web/docs/guides/database.mdx index c6c4541f947..75159fe7ee1 100644 --- a/web/docs/guides/database.mdx +++ b/web/docs/guides/database.mdx @@ -4,6 +4,8 @@ title: Database description: Use Supabase to manage your data. --- +import ExtensionsComponent from '../../src/components/Extensions' + Supabase is built on top of [Postgres](/docs/postgres/server/about), an extremely scalable Relational Database. ## Features @@ -33,14 +35,6 @@ You can duplicate your tables, just like you would inside a spreadsheet. -### Enable and disable extensions - -Extensions are one of the best things about Postgres. You can enable Postgres extensions with the click of a button. - - - ### The SQL Editor @@ -58,6 +52,25 @@ Supabase comes with a SQL Editor. You can also save your favorite queries to run - Managed backups - Supabase handles all your database backups. - Data imports - import directly from a CSV or excel spreadsheet. +## Extensions + + +### Enable and disable extensions + +Postgres is extensible, allowing Supabase to provide some amazing functionality immediately . Enable Postgres extensions with the click of a button. +You can enable Postgres extensions with the click of a button. + + + + +### Full list of extensions + +Supabase is pre-configured with over 50 extensions. You can also install your own SQL extensions directly into the database through our SQL editor. + + + ## Tips diff --git a/web/src/components/Extensions.js b/web/src/components/Extensions.js new file mode 100644 index 00000000000..2ea6f2eaa86 --- /dev/null +++ b/web/src/components/Extensions.js @@ -0,0 +1,66 @@ +import React, { useState } from 'react' +import extensions from '../data/extensions.json' + +export default function Extensions() { + const [filter, setFilter] = useState('') + return ( + <> +
+ setFilter(e.target.value)} + /> +
+
+ {extensions + .filter((x) => x.name.indexOf(filter) >= 0) + .map((extension) => ( +
+
+

+ {extension.name} +

+

{extension.comment}

+
+
+ ))} +
+ + ) +} + +const styles = { + inputContainer: { + marginBottom: '15px', + }, + input: { + border: '1px solid var(--ifm-panel-border-color)', + borderRadius: 4, + backgroundColor: 'var(--custom-background-color-diff)', + color: 'var(--ifm-font-color-base)', + margin: 0, + padding: '6px 8px', + width: 300, + }, + column: { + margin: '5px 0px', + padding: '0px 5px', + }, + card: { + border: '1px solid var(--ifm-panel-border-color)', + borderRadius: 5, + padding: 8, + }, + title: { + margin: 0, + fontSize: '0.9rem', + border: '1px solid var(--ifm-panel-border-color)', + }, + description: { + textTransform: 'capitalize', + fontSize: '0.8rem', + margin: 0, + }, +} diff --git a/web/src/data/extensions.json b/web/src/data/extensions.json new file mode 100644 index 00000000000..f0201a70055 --- /dev/null +++ b/web/src/data/extensions.json @@ -0,0 +1,506 @@ +[ + { + "name": "address_standardizer", + "schema": null, + "default_version": "3.1.1", + "installed_version": null, + "comment": "Used to parse an address into constituent elements. Generally used to support geocoding address normalization step." + }, + { + "name": "address_standardizer-3", + "schema": null, + "default_version": "3.1.1", + "installed_version": null, + "comment": "Used to parse an address into constituent elements. Generally used to support geocoding address normalization step." + }, + { + "name": "address_standardizer_data_us", + "schema": null, + "default_version": "3.1.1", + "installed_version": null, + "comment": "Address Standardizer US dataset example" + }, + { + "name": "address_standardizer_data_us-3", + "schema": null, + "default_version": "3.1.1", + "installed_version": null, + "comment": "Address Standardizer US dataset example" + }, + { + "name": "adminpack", + "schema": null, + "default_version": "2.0", + "installed_version": null, + "comment": "administrative functions for PostgreSQL" + }, + { + "name": "amcheck", + "schema": null, + "default_version": "1.2", + "installed_version": null, + "comment": "functions for verifying relation integrity" + }, + { + "name": "autoinc", + "schema": null, + "default_version": "1.0", + "installed_version": null, + "comment": "functions for autoincrementing fields" + }, + { + "name": "bloom", + "schema": null, + "default_version": "1.0", + "installed_version": null, + "comment": "bloom access method - signature file based index" + }, + { + "name": "btree_gin", + "schema": null, + "default_version": "1.3", + "installed_version": null, + "comment": "support for indexing common datatypes in GIN" + }, + { + "name": "btree_gist", + "schema": null, + "default_version": "1.5", + "installed_version": null, + "comment": "support for indexing common datatypes in GiST" + }, + { + "name": "citext", + "schema": null, + "default_version": "1.6", + "installed_version": null, + "comment": "data type for case-insensitive character strings" + }, + { + "name": "cube", + "schema": null, + "default_version": "1.4", + "installed_version": null, + "comment": "data type for multidimensional cubes" + }, + { + "name": "dblink", + "schema": null, + "default_version": "1.2", + "installed_version": null, + "comment": "connect to other PostgreSQL databases from within a database" + }, + { + "name": "dict_int", + "schema": null, + "default_version": "1.0", + "installed_version": null, + "comment": "text search dictionary template for integers" + }, + { + "name": "dict_xsyn", + "schema": null, + "default_version": "1.0", + "installed_version": null, + "comment": "text search dictionary template for extended synonym processing" + }, + { + "name": "earthdistance", + "schema": null, + "default_version": "1.1", + "installed_version": null, + "comment": "calculate great-circle distances on the surface of the Earth" + }, + { + "name": "file_fdw", + "schema": null, + "default_version": "1.0", + "installed_version": null, + "comment": "foreign-data wrapper for flat file access" + }, + { + "name": "fuzzystrmatch", + "schema": null, + "default_version": "1.1", + "installed_version": null, + "comment": "determine similarities and distance between strings" + }, + { + "name": "hstore", + "schema": null, + "default_version": "1.6", + "installed_version": null, + "comment": "data type for storing sets of (key, value) pairs" + }, + { + "name": "hstore_plpython3u", + "schema": null, + "default_version": "1.0", + "installed_version": null, + "comment": "transform between hstore and plpython3u" + }, + { + "name": "http", + "schema": "extensions", + "default_version": "1.3", + "installed_version": "1.3", + "comment": "HTTP client for PostgreSQL, allows web page retrieval inside the database." + }, + { + "name": "insert_username", + "schema": null, + "default_version": "1.0", + "installed_version": null, + "comment": "functions for tracking who changed a table" + }, + { + "name": "intagg", + "schema": null, + "default_version": "1.1", + "installed_version": null, + "comment": "integer aggregator and enumerator (obsolete)" + }, + { + "name": "intarray", + "schema": null, + "default_version": "1.2", + "installed_version": null, + "comment": "functions, operators, and index support for 1-D arrays of integers" + }, + { + "name": "isn", + "schema": null, + "default_version": "1.2", + "installed_version": null, + "comment": "data types for international product numbering standards" + }, + { + "name": "jsonb_plpython3u", + "schema": null, + "default_version": "1.0", + "installed_version": null, + "comment": "transform between jsonb and plpython3u" + }, + { + "name": "lo", + "schema": null, + "default_version": "1.1", + "installed_version": null, + "comment": "Large Object maintenance" + }, + { + "name": "ltree", + "schema": null, + "default_version": "1.1", + "installed_version": null, + "comment": "data type for hierarchical tree-like structures" + }, + { + "name": "ltree_plpython3u", + "schema": null, + "default_version": "1.0", + "installed_version": null, + "comment": "transform between ltree and plpython3u" + }, + { + "name": "moddatetime", + "schema": null, + "default_version": "1.0", + "installed_version": null, + "comment": "functions for tracking last modification time" + }, + { + "name": "pageinspect", + "schema": null, + "default_version": "1.7", + "installed_version": null, + "comment": "inspect the contents of database pages at a low level" + }, + { + "name": "pg_buffercache", + "schema": null, + "default_version": "1.3", + "installed_version": null, + "comment": "examine the shared buffer cache" + }, + { + "name": "pg_cron", + "schema": "extensions", + "default_version": "1.3", + "installed_version": "1.3", + "comment": "Job scheduler for PostgreSQL" + }, + { + "name": "pg_freespacemap", + "schema": null, + "default_version": "1.2", + "installed_version": null, + "comment": "examine the free space map (FSM)" + }, + { + "name": "pg_prewarm", + "schema": null, + "default_version": "1.2", + "installed_version": null, + "comment": "prewarm relation data" + }, + { + "name": "pg_stat_statements", + "schema": null, + "default_version": "1.7", + "installed_version": null, + "comment": "track execution statistics of all SQL statements executed" + }, + { + "name": "pg_trgm", + "schema": null, + "default_version": "1.4", + "installed_version": null, + "comment": "text similarity measurement and index searching based on trigrams" + }, + { + "name": "pg_visibility", + "schema": null, + "default_version": "1.2", + "installed_version": null, + "comment": "examine the visibility map (VM) and page-level visibility info" + }, + { + "name": "pgaudit", + "schema": null, + "default_version": "1.4", + "installed_version": null, + "comment": "provides auditing functionality" + }, + { + "name": "pgcrypto", + "schema": "extensions", + "default_version": "1.3", + "installed_version": "1.3", + "comment": "cryptographic functions" + }, + { + "name": "pgjwt", + "schema": "extensions", + "default_version": "0.1.0", + "installed_version": "0.1.0", + "comment": "JSON Web Token API for Postgresql" + }, + { + "name": "pgrowlocks", + "schema": null, + "default_version": "1.2", + "installed_version": null, + "comment": "show row-level locking information" + }, + { + "name": "pgstattuple", + "schema": null, + "default_version": "1.5", + "installed_version": null, + "comment": "show tuple-level statistics" + }, + { + "name": "pgtap", + "schema": null, + "default_version": "1.1.0", + "installed_version": null, + "comment": "Unit testing for PostgreSQL" + }, + { + "name": "plcoffee", + "schema": null, + "default_version": "3.0alpha", + "installed_version": null, + "comment": "PL/CoffeeScript (v8) trusted procedural language" + }, + { + "name": "pljava", + "schema": null, + "default_version": "1.6.0", + "installed_version": null, + "comment": "PL/Java procedural language (https://tada.github.io/pljava/)" + }, + { + "name": "plls", + "schema": null, + "default_version": "3.0alpha", + "installed_version": null, + "comment": "PL/LiveScript (v8) trusted procedural language" + }, + { + "name": "plpgsql", + "schema": "pg_catalog", + "default_version": "1.0", + "installed_version": "1.0", + "comment": "PL/pgSQL procedural language" + }, + { + "name": "plpgsql_check", + "schema": null, + "default_version": "1.11", + "installed_version": null, + "comment": "extended check for plpgsql functions" + }, + { + "name": "plpython3u", + "schema": null, + "default_version": "1.0", + "installed_version": null, + "comment": "PL/Python3U untrusted procedural language" + }, + { + "name": "plv8", + "schema": null, + "default_version": "3.0alpha", + "installed_version": null, + "comment": "PL/JavaScript (v8) trusted procedural language" + }, + { + "name": "postgis", + "schema": null, + "default_version": "3.1.1", + "installed_version": null, + "comment": "PostGIS geometry and geography spatial types and functions" + }, + { + "name": "postgis-3", + "schema": null, + "default_version": "3.1.1", + "installed_version": null, + "comment": "PostGIS geometry and geography spatial types and functions" + }, + { + "name": "postgis_raster", + "schema": null, + "default_version": "3.1.1", + "installed_version": null, + "comment": "PostGIS raster types and functions" + }, + { + "name": "postgis_raster-3", + "schema": null, + "default_version": "3.1.1", + "installed_version": null, + "comment": "PostGIS raster types and functions" + }, + { + "name": "postgis_sfcgal", + "schema": null, + "default_version": "3.1.1", + "installed_version": null, + "comment": "PostGIS SFCGAL functions" + }, + { + "name": "postgis_sfcgal-3", + "schema": null, + "default_version": "3.1.1", + "installed_version": null, + "comment": "PostGIS SFCGAL functions" + }, + { + "name": "postgis_tiger_geocoder", + "schema": null, + "default_version": "3.1.1", + "installed_version": null, + "comment": "PostGIS tiger geocoder and reverse geocoder" + }, + { + "name": "postgis_tiger_geocoder-3", + "schema": null, + "default_version": "3.1.1", + "installed_version": null, + "comment": "PostGIS tiger geocoder and reverse geocoder" + }, + { + "name": "postgis_topology", + "schema": null, + "default_version": "3.1.1", + "installed_version": null, + "comment": "PostGIS topology spatial types and functions" + }, + { + "name": "postgis_topology-3", + "schema": null, + "default_version": "3.1.1", + "installed_version": null, + "comment": "PostGIS topology spatial types and functions" + }, + { + "name": "postgres_fdw", + "schema": null, + "default_version": "1.0", + "installed_version": null, + "comment": "foreign-data wrapper for remote PostgreSQL servers" + }, + { + "name": "refint", + "schema": null, + "default_version": "1.0", + "installed_version": null, + "comment": "functions for implementing referential integrity (obsolete)" + }, + { + "name": "seg", + "schema": null, + "default_version": "1.3", + "installed_version": null, + "comment": "data type for representing line segments or floating-point intervals" + }, + { + "name": "sslinfo", + "schema": null, + "default_version": "1.2", + "installed_version": null, + "comment": "information about SSL certificates" + }, + { + "name": "tablefunc", + "schema": null, + "default_version": "1.0", + "installed_version": null, + "comment": "functions that manipulate whole tables, including crosstab" + }, + { + "name": "tcn", + "schema": null, + "default_version": "1.0", + "installed_version": null, + "comment": "Triggered change notifications" + }, + { + "name": "tsm_system_rows", + "schema": null, + "default_version": "1.0", + "installed_version": null, + "comment": "TABLESAMPLE method which accepts number of rows as a limit" + }, + { + "name": "tsm_system_time", + "schema": null, + "default_version": "1.0", + "installed_version": null, + "comment": "TABLESAMPLE method which accepts time in milliseconds as a limit" + }, + { + "name": "unaccent", + "schema": null, + "default_version": "1.1", + "installed_version": null, + "comment": "text search dictionary that removes accents" + }, + { + "name": "uuid-ossp", + "schema": "extensions", + "default_version": "1.1", + "installed_version": "1.1", + "comment": "generate universally unique identifiers (UUIDs)" + }, + { + "name": "xml2", + "schema": null, + "default_version": "1.1", + "installed_version": null, + "comment": "XPath querying and XSLT" + } +] \ No newline at end of file From 9b84b794b288fa2624ec7ec675096d6d5ada0ba1 Mon Sep 17 00:00:00 2001 From: Paul Copplestone Date: Thu, 18 Mar 2021 11:45:27 +0800 Subject: [PATCH 05/70] Adds more Postgres docs --- web/docs/guides/database.mdx | 54 +++++++- web/sidebar_spec_postgres.js | 14 ++- web/spec/postgres.yml | 209 +++++++++++++++++++++++++------ web/src/components/Extensions.js | 5 +- web/src/css/custom.css | 4 + 5 files changed, 241 insertions(+), 45 deletions(-) diff --git a/web/docs/guides/database.mdx b/web/docs/guides/database.mdx index 75159fe7ee1..d9a57c75890 100644 --- a/web/docs/guides/database.mdx +++ b/web/docs/guides/database.mdx @@ -74,18 +74,68 @@ Supabase is pre-configured with over 50 extensions. You can also install your ow ## Tips +### Realtime + +Supabase provides a realtime engine on top of Postgres, so that you can listen to changes as they happen. +Our realtime engine uses the built-in replication functionality of Postgres. +You can manage the realtime system, simply by +[updating](http://localhost:3006/docs/reference/postgres/publications) the `supabase_realtime` publication. + +For example to enable realtime only for individual tables: + +```sql +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; +``` + +By default only "new" values are sent, but if you want to receive the old record (previous values) whenever you `update` or `delete` a record, +you can update the replica identity of your tables, setting it to `full`: + +```sql +alter table_name your_table +replica identity full; +``` + + +### Resetting your project password + +When you create a new project in Supabase we ask for a password. You can use this password to connect direcly to your Postgres database. + +If you forget your password, you can reset it from the Dashboard SQL editor: + +For example: + +```sql +alter user postgres +with password 'new_password'; +``` + +Read more in [Database Configuration](/reference/postgres/database-passwords). ### Changing the timezone of your server. -Your database is initialized with the UTC timezone. We recommend keeping it this way, as it is helpful for time calculation. +Your database is initialized with the UTC timezone. We recommend keeping it this way, as it is helpful for time calculations. If, however, you want to update the timezone, you can do so using any of the [database timezones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). For example: ```sql -alter database postgres set timezone to 'Asia/Singapore'; +alter database postgres set timezone to 'America/New_York'; ``` +Read more in [Database Configuration](/reference/postgres/changing-timezones). + ## Next steps - Read more about [Postgres](/docs/postgres/server/about) diff --git a/web/sidebar_spec_postgres.js b/web/sidebar_spec_postgres.js index d428462a9be..102e32f3d4e 100644 --- a/web/sidebar_spec_postgres.js +++ b/web/sidebar_spec_postgres.js @@ -8,14 +8,20 @@ module.exports = { }, { type: 'category', - label: 'Database', - items: ['reference/postgres/database-passwords'], + label: 'Managing Tables', + items: ['reference/postgres/schemas', 'reference/postgres/tables'], collapsed: true, }, { type: 'category', - label: 'Tables', - items: ['reference/postgres/creating-tables'], + label: 'Replication', + items: ['reference/postgres/publications'], + collapsed: true, + }, + { + type: 'category', + label: 'Database Configuration', + items: ['reference/postgres/database-passwords', 'reference/postgres/changing-timezones'], collapsed: true, } ], diff --git a/web/spec/postgres.yml b/web/spec/postgres.yml index bc5b81033ae..d41f06c36bd 100644 --- a/web/spec/postgres.yml +++ b/web/spec/postgres.yml @@ -21,57 +21,66 @@ info: - name: 'About' items: - index - - name: 'Database' + - name: 'Managing Tables' items: - # - Database Users - - Database Passwords - # - name: 'Schemas' - # items: - # - Creating schemas - - name: 'Tables' - items: - - Creating tables + - Schemas + - Tables # - name: 'Columns' # items: # - Creating columns # - Column types + - name: 'Replication' + items: + - Publications + - name: 'Database Configuration' + items: + # - Database Users + - Database Passwords + - Changing Timezones pages: - Database Users: + Schemas: description: | - Users and Roles are almost interchangable. + Schemas are like "folders". They are a to keep your database organized. + + This is particularly useful for security. You can set different permissions on each schema. + For example, you might want to use a `public` schema for user-facing data, and an `auth` schema for all logins and secured data. + + notes: | + - Schemas contain tables, columns, triggers, functions, etc. + - Postgres comes with a `public` schema set up by default. + - It is best practice to use lowercase and underscores when naming schemas. For example: `schema_name`, not `Schema Name`. examples: - - name: Create New User + - name: Creating a schema + isSpotlight: true sql: | ```sql - create user prisma - with password 'hello'; + create schema schema_name; ``` - Database Passwords: + - name: Removing a schema + sql: | + ```sql + drop schema if exists schema_name; + ``` + - name: Using special characters + description: | + Although it's not recommended, you can use uppercase and spaces when naming your schema by wrapping the name with double-quotes. + As a result, you will always need to use double-quotes when referencing your schema. + sql: | + ```sql + create schema "Schema Name"; + ``` + Tables: description: | - You can manage the passwords of your database users using any super user. + Tables are similar to excel spreadsheets. They contain columns & rows of data. There are a few key differences from a spreadsheet however: + + - Every column is a strict type of data. When you set up a column, you must define what "data type" it is. + - Tables can be joined together through relationships. For example you can have a "users" table, which is joined to a "teams" table. - examples: - - name: Password reset - sql: | - ```sql - alter user postgres - with password 'new_password'; - ``` - Creating schemas: - description: | - Creating schemas. - - examples: - - name: Create schema - sql: | - ```sql - create schema new_schema; - ``` - Creating tables: - description: | - A relational database consists of multiple related tables. A table consists of rows and columns. + notes: | + - Tables contain columns, rows, triggers, comments, + - It is best practice to use lowercase and underscores when naming tables. For example: `table_name`, not `Table Name`. examples: - name: Create table @@ -94,7 +103,7 @@ pages: primary key (column_1, column_2) ); ``` - Creating columns: + Columns: description: | Creating columns. @@ -126,4 +135,130 @@ pages: # alter table new_table # add new_column text; # ``` + + Publications: + description: | + Publications are a way of grouping changes generated from a table or a group of tables. + These changes can then be sent to other systems (usually another Postgres database). + + examples: + - name: Create a Publication + description: | + This publication will contain all changes to all tables. + sql: | + ```sql + create publication publication_name + for all tables; + ``` + - name: Create a Publication which listens to individual tables + sql: | + ```sql + create publication publication_name + for table table_one, table_two; + ``` + - name: Add tables to an existing publication + sql: | + ```sql + alter publication publication_name + add table table_name; + ``` + - name: Listens to inserts only + sql: | + ```sql + create publication publication_name + for all tables + with (publish = 'insert'); + ``` + - name: Listens to updates only + sql: | + ```sql + create publication publication_name + for all tables + with (publish = 'update'); + ``` + - name: Listens to deletions only + sql: | + ```sql + create publication publication_name + for all tables + with (publish = 'delete'); + ``` + - name: Remove a Publication + sql: | + ```sql + drop publication if exists publication_name; + ``` + - name: Recreate a Publication + description: | + If you are planning to re-create a publication, it's best to do it in a transaction to ensure the operation succeeds. + sql: | + ```sql + begin; + -- remove the realtime publication + drop publication if exists publication_name; + + -- re-create the publication but don't enable it for any tables + create publication publication_name; + commit; + ``` + + Database Users: + description: | + Users and Roles are almost interchangable. + + examples: + - name: Create New User + sql: | + ```sql + create user new_user + with password 'hello'; + ``` + Database Passwords: + description: | + Manage the passwords of your database users using any super user. + + examples: + - name: Password reset + sql: | + ```sql + alter user postgres + with password 'new_password'; + ``` + Changing Timezones: + description: | + Data types. + notes: | + - View a full list of timezones on [Wikipedia](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). + + examples: + - name: Change timezone + isSpotlight: true + sql: | + ```sql + alter database postgres + set timezone to 'America/New_York'; + ``` + - name: Full list of timezones + description: | + Get a full list of timezones supported by your database. This will return the following columns: + + - `name`: Time zone name + - `abbrev`: Time zone abbreviation + - `utc_offset`: Offset from UTC (positive means east of Greenwich) + - `is_dst`: True if currently observing daylight savings + + sql: | + ```sql + select name, abbrev, utc_offset, is_dst + from pg_timezone_names() + order by name; + ``` + - name: Search for a specific timezone + description: Use `ilike` (case insensitive search) to find specific timezones. + sql: | + ```sql + select * + from pg_timezone_names() + where name ilike '%york%'; + ``` diff --git a/web/src/components/Extensions.js b/web/src/components/Extensions.js index 2ea6f2eaa86..e1d10d6c799 100644 --- a/web/src/components/Extensions.js +++ b/web/src/components/Extensions.js @@ -22,7 +22,9 @@ export default function Extensions() {

{extension.name}

-

{extension.comment}

+

+ {extension.comment.charAt(0).toUpperCase() + extension.comment.slice(1)} +

))} @@ -59,7 +61,6 @@ const styles = { border: '1px solid var(--ifm-panel-border-color)', }, description: { - textTransform: 'capitalize', fontSize: '0.8rem', margin: 0, }, diff --git a/web/src/css/custom.css b/web/src/css/custom.css index 7d196ab5a39..6e03d26dd9b 100755 --- a/web/src/css/custom.css +++ b/web/src/css/custom.css @@ -1268,6 +1268,10 @@ html[data-theme='dark'] .navbar-item-twitter:before { /* New CSS */ +code { + border: 1px solid var(--ifm-hr-border-color); +} + .tabs { margin: 0; font-size: 0.7rem; From 35976fc6e4187a43c5fda3d3b3013b7668b504e1 Mon Sep 17 00:00:00 2001 From: Paul Copplestone Date: Thu, 18 Mar 2021 11:55:00 +0800 Subject: [PATCH 06/70] Fixes broken links --- web/docs/guides/database.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/docs/guides/database.mdx b/web/docs/guides/database.mdx index d9a57c75890..dd343976a0a 100644 --- a/web/docs/guides/database.mdx +++ b/web/docs/guides/database.mdx @@ -121,7 +121,7 @@ alter user postgres with password 'new_password'; ``` -Read more in [Database Configuration](/reference/postgres/database-passwords). +Read more in [Database Configuration](/docs/reference/postgres/database-passwords). ### Changing the timezone of your server. @@ -134,7 +134,7 @@ For example: alter database postgres set timezone to 'America/New_York'; ``` -Read more in [Database Configuration](/reference/postgres/changing-timezones). +Read more in [Database Configuration](/docs/reference/postgres/changing-timezones). ## Next steps From d9e3759eb37421e5adaccd81fc83e98c6c6d2a2f Mon Sep 17 00:00:00 2001 From: Paul Copplestone Date: Thu, 18 Mar 2021 12:22:17 +0800 Subject: [PATCH 07/70] fix typos on extensions --- web/docs/guides/database.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/docs/guides/database.mdx b/web/docs/guides/database.mdx index dd343976a0a..2a44a8f4d0d 100644 --- a/web/docs/guides/database.mdx +++ b/web/docs/guides/database.mdx @@ -57,8 +57,8 @@ Supabase comes with a SQL Editor. You can also save your favorite queries to run ### Enable and disable extensions -Postgres is extensible, allowing Supabase to provide some amazing functionality immediately . Enable Postgres extensions with the click of a button. -You can enable Postgres extensions with the click of a button. +To expand the functionality of your Postgres database, you can use extensions. +You can enable Postgres extensions with the click of a button within the Supabase dashboard.