Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multitenancy support #8

Merged
merged 26 commits into from Jan 31, 2023
Merged

Multitenancy support #8

merged 26 commits into from Jan 31, 2023

Conversation

abc3
Copy link
Member

@abc3 abc3 commented Jan 26, 2023

What kind of change does this PR introduce?

This PR adds support for multitenancy. Different credentials can be stored in the database and managed by HTTP API.

The tenant record includes the external_id column, which will store the Supabase project id.

During connections, pg_edge gets the external_id value from the query parameters "options".

Additional context

How to start it

At first, we need to reinitialize a database image:

make db_rebuild

pg_edge keeps tables in the pgedge schema. The schema should be created automatically by the dev/postgres/00-setup.sql file. Make sure that this schema exists if got troubles with migrations.

Then we need to apply migrations:

mix ecto.migrate --prefix pgedge --log-migrator-sql

Launch the pg_edge application as usual:

make dev

When you start the application, you can try following commands to add tenants to the database

add/update tenant:

curl -X PUT \
  'http://localhost:4000/api/tenants/dev_tenant' \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJvbGUiOiJhbm9uIiwiaWF0IjoxNjQ1MTkyODI0LCJleHAiOjE5NjA3Njg4MjR9.M9jrxyvPLkUxWgOYSf5dNdJ8v_eRrq810ShFRT8N-6M' \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "tenant": {
      "db_host": "localhost",
      "db_port": 6432, 
      "db_user": "postgres",
      "db_database": "postgres",
      "db_password": "postgres",
      "pool_size": 20
  }
}'

and now it's possible to connect through the proxy

psql postgresql://postgres:no_pass@localhost:7654/postgres?options=tenant%20dev_tenant

delete tenant:

curl -X DELETE \
  'http://localhost:4000/api/tenants/dev_tenant' \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJvbGUiOiJhbm9uIiwiaWF0IjoxNjQ1MTkyODI0LCJleHAiOjE5NjA3Njg4MjR9.M9jrxyvPLkUxWgOYSf5dNdJ8v_eRrq810ShFRT8N-6M'

@abc3 abc3 self-assigned this Jan 26, 2023
@abc3 abc3 marked this pull request as draft January 26, 2023 11:23
@abc3 abc3 changed the title [WIP] Multitenancy support Multitenancy support Jan 26, 2023
@abc3 abc3 marked this pull request as ready for review January 26, 2023 19:28
@abc3 abc3 requested a review from chasers January 26, 2023 19:47
@abc3 abc3 requested a review from a team January 26, 2023 20:15
@abc3
Copy link
Member Author

abc3 commented Jan 26, 2023

Hey, @supabase/dashbit team, another day, another PR for the review!
You can ignore files lib/pg_edge/client_handler.ex and lib/pg_edge/db_handler.ex. I hope we can replace poolboy with some more performance approach like what @wojtekmach suggested here #4 (review)

priv/repo/migrations/20230125140723_create_tenants.exs Outdated Show resolved Hide resolved
config/runtime.exs Outdated Show resolved Hide resolved
Comment on lines +39 to +44
hostname: System.get_env("DB_HOST", "localhost"),
username: System.get_env("DB_USER", "postgres"),
password: System.get_env("DB_PASSWORD", "postgres"),
database: System.get_env("DB_NAME", "postgres"),
port: System.get_env("DB_PORT", "6432"),
pool_size: System.get_env("DB_POOL_SIZE", "5") |> String.to_integer(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a friendly reminder that while it is of course totally fine to configure each parameter separately, on very DB-centric projects where I would often jump between system/docker/hosted pg and elixir/psql, I found it very convenient to configure the connection through the URL:

url: System.get_env("DATABASE_URL", "ecto://postgres:postgres@localhost:6432/postgres?pool_size=5")

(yup, we can configure pool_size like this too!)

Again, no need for the change, just something to keep in mind in case you weren't aware!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sometimes it's handy to update only a single value in production, for example, only pool size. In the case of URL, it needs to copy and find all credentials.

Comment on lines +16 to +17
"joken": {:hex, :joken, "2.5.0", "09be497d804b8115eb6f07615cef2e60c2a1008fb89dc0aef0d4c4b4609b99aa", [:mix], [{:jose, "~> 1.11.2", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm", "22b25c89617c5ed8ca7b31026340a25ea0f9ca7160f9706b79be9ed81fdf74e7"},
"jose": {:hex, :jose, "1.11.5", "3bc2d75ffa5e2c941ca93e5696b54978323191988eb8d225c2e663ddfefd515e", [:mix, :rebar3], [], "hexpm", "dcd3b215bafe02ea7c5b23dafd3eb8062a5cd8f2d904fd9caa323d37034ab384"},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unless you get significant benefits out of using Joken, I'd go for the JOSE library directly to keep dependencies to minimum as well as if you do need to debug something you'll have less layers to peel off. But if for your use case Joken is not just delegating to JOSE but actually encapsulates a lot of logic that you'd rather not implement yourself, by all means go for it!

lib/pg_edge/jwt.ex Outdated Show resolved Hide resolved
mix.exs Outdated Show resolved Hide resolved
lib/pg_edge_web/router.ex Outdated Show resolved Hide resolved
lib/pg_edge_web/router.ex Outdated Show resolved Hide resolved
lib/pg_edge_web/router.ex Outdated Show resolved Hide resolved
lib/pg_edge/jwt.ex Show resolved Hide resolved
abc3 and others added 2 commits January 27, 2023 13:28
Co-authored-by: Wojtek Mach <wojtekmach@users.noreply.github.com>
Co-authored-by: Wojtek Mach <wojtekmach@users.noreply.github.com>
@abc3 abc3 mentioned this pull request Jan 27, 2023
@abc3
Copy link
Member Author

abc3 commented Jan 27, 2023

Added cloak_ecto for password encryption

@abc3 abc3 merged commit b17316e into main Jan 31, 2023
@abc3 abc3 deleted the feat/multitenancy branch January 31, 2023 11:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants