diff --git a/CHANGELOG.md b/CHANGELOG.md
index a929e921e..c2c999110 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,13 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [6.0.0] - 2023-06-02
+### Adds
+
+- Support for multitenancy.
+- New config `supertokens_saas_secret` added to support multitenancy in SaaS mode.
+- New config `supertokens_default_cdi_version` is added to specify the version of CDI core must assume when the
+ version is not specified in the request. If this config is not specified, the core will assume the latest version.
+
### Fixes
- Fixes an issue where session verification would fail for JWTs created using the JWT recipe
@@ -36,1381 +43,1544 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
### Migration steps for SQL
-
-
-If using PostgreSQL
-
-#### Run the following SQL script
-
-```sql
--- General Tables
-
-CREATE TABLE IF NOT EXISTS apps (
- app_id VARCHAR(64) NOT NULL DEFAULT 'public',
- created_at_time BIGINT,
- CONSTRAINT apps_pkey PRIMARY KEY(app_id)
-);
-
-INSERT INTO apps (app_id, created_at_time)
- VALUES ('public', 0);
-
-------------------------------------------------------------
-
-CREATE TABLE IF NOT EXISTS tenants (
- app_id VARCHAR(64) NOT NULL DEFAULT 'public',
- tenant_id VARCHAR(64) NOT NULL DEFAULT 'public',
- created_at_time BIGINT ,
- CONSTRAINT tenants_pkey
- PRIMARY KEY (app_id, tenant_id),
- CONSTRAINT tenants_app_id_fkey FOREIGN KEY(app_id)
- REFERENCES apps (app_id) ON DELETE CASCADE
-);
-
-INSERT INTO tenants (app_id, tenant_id, created_at_time)
- VALUES ('public', 'public', 0);
-
-------------------------------------------------------------
-
-ALTER TABLE key_value
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public',
- ADD COLUMN tenant_id VARCHAR(64) DEFAULT 'public';
-
-ALTER TABLE key_value
- DROP CONSTRAINT key_value_pkey;
-
-ALTER TABLE key_value
- ADD CONSTRAINT key_value_pkey
- PRIMARY KEY (app_id, tenant_id, name);
-
-ALTER TABLE key_value
- ADD CONSTRAINT key_value_tenant_id_fkey
- FOREIGN KEY (app_id, tenant_id)
- REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE;
-
-------------------------------------------------------------
-
-CREATE TABLE IF NOT EXISTS app_id_to_user_id (
- app_id VARCHAR(64) NOT NULL DEFAULT 'public',
- user_id CHAR(36) NOT NULL,
- recipe_id VARCHAR(128) NOT NULL,
- CONSTRAINT app_id_to_user_id_pkey
- PRIMARY KEY (app_id, user_id),
- CONSTRAINT app_id_to_user_id_app_id_fkey
- FOREIGN KEY(app_id) REFERENCES apps (app_id) ON DELETE CASCADE
-);
-
-INSERT INTO app_id_to_user_id (user_id, recipe_id)
- SELECT user_id, recipe_id
- FROM all_auth_recipe_users;
-
-------------------------------------------------------------
-
-ALTER TABLE all_auth_recipe_users
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public',
- ADD COLUMN tenant_id VARCHAR(64) DEFAULT 'public';
-
-ALTER TABLE all_auth_recipe_users
- DROP CONSTRAINT all_auth_recipe_users_pkey CASCADE;
-
-ALTER TABLE all_auth_recipe_users
- ADD CONSTRAINT all_auth_recipe_users_pkey
- PRIMARY KEY (app_id, tenant_id, user_id);
-
-ALTER TABLE all_auth_recipe_users
- ADD CONSTRAINT all_auth_recipe_users_tenant_id_fkey
- FOREIGN KEY (app_id, tenant_id)
- REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE;
-
-ALTER TABLE all_auth_recipe_users
- ADD CONSTRAINT all_auth_recipe_users_user_id_fkey
- FOREIGN KEY (app_id, user_id)
- REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE;
-
-DROP INDEX all_auth_recipe_users_pagination_index;
-
-CREATE INDEX all_auth_recipe_users_pagination_index ON all_auth_recipe_users (time_joined DESC, user_id DESC, tenant_id DESC, app_id DESC);
-
--- Multitenancy
-
-CREATE TABLE IF NOT EXISTS tenant_configs (
- connection_uri_domain VARCHAR(256) DEFAULT '',
- app_id VARCHAR(64) DEFAULT 'public',
- tenant_id VARCHAR(64) DEFAULT 'public',
- core_config TEXT,
- email_password_enabled BOOLEAN,
- passwordless_enabled BOOLEAN,
- third_party_enabled BOOLEAN,
- CONSTRAINT tenant_configs_pkey
- PRIMARY KEY (connection_uri_domain, app_id, tenant_id)
-);
-
-------------------------------------------------------------
-
-CREATE TABLE IF NOT EXISTS tenant_thirdparty_providers (
- connection_uri_domain VARCHAR(256) DEFAULT '',
- app_id VARCHAR(64) DEFAULT 'public',
- tenant_id VARCHAR(64) DEFAULT 'public',
- third_party_id VARCHAR(28) NOT NULL,
- name VARCHAR(64),
- authorization_endpoint TEXT,
- authorization_endpoint_query_params TEXT,
- token_endpoint TEXT,
- token_endpoint_body_params TEXT,
- user_info_endpoint TEXT,
- user_info_endpoint_query_params TEXT,
- user_info_endpoint_headers TEXT,
- jwks_uri TEXT,
- oidc_discovery_endpoint TEXT,
- require_email BOOLEAN,
- user_info_map_from_id_token_payload_user_id VARCHAR(64),
- user_info_map_from_id_token_payload_email VARCHAR(64),
- user_info_map_from_id_token_payload_email_verified VARCHAR(64),
- user_info_map_from_user_info_endpoint_user_id VARCHAR(64),
- user_info_map_from_user_info_endpoint_email VARCHAR(64),
- user_info_map_from_user_info_endpoint_email_verified VARCHAR(64),
- CONSTRAINT tenant_thirdparty_providers_pkey
- PRIMARY KEY (connection_uri_domain, app_id, tenant_id, third_party_id),
- CONSTRAINT tenant_thirdparty_providers_tenant_id_fkey
- FOREIGN KEY(connection_uri_domain, app_id, tenant_id)
- REFERENCES tenant_configs (connection_uri_domain, app_id, tenant_id) ON DELETE CASCADE
-);
-
-------------------------------------------------------------
-
-CREATE TABLE IF NOT EXISTS tenant_thirdparty_provider_clients (
- connection_uri_domain VARCHAR(256) DEFAULT '',
- app_id VARCHAR(64) DEFAULT 'public',
- tenant_id VARCHAR(64) DEFAULT 'public',
- third_party_id VARCHAR(28) NOT NULL,
- client_type VARCHAR(64) NOT NULL DEFAULT '',
- client_id VARCHAR(256) NOT NULL,
- client_secret TEXT,
- scope VARCHAR(128)[],
- force_pkce BOOLEAN,
- additional_config TEXT,
- CONSTRAINT tenant_thirdparty_provider_clients_pkey
- PRIMARY KEY (connection_uri_domain, app_id, tenant_id, third_party_id, client_type),
- CONSTRAINT tenant_thirdparty_provider_clients_third_party_id_fkey
- FOREIGN KEY (connection_uri_domain, app_id, tenant_id, third_party_id)
- REFERENCES tenant_thirdparty_providers (connection_uri_domain, app_id, tenant_id, third_party_id) ON DELETE CASCADE
-);
-
--- Session
-
-ALTER TABLE session_info
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public',
- ADD COLUMN tenant_id VARCHAR(64) DEFAULT 'public';
-
-ALTER TABLE session_info
- DROP CONSTRAINT session_info_pkey CASCADE;
-
-ALTER TABLE session_info
- ADD CONSTRAINT session_info_pkey
- PRIMARY KEY (app_id, tenant_id, session_handle);
-
-ALTER TABLE session_info
- ADD CONSTRAINT session_info_tenant_id_fkey
- FOREIGN KEY (app_id, tenant_id)
- REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE;
-
-CREATE INDEX session_expiry_index ON session_info (expires_at);
-
-------------------------------------------------------------
-
-ALTER TABLE session_access_token_signing_keys
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
-
-ALTER TABLE session_access_token_signing_keys
- DROP CONSTRAINT session_access_token_signing_keys_pkey CASCADE;
-
-ALTER TABLE session_access_token_signing_keys
- ADD CONSTRAINT session_access_token_signing_keys_pkey
- PRIMARY KEY (app_id, created_at_time);
-
-ALTER TABLE session_access_token_signing_keys
- ADD CONSTRAINT session_access_token_signing_keys_app_id_fkey
- FOREIGN KEY (app_id)
- REFERENCES apps (app_id) ON DELETE CASCADE;
-
--- JWT
-
-ALTER TABLE jwt_signing_keys
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
-
-ALTER TABLE jwt_signing_keys
- DROP CONSTRAINT jwt_signing_keys_pkey CASCADE;
-
-ALTER TABLE jwt_signing_keys
- ADD CONSTRAINT jwt_signing_keys_pkey
- PRIMARY KEY (app_id, key_id);
-
-ALTER TABLE jwt_signing_keys
- ADD CONSTRAINT jwt_signing_keys_app_id_fkey
- FOREIGN KEY (app_id)
- REFERENCES apps (app_id) ON DELETE CASCADE;
-
--- EmailVerification
-
-ALTER TABLE emailverification_verified_emails
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
-
-ALTER TABLE emailverification_verified_emails
- DROP CONSTRAINT emailverification_verified_emails_pkey CASCADE;
-
-ALTER TABLE emailverification_verified_emails
- ADD CONSTRAINT emailverification_verified_emails_pkey
- PRIMARY KEY (app_id, user_id, email);
-
-ALTER TABLE emailverification_verified_emails
- ADD CONSTRAINT emailverification_verified_emails_app_id_fkey
- FOREIGN KEY (app_id)
- REFERENCES apps (app_id) ON DELETE CASCADE;
-
-------------------------------------------------------------
-
-ALTER TABLE emailverification_tokens
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public',
- ADD COLUMN tenant_id VARCHAR(64) DEFAULT 'public';
-
-ALTER TABLE emailverification_tokens
- DROP CONSTRAINT emailverification_tokens_pkey CASCADE;
-
-ALTER TABLE emailverification_tokens
- ADD CONSTRAINT emailverification_tokens_pkey
- PRIMARY KEY (app_id, tenant_id, user_id, email, token);
-
-ALTER TABLE emailverification_tokens
- ADD CONSTRAINT emailverification_tokens_tenant_id_fkey
- FOREIGN KEY (app_id, tenant_id)
- REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE;
-
-
--- EmailPassword
-
-ALTER TABLE emailpassword_users
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
-
-ALTER TABLE emailpassword_users
- DROP CONSTRAINT emailpassword_users_pkey CASCADE;
-
-ALTER TABLE emailpassword_users
- DROP CONSTRAINT emailpassword_users_email_key CASCADE;
-
-ALTER TABLE emailpassword_users
- ADD CONSTRAINT emailpassword_users_pkey
- PRIMARY KEY (app_id, user_id);
-
-ALTER TABLE emailpassword_users
- ADD CONSTRAINT emailpassword_users_user_id_fkey
- FOREIGN KEY (app_id, user_id)
- REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE;
-
-------------------------------------------------------------
-
-CREATE TABLE IF NOT EXISTS emailpassword_user_to_tenant (
- app_id VARCHAR(64) DEFAULT 'public',
- tenant_id VARCHAR(64) DEFAULT 'public',
- user_id CHAR(36) NOT NULL,
- email VARCHAR(256) NOT NULL,
- CONSTRAINT emailpassword_user_to_tenant_email_key
- UNIQUE (app_id, tenant_id, email),
- CONSTRAINT emailpassword_user_to_tenant_pkey
- PRIMARY KEY (app_id, tenant_id, user_id),
- CONSTRAINT emailpassword_user_to_tenant_user_id_fkey
- FOREIGN KEY (app_id, tenant_id, user_id)
- REFERENCES all_auth_recipe_users (app_id, tenant_id, user_id) ON DELETE CASCADE
-);
-
-INSERT INTO emailpassword_user_to_tenant (user_id, email)
- SELECT user_id, email FROM emailpassword_users;
-
-------------------------------------------------------------
-
-ALTER TABLE emailpassword_pswd_reset_tokens
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
-
-ALTER TABLE emailpassword_pswd_reset_tokens
- DROP CONSTRAINT emailpassword_pswd_reset_tokens_pkey CASCADE;
-
-ALTER TABLE emailpassword_pswd_reset_tokens
- ADD CONSTRAINT emailpassword_pswd_reset_tokens_pkey
- PRIMARY KEY (app_id, user_id, token);
-
-ALTER TABLE emailpassword_pswd_reset_tokens
- DROP CONSTRAINT IF EXISTS emailpassword_pswd_reset_tokens_user_id_fkey;
-
-ALTER TABLE emailpassword_pswd_reset_tokens
- ADD CONSTRAINT emailpassword_pswd_reset_tokens_user_id_fkey
- FOREIGN KEY (app_id, user_id)
- REFERENCES emailpassword_users (app_id, user_id) ON DELETE CASCADE;
-
--- Passwordless
-
-ALTER TABLE passwordless_users
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
-
-ALTER TABLE passwordless_users
- DROP CONSTRAINT passwordless_users_pkey CASCADE;
-
-ALTER TABLE passwordless_users
- ADD CONSTRAINT passwordless_users_pkey
- PRIMARY KEY (app_id, user_id);
-
-ALTER TABLE passwordless_users
- DROP CONSTRAINT passwordless_users_email_key;
-
-ALTER TABLE passwordless_users
- DROP CONSTRAINT passwordless_users_phone_number_key;
-
-ALTER TABLE passwordless_users
- ADD CONSTRAINT passwordless_users_user_id_fkey
- FOREIGN KEY (app_id, user_id)
- REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE;
-
-------------------------------------------------------------
-
-CREATE TABLE IF NOT EXISTS passwordless_user_to_tenant (
- app_id VARCHAR(64) DEFAULT 'public',
- tenant_id VARCHAR(64) DEFAULT 'public',
- user_id CHAR(36) NOT NULL,
- email VARCHAR(256),
- phone_number VARCHAR(256),
- CONSTRAINT passwordless_user_to_tenant_email_key
- UNIQUE (app_id, tenant_id, email),
- CONSTRAINT passwordless_user_to_tenant_phone_number_key
- UNIQUE (app_id, tenant_id, phone_number),
- CONSTRAINT passwordless_user_to_tenant_pkey
- PRIMARY KEY (app_id, tenant_id, user_id),
- CONSTRAINT passwordless_user_to_tenant_user_id_fkey
- FOREIGN KEY (app_id, tenant_id, user_id)
- REFERENCES all_auth_recipe_users (app_id, tenant_id, user_id) ON DELETE CASCADE
-);
-
-INSERT INTO passwordless_user_to_tenant (user_id, email, phone_number)
- SELECT user_id, email, phone_number FROM passwordless_users;
-
-------------------------------------------------------------
-
-ALTER TABLE passwordless_devices
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public',
- ADD COLUMN tenant_id VARCHAR(64) DEFAULT 'public';
-
-ALTER TABLE passwordless_devices
- DROP CONSTRAINT passwordless_devices_pkey CASCADE;
-
-ALTER TABLE passwordless_devices
- ADD CONSTRAINT passwordless_devices_pkey
- PRIMARY KEY (app_id, tenant_id, device_id_hash);
-
-ALTER TABLE passwordless_devices
- ADD CONSTRAINT passwordless_devices_tenant_id_fkey
- FOREIGN KEY (app_id, tenant_id)
- REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE;
-
-DROP INDEX passwordless_devices_email_index;
-
-CREATE INDEX passwordless_devices_email_index ON passwordless_devices (app_id, tenant_id, email);
-
-DROP INDEX passwordless_devices_phone_number_index;
-
-CREATE INDEX passwordless_devices_phone_number_index ON passwordless_devices (app_id, tenant_id, phone_number);
-
-------------------------------------------------------------
-
-ALTER TABLE passwordless_codes
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public',
- ADD COLUMN tenant_id VARCHAR(64) DEFAULT 'public';
-
-ALTER TABLE passwordless_codes
- DROP CONSTRAINT passwordless_codes_pkey CASCADE;
-
-ALTER TABLE passwordless_codes
- ADD CONSTRAINT passwordless_codes_pkey
- PRIMARY KEY (app_id, tenant_id, code_id);
-
-ALTER TABLE passwordless_codes
- DROP CONSTRAINT IF EXISTS passwordless_codes_device_id_hash_fkey;
-
-ALTER TABLE passwordless_codes
- ADD CONSTRAINT passwordless_codes_device_id_hash_fkey
- FOREIGN KEY (app_id, tenant_id, device_id_hash)
- REFERENCES passwordless_devices (app_id, tenant_id, device_id_hash) ON DELETE CASCADE;
-
-ALTER TABLE passwordless_codes
- DROP CONSTRAINT passwordless_codes_link_code_hash_key;
-
-ALTER TABLE passwordless_codes
- ADD CONSTRAINT passwordless_codes_link_code_hash_key
- UNIQUE (app_id, tenant_id, link_code_hash);
-
-DROP INDEX passwordless_codes_created_at_index;
-
-CREATE INDEX passwordless_codes_created_at_index ON passwordless_codes (app_id, tenant_id, created_at);
-
-DROP INDEX passwordless_codes_device_id_hash_index;
-CREATE INDEX passwordless_codes_device_id_hash_index ON passwordless_codes (app_id, tenant_id, device_id_hash);
-
--- ThirdParty
-
-ALTER TABLE thirdparty_users
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+1. Ensure that the core is already upgraded to version 5.0.0 (CDI version 2.21)
+2. Stop the core instance(s)
+3. Run the migration script
-ALTER TABLE thirdparty_users
- DROP CONSTRAINT thirdparty_users_pkey CASCADE;
+
+
+ If using PostgreSQL
+
+ #### Run the following SQL script
-ALTER TABLE thirdparty_users
- DROP CONSTRAINT thirdparty_users_user_id_key CASCADE;
+ ```sql
+ -- General Tables
-ALTER TABLE thirdparty_users
- ADD CONSTRAINT thirdparty_users_pkey
- PRIMARY KEY (app_id, user_id);
+ CREATE TABLE IF NOT EXISTS apps (
+ app_id VARCHAR(64) NOT NULL DEFAULT 'public',
+ created_at_time BIGINT,
+ CONSTRAINT apps_pkey PRIMARY KEY(app_id)
+ );
-ALTER TABLE thirdparty_users
- ADD CONSTRAINT thirdparty_users_user_id_fkey
- FOREIGN KEY (app_id, user_id)
- REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE;
+ INSERT INTO apps (app_id, created_at_time)
+ VALUES ('public', 0) ON CONFLICT DO NOTHING;
-DROP INDEX IF EXISTS thirdparty_users_thirdparty_user_id_index;
+ ------------------------------------------------------------
-CREATE INDEX thirdparty_users_thirdparty_user_id_index ON thirdparty_users (app_id, third_party_id, third_party_user_id);
+ CREATE TABLE IF NOT EXISTS tenants (
+ app_id VARCHAR(64) NOT NULL DEFAULT 'public',
+ tenant_id VARCHAR(64) NOT NULL DEFAULT 'public',
+ created_at_time BIGINT ,
+ CONSTRAINT tenants_pkey
+ PRIMARY KEY (app_id, tenant_id),
+ CONSTRAINT tenants_app_id_fkey FOREIGN KEY(app_id)
+ REFERENCES apps (app_id) ON DELETE CASCADE
+ );
-DROP INDEX IF EXISTS thirdparty_users_email_index;
+ INSERT INTO tenants (app_id, tenant_id, created_at_time)
+ VALUES ('public', 'public', 0) ON CONFLICT DO NOTHING;
-CREATE INDEX thirdparty_users_email_index ON thirdparty_users (app_id, email);
+ CREATE INDEX IF NOT EXISTS tenants_app_id_index ON tenants (app_id);
-------------------------------------------------------------
+ ------------------------------------------------------------
-CREATE TABLE IF NOT EXISTS thirdparty_user_to_tenant (
- app_id VARCHAR(64) DEFAULT 'public',
- tenant_id VARCHAR(64) DEFAULT 'public',
- user_id CHAR(36) NOT NULL,
- third_party_id VARCHAR(28) NOT NULL,
- third_party_user_id VARCHAR(256) NOT NULL,
- CONSTRAINT thirdparty_user_to_tenant_third_party_user_id_key
- UNIQUE (app_id, tenant_id, third_party_id, third_party_user_id),
- CONSTRAINT thirdparty_user_to_tenant_pkey
- PRIMARY KEY (app_id, tenant_id, user_id),
- CONSTRAINT thirdparty_user_to_tenant_user_id_fkey
- FOREIGN KEY (app_id, tenant_id, user_id)
- REFERENCES all_auth_recipe_users (app_id, tenant_id, user_id) ON DELETE CASCADE
-);
+ ALTER TABLE key_value
+ ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public',
+ ADD COLUMN IF NOT EXISTS tenant_id VARCHAR(64) DEFAULT 'public';
-INSERT INTO thirdparty_user_to_tenant (user_id, third_party_id, third_party_user_id)
- SELECT user_id, third_party_id, third_party_user_id FROM thirdparty_users;
+ ALTER TABLE key_value
+ DROP CONSTRAINT key_value_pkey;
+
+ ALTER TABLE key_value
+ ADD CONSTRAINT key_value_pkey
+ PRIMARY KEY (app_id, tenant_id, name);
+
+ ALTER TABLE key_value
+ DROP CONSTRAINT IF EXISTS key_value_tenant_id_fkey;
+
+ ALTER TABLE key_value
+ ADD CONSTRAINT key_value_tenant_id_fkey
+ FOREIGN KEY (app_id, tenant_id)
+ REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE;
+
+ CREATE INDEX IF NOT EXISTS key_value_tenant_id_index ON key_value (app_id, tenant_id);
+
+ ------------------------------------------------------------
+
+ CREATE TABLE IF NOT EXISTS app_id_to_user_id (
+ app_id VARCHAR(64) NOT NULL DEFAULT 'public',
+ user_id CHAR(36) NOT NULL,
+ recipe_id VARCHAR(128) NOT NULL,
+ CONSTRAINT app_id_to_user_id_pkey
+ PRIMARY KEY (app_id, user_id),
+ CONSTRAINT app_id_to_user_id_app_id_fkey
+ FOREIGN KEY(app_id) REFERENCES apps (app_id) ON DELETE CASCADE
+ );
+
+ INSERT INTO app_id_to_user_id (user_id, recipe_id)
+ SELECT user_id, recipe_id
+ FROM all_auth_recipe_users ON CONFLICT DO NOTHING;
+
+ CREATE INDEX IF NOT EXISTS app_id_to_user_id_app_id_index ON app_id_to_user_id (app_id);
+
+ ------------------------------------------------------------
+
+ ALTER TABLE all_auth_recipe_users
+ ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public',
+ ADD COLUMN IF NOT EXISTS tenant_id VARCHAR(64) DEFAULT 'public';
+
+ ALTER TABLE all_auth_recipe_users
+ DROP CONSTRAINT all_auth_recipe_users_pkey CASCADE;
+
+ ALTER TABLE all_auth_recipe_users
+ ADD CONSTRAINT all_auth_recipe_users_pkey
+ PRIMARY KEY (app_id, tenant_id, user_id);
+
+ ALTER TABLE all_auth_recipe_users
+ DROP CONSTRAINT IF EXISTS all_auth_recipe_users_tenant_id_fkey;
+
+ ALTER TABLE all_auth_recipe_users
+ ADD CONSTRAINT all_auth_recipe_users_tenant_id_fkey
+ FOREIGN KEY (app_id, tenant_id)
+ REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE;
+
+ ALTER TABLE all_auth_recipe_users
+ DROP CONSTRAINT IF EXISTS all_auth_recipe_users_user_id_fkey;
+
+ ALTER TABLE all_auth_recipe_users
+ ADD CONSTRAINT all_auth_recipe_users_user_id_fkey
+ FOREIGN KEY (app_id, user_id)
+ REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE;
+
+ DROP INDEX all_auth_recipe_users_pagination_index;
+
+ CREATE INDEX all_auth_recipe_users_pagination_index ON all_auth_recipe_users (time_joined DESC, user_id DESC, tenant_id DESC, app_id DESC);
+
+ CREATE INDEX IF NOT EXISTS all_auth_recipe_user_id_index ON all_auth_recipe_users (app_id, user_id);
+
+ CREATE INDEX IF NOT EXISTS all_auth_recipe_tenant_id_index ON all_auth_recipe_users (app_id, tenant_id);
+
+ -- Multitenancy
+
+ CREATE TABLE IF NOT EXISTS tenant_configs (
+ connection_uri_domain VARCHAR(256) DEFAULT '',
+ app_id VARCHAR(64) DEFAULT 'public',
+ tenant_id VARCHAR(64) DEFAULT 'public',
+ core_config TEXT,
+ email_password_enabled BOOLEAN,
+ passwordless_enabled BOOLEAN,
+ third_party_enabled BOOLEAN,
+ CONSTRAINT tenant_configs_pkey
+ PRIMARY KEY (connection_uri_domain, app_id, tenant_id)
+ );
+
+ ------------------------------------------------------------
+
+ CREATE TABLE IF NOT EXISTS tenant_thirdparty_providers (
+ connection_uri_domain VARCHAR(256) DEFAULT '',
+ app_id VARCHAR(64) DEFAULT 'public',
+ tenant_id VARCHAR(64) DEFAULT 'public',
+ third_party_id VARCHAR(28) NOT NULL,
+ name VARCHAR(64),
+ authorization_endpoint TEXT,
+ authorization_endpoint_query_params TEXT,
+ token_endpoint TEXT,
+ token_endpoint_body_params TEXT,
+ user_info_endpoint TEXT,
+ user_info_endpoint_query_params TEXT,
+ user_info_endpoint_headers TEXT,
+ jwks_uri TEXT,
+ oidc_discovery_endpoint TEXT,
+ require_email BOOLEAN,
+ user_info_map_from_id_token_payload_user_id VARCHAR(64),
+ user_info_map_from_id_token_payload_email VARCHAR(64),
+ user_info_map_from_id_token_payload_email_verified VARCHAR(64),
+ user_info_map_from_user_info_endpoint_user_id VARCHAR(64),
+ user_info_map_from_user_info_endpoint_email VARCHAR(64),
+ user_info_map_from_user_info_endpoint_email_verified VARCHAR(64),
+ CONSTRAINT tenant_thirdparty_providers_pkey
+ PRIMARY KEY (connection_uri_domain, app_id, tenant_id, third_party_id),
+ CONSTRAINT tenant_thirdparty_providers_tenant_id_fkey
+ FOREIGN KEY(connection_uri_domain, app_id, tenant_id)
+ REFERENCES tenant_configs (connection_uri_domain, app_id, tenant_id) ON DELETE CASCADE
+ );
+
+ CREATE INDEX IF NOT EXISTS tenant_thirdparty_providers_tenant_id_index ON tenant_thirdparty_providers (connection_uri_domain, app_id, tenant_id);
+
+ ------------------------------------------------------------
+
+ CREATE TABLE IF NOT EXISTS tenant_thirdparty_provider_clients (
+ connection_uri_domain VARCHAR(256) DEFAULT '',
+ app_id VARCHAR(64) DEFAULT 'public',
+ tenant_id VARCHAR(64) DEFAULT 'public',
+ third_party_id VARCHAR(28) NOT NULL,
+ client_type VARCHAR(64) NOT NULL DEFAULT '',
+ client_id VARCHAR(256) NOT NULL,
+ client_secret TEXT,
+ scope VARCHAR(128)[],
+ force_pkce BOOLEAN,
+ additional_config TEXT,
+ CONSTRAINT tenant_thirdparty_provider_clients_pkey
+ PRIMARY KEY (connection_uri_domain, app_id, tenant_id, third_party_id, client_type),
+ CONSTRAINT tenant_thirdparty_provider_clients_third_party_id_fkey
+ FOREIGN KEY (connection_uri_domain, app_id, tenant_id, third_party_id)
+ REFERENCES tenant_thirdparty_providers (connection_uri_domain, app_id, tenant_id, third_party_id) ON DELETE CASCADE
+ );
--- UserIdMapping
+ CREATE INDEX IF NOT EXISTS tenant_thirdparty_provider_clients_third_party_id_index ON tenant_thirdparty_provider_clients (connection_uri_domain, app_id, tenant_id, third_party_id);
-ALTER TABLE userid_mapping
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+ -- Session
-ALTER TABLE userid_mapping
- DROP CONSTRAINT userid_mapping_pkey CASCADE;
+ ALTER TABLE session_info
+ ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public',
+ ADD COLUMN IF NOT EXISTS tenant_id VARCHAR(64) DEFAULT 'public';
-ALTER TABLE userid_mapping
- ADD CONSTRAINT userid_mapping_pkey
- PRIMARY KEY (app_id, supertokens_user_id, external_user_id);
+ ALTER TABLE session_info
+ DROP CONSTRAINT session_info_pkey CASCADE;
-ALTER TABLE userid_mapping
- DROP CONSTRAINT userid_mapping_supertokens_user_id_key;
+ ALTER TABLE session_info
+ ADD CONSTRAINT session_info_pkey
+ PRIMARY KEY (app_id, tenant_id, session_handle);
-ALTER TABLE userid_mapping
- ADD CONSTRAINT userid_mapping_supertokens_user_id_key
- UNIQUE (app_id, supertokens_user_id);
+ ALTER TABLE session_info
+ DROP CONSTRAINT IF EXISTS session_info_tenant_id_fkey;
-ALTER TABLE userid_mapping
- DROP CONSTRAINT userid_mapping_external_user_id_key;
+ ALTER TABLE session_info
+ ADD CONSTRAINT session_info_tenant_id_fkey
+ FOREIGN KEY (app_id, tenant_id)
+ REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE;
-ALTER TABLE userid_mapping
- ADD CONSTRAINT userid_mapping_external_user_id_key
- UNIQUE (app_id, external_user_id);
+ CREATE INDEX IF NOT EXISTS session_expiry_index ON session_info (expires_at);
-ALTER TABLE userid_mapping
- DROP CONSTRAINT IF EXISTS userid_mapping_supertokens_user_id_fkey;
+ CREATE INDEX IF NOT EXISTS session_info_tenant_id_index ON session_info (app_id, tenant_id);
-ALTER TABLE userid_mapping
- ADD CONSTRAINT userid_mapping_supertokens_user_id_fkey
- FOREIGN KEY (app_id, supertokens_user_id)
- REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE;
+ ------------------------------------------------------------
--- UserRoles
+ ALTER TABLE session_access_token_signing_keys
+ ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public';
-ALTER TABLE roles
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+ ALTER TABLE session_access_token_signing_keys
+ DROP CONSTRAINT session_access_token_signing_keys_pkey CASCADE;
-ALTER TABLE roles
- DROP CONSTRAINT roles_pkey CASCADE;
+ ALTER TABLE session_access_token_signing_keys
+ ADD CONSTRAINT session_access_token_signing_keys_pkey
+ PRIMARY KEY (app_id, created_at_time);
-ALTER TABLE roles
- ADD CONSTRAINT roles_pkey
- PRIMARY KEY (app_id, role);
+ ALTER TABLE session_access_token_signing_keys
+ DROP CONSTRAINT IF EXISTS session_access_token_signing_keys_app_id_fkey;
-ALTER TABLE roles
- ADD CONSTRAINT roles_app_id_fkey
- FOREIGN KEY (app_id)
- REFERENCES apps (app_id) ON DELETE CASCADE;
+ ALTER TABLE session_access_token_signing_keys
+ ADD CONSTRAINT session_access_token_signing_keys_app_id_fkey
+ FOREIGN KEY (app_id)
+ REFERENCES apps (app_id) ON DELETE CASCADE;
-------------------------------------------------------------
+ CREATE INDEX IF NOT EXISTS access_token_signing_keys_app_id_index ON session_access_token_signing_keys (app_id);
-ALTER TABLE role_permissions
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+ -- JWT
+
+ ALTER TABLE jwt_signing_keys
+ ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public';
+
+ ALTER TABLE jwt_signing_keys
+ DROP CONSTRAINT jwt_signing_keys_pkey CASCADE;
-ALTER TABLE role_permissions
- DROP CONSTRAINT role_permissions_pkey CASCADE;
+ ALTER TABLE jwt_signing_keys
+ ADD CONSTRAINT jwt_signing_keys_pkey
+ PRIMARY KEY (app_id, key_id);
-ALTER TABLE role_permissions
- ADD CONSTRAINT role_permissions_pkey
- PRIMARY KEY (app_id, role, permission);
+ ALTER TABLE jwt_signing_keys
+ DROP CONSTRAINT IF EXISTS jwt_signing_keys_app_id_fkey;
-ALTER TABLE role_permissions
- DROP CONSTRAINT IF EXISTS role_permissions_role_fkey;
+ ALTER TABLE jwt_signing_keys
+ ADD CONSTRAINT jwt_signing_keys_app_id_fkey
+ FOREIGN KEY (app_id)
+ REFERENCES apps (app_id) ON DELETE CASCADE;
-ALTER TABLE role_permissions
- ADD CONSTRAINT role_permissions_role_fkey
- FOREIGN KEY (app_id, role)
- REFERENCES roles (app_id, role) ON DELETE CASCADE;
+ CREATE INDEX IF NOT EXISTS jwt_signing_keys_app_id_index ON jwt_signing_keys (app_id);
-DROP INDEX role_permissions_permission_index;
+ -- EmailVerification
-CREATE INDEX role_permissions_permission_index ON role_permissions (app_id, permission);
+ ALTER TABLE emailverification_verified_emails
+ ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public';
-------------------------------------------------------------
+ ALTER TABLE emailverification_verified_emails
+ DROP CONSTRAINT emailverification_verified_emails_pkey CASCADE;
-ALTER TABLE user_roles
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public',
- ADD COLUMN tenant_id VARCHAR(64) DEFAULT 'public';
+ ALTER TABLE emailverification_verified_emails
+ ADD CONSTRAINT emailverification_verified_emails_pkey
+ PRIMARY KEY (app_id, user_id, email);
-ALTER TABLE user_roles
- DROP CONSTRAINT user_roles_pkey CASCADE;
+ ALTER TABLE emailverification_verified_emails
+ DROP CONSTRAINT IF EXISTS emailverification_verified_emails_app_id_fkey;
-ALTER TABLE user_roles
- ADD CONSTRAINT user_roles_pkey
- PRIMARY KEY (app_id, tenant_id, user_id, role);
+ ALTER TABLE emailverification_verified_emails
+ ADD CONSTRAINT emailverification_verified_emails_app_id_fkey
+ FOREIGN KEY (app_id)
+ REFERENCES apps (app_id) ON DELETE CASCADE;
-ALTER TABLE user_roles
- ADD CONSTRAINT user_roles_tenant_id_fkey
- FOREIGN KEY (app_id, tenant_id)
- REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE;
+ CREATE INDEX IF NOT EXISTS emailverification_verified_emails_app_id_index ON emailverification_verified_emails (app_id);
-ALTER TABLE user_roles
- DROP CONSTRAINT IF EXISTS user_roles_role_fkey;
+ ------------------------------------------------------------
-ALTER TABLE user_roles
- ADD CONSTRAINT user_roles_role_fkey
- FOREIGN KEY (app_id, role)
- REFERENCES roles (app_id, role) ON DELETE CASCADE;
+ ALTER TABLE emailverification_tokens
+ ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public',
+ ADD COLUMN IF NOT EXISTS tenant_id VARCHAR(64) DEFAULT 'public';
-DROP INDEX user_roles_role_index;
+ ALTER TABLE emailverification_tokens
+ DROP CONSTRAINT emailverification_tokens_pkey CASCADE;
-CREATE INDEX user_roles_role_index ON user_roles (app_id, tenant_id, role);
+ ALTER TABLE emailverification_tokens
+ ADD CONSTRAINT emailverification_tokens_pkey
+ PRIMARY KEY (app_id, tenant_id, user_id, email, token);
--- UserMetadata
+ ALTER TABLE emailverification_tokens
+ DROP CONSTRAINT IF EXISTS emailverification_tokens_tenant_id_fkey;
-ALTER TABLE user_metadata
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+ ALTER TABLE emailverification_tokens
+ ADD CONSTRAINT emailverification_tokens_tenant_id_fkey
+ FOREIGN KEY (app_id, tenant_id)
+ REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE;
-ALTER TABLE user_metadata
- DROP CONSTRAINT user_metadata_pkey CASCADE;
+ CREATE INDEX IF NOT EXISTS emailverification_tokens_tenant_id_index ON emailverification_tokens (app_id, tenant_id);
-ALTER TABLE user_metadata
- ADD CONSTRAINT user_metadata_pkey
- PRIMARY KEY (app_id, user_id);
+ -- EmailPassword
-ALTER TABLE user_metadata
- ADD CONSTRAINT user_metadata_app_id_fkey
- FOREIGN KEY (app_id)
- REFERENCES apps (app_id) ON DELETE CASCADE;
+ ALTER TABLE emailpassword_users
+ ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public';
--- Dashboard
+ ALTER TABLE emailpassword_users
+ DROP CONSTRAINT emailpassword_users_pkey CASCADE;
-ALTER TABLE dashboard_users
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+ ALTER TABLE emailpassword_users
+ DROP CONSTRAINT IF EXISTS emailpassword_users_email_key CASCADE;
-ALTER TABLE dashboard_users
- DROP CONSTRAINT dashboard_users_pkey CASCADE;
+ ALTER TABLE emailpassword_users
+ ADD CONSTRAINT emailpassword_users_pkey
+ PRIMARY KEY (app_id, user_id);
-ALTER TABLE dashboard_users
- ADD CONSTRAINT dashboard_users_pkey
- PRIMARY KEY (app_id, user_id);
+ ALTER TABLE emailpassword_users
+ DROP CONSTRAINT IF EXISTS emailpassword_users_user_id_fkey;
-ALTER TABLE dashboard_users
- DROP CONSTRAINT dashboard_users_email_key;
+ ALTER TABLE emailpassword_users
+ ADD CONSTRAINT emailpassword_users_user_id_fkey
+ FOREIGN KEY (app_id, user_id)
+ REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE;
-ALTER TABLE dashboard_users
- ADD CONSTRAINT dashboard_users_email_key
- UNIQUE (app_id, email);
+ ------------------------------------------------------------
-ALTER TABLE dashboard_users
- ADD CONSTRAINT dashboard_users_app_id_fkey
- FOREIGN KEY (app_id)
- REFERENCES apps (app_id) ON DELETE CASCADE;
+ CREATE TABLE IF NOT EXISTS emailpassword_user_to_tenant (
+ app_id VARCHAR(64) DEFAULT 'public',
+ tenant_id VARCHAR(64) DEFAULT 'public',
+ user_id CHAR(36) NOT NULL,
+ email VARCHAR(256) NOT NULL,
+ CONSTRAINT emailpassword_user_to_tenant_email_key
+ UNIQUE (app_id, tenant_id, email),
+ CONSTRAINT emailpassword_user_to_tenant_pkey
+ PRIMARY KEY (app_id, tenant_id, user_id),
+ CONSTRAINT emailpassword_user_to_tenant_user_id_fkey
+ FOREIGN KEY (app_id, tenant_id, user_id)
+ REFERENCES all_auth_recipe_users (app_id, tenant_id, user_id) ON DELETE CASCADE
+ );
-------------------------------------------------------------
+ ALTER TABLE emailpassword_user_to_tenant
+ DROP CONSTRAINT IF EXISTS emailpassword_user_to_tenant_email_key;
-ALTER TABLE dashboard_user_sessions
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+ ALTER TABLE emailpassword_user_to_tenant
+ ADD CONSTRAINT emailpassword_user_to_tenant_email_key
+ UNIQUE (app_id, tenant_id, email);
-ALTER TABLE dashboard_user_sessions
- DROP CONSTRAINT dashboard_user_sessions_pkey CASCADE;
+ ALTER TABLE emailpassword_user_to_tenant
+ DROP CONSTRAINT IF EXISTS emailpassword_user_to_tenant_user_id_fkey;
-ALTER TABLE dashboard_user_sessions
- ADD CONSTRAINT dashboard_user_sessions_pkey
- PRIMARY KEY (app_id, session_id);
+ ALTER TABLE emailpassword_user_to_tenant
+ ADD CONSTRAINT emailpassword_user_to_tenant_user_id_fkey
+ FOREIGN KEY (app_id, tenant_id, user_id)
+ REFERENCES all_auth_recipe_users (app_id, tenant_id, user_id) ON DELETE CASCADE;
-ALTER TABLE dashboard_user_sessions
- DROP CONSTRAINT IF EXISTS dashboard_user_sessions_user_id_fkey;
+ INSERT INTO emailpassword_user_to_tenant (user_id, email)
+ SELECT user_id, email FROM emailpassword_users ON CONFLICT DO NOTHING;
-ALTER TABLE dashboard_user_sessions
- ADD CONSTRAINT dashboard_user_sessions_user_id_fkey
- FOREIGN KEY (app_id, user_id)
- REFERENCES dashboard_users (app_id, user_id) ON DELETE CASCADE;
+ ------------------------------------------------------------
--- TOTP
+ ALTER TABLE emailpassword_pswd_reset_tokens
+ ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public';
-ALTER TABLE totp_users
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+ ALTER TABLE emailpassword_pswd_reset_tokens
+ DROP CONSTRAINT emailpassword_pswd_reset_tokens_pkey CASCADE;
-ALTER TABLE totp_users
- DROP CONSTRAINT totp_users_pkey CASCADE;
+ ALTER TABLE emailpassword_pswd_reset_tokens
+ ADD CONSTRAINT emailpassword_pswd_reset_tokens_pkey
+ PRIMARY KEY (app_id, user_id, token);
-ALTER TABLE totp_users
- ADD CONSTRAINT totp_users_pkey
- PRIMARY KEY (app_id, user_id);
+ ALTER TABLE emailpassword_pswd_reset_tokens
+ DROP CONSTRAINT IF EXISTS emailpassword_pswd_reset_tokens_user_id_fkey;
-ALTER TABLE totp_users
- ADD CONSTRAINT totp_users_app_id_fkey
- FOREIGN KEY (app_id)
- REFERENCES apps (app_id) ON DELETE CASCADE;
+ ALTER TABLE emailpassword_pswd_reset_tokens
+ ADD CONSTRAINT emailpassword_pswd_reset_tokens_user_id_fkey
+ FOREIGN KEY (app_id, user_id)
+ REFERENCES emailpassword_users (app_id, user_id) ON DELETE CASCADE;
-------------------------------------------------------------
+ CREATE INDEX IF NOT EXISTS emailpassword_pswd_reset_tokens_user_id_index ON emailpassword_pswd_reset_tokens (app_id, user_id);
-ALTER TABLE totp_user_devices
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+ -- Passwordless
-ALTER TABLE totp_user_devices
- DROP CONSTRAINT totp_user_devices_pkey;
+ ALTER TABLE passwordless_users
+ ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public';
-ALTER TABLE totp_user_devices
- ADD CONSTRAINT totp_user_devices_pkey
- PRIMARY KEY (app_id, user_id, device_name);
+ ALTER TABLE passwordless_users
+ DROP CONSTRAINT passwordless_users_pkey CASCADE;
-ALTER TABLE totp_user_devices
- DROP CONSTRAINT IF EXISTS totp_user_devices_user_id_fkey;
+ ALTER TABLE passwordless_users
+ ADD CONSTRAINT passwordless_users_pkey
+ PRIMARY KEY (app_id, user_id);
-ALTER TABLE totp_user_devices
- ADD CONSTRAINT totp_user_devices_user_id_fkey
- FOREIGN KEY (app_id, user_id)
- REFERENCES totp_users (app_id, user_id) ON DELETE CASCADE;
+ ALTER TABLE passwordless_users
+ DROP CONSTRAINT IF EXISTS passwordless_users_email_key;
-------------------------------------------------------------
+ ALTER TABLE passwordless_users
+ DROP CONSTRAINT IF EXISTS passwordless_users_phone_number_key;
-ALTER TABLE totp_used_codes
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public',
- ADD COLUMN tenant_id VARCHAR(64) DEFAULT 'public';
+ ALTER TABLE passwordless_users
+ DROP CONSTRAINT IF EXISTS passwordless_users_user_id_fkey;
-ALTER TABLE totp_used_codes
- DROP CONSTRAINT totp_used_codes_pkey CASCADE;
+ ALTER TABLE passwordless_users
+ ADD CONSTRAINT passwordless_users_user_id_fkey
+ FOREIGN KEY (app_id, user_id)
+ REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE;
-ALTER TABLE totp_used_codes
- ADD CONSTRAINT totp_used_codes_pkey
- PRIMARY KEY (app_id, tenant_id, user_id, created_time_ms);
+ ------------------------------------------------------------
-ALTER TABLE totp_used_codes
- DROP CONSTRAINT IF EXISTS totp_used_codes_user_id_fkey;
+ CREATE TABLE IF NOT EXISTS passwordless_user_to_tenant (
+ app_id VARCHAR(64) DEFAULT 'public',
+ tenant_id VARCHAR(64) DEFAULT 'public',
+ user_id CHAR(36) NOT NULL,
+ email VARCHAR(256),
+ phone_number VARCHAR(256),
+ CONSTRAINT passwordless_user_to_tenant_email_key
+ UNIQUE (app_id, tenant_id, email),
+ CONSTRAINT passwordless_user_to_tenant_phone_number_key
+ UNIQUE (app_id, tenant_id, phone_number),
+ CONSTRAINT passwordless_user_to_tenant_pkey
+ PRIMARY KEY (app_id, tenant_id, user_id),
+ CONSTRAINT passwordless_user_to_tenant_user_id_fkey
+ FOREIGN KEY (app_id, tenant_id, user_id)
+ REFERENCES all_auth_recipe_users (app_id, tenant_id, user_id) ON DELETE CASCADE
+ );
-ALTER TABLE totp_used_codes
- ADD CONSTRAINT totp_used_codes_user_id_fkey
- FOREIGN KEY (app_id, user_id)
- REFERENCES totp_users (app_id, user_id) ON DELETE CASCADE;
+ ALTER TABLE passwordless_user_to_tenant
+ DROP CONSTRAINT IF EXISTS passwordless_user_to_tenant_user_id_fkey;
-ALTER TABLE totp_used_codes
- ADD CONSTRAINT totp_used_codes_tenant_id_fkey
- FOREIGN KEY (app_id, tenant_id)
- REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE;
+ ALTER TABLE passwordless_user_to_tenant
+ ADD CONSTRAINT passwordless_user_to_tenant_user_id_fkey
+ FOREIGN KEY (app_id, tenant_id, user_id)
+ REFERENCES all_auth_recipe_users (app_id, tenant_id, user_id) ON DELETE CASCADE;
-DROP INDEX totp_used_codes_expiry_time_ms_index;
+ INSERT INTO passwordless_user_to_tenant (user_id, email, phone_number)
+ SELECT user_id, email, phone_number FROM passwordless_users ON CONFLICT DO NOTHING;
-CREATE INDEX totp_used_codes_expiry_time_ms_index ON totp_used_codes (app_id, tenant_id, expiry_time_ms);
+ ------------------------------------------------------------
--- ActiveUsers
+ ALTER TABLE passwordless_devices
+ ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public',
+ ADD COLUMN IF NOT EXISTS tenant_id VARCHAR(64) DEFAULT 'public';
-ALTER TABLE user_last_active
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+ ALTER TABLE passwordless_devices
+ DROP CONSTRAINT passwordless_devices_pkey CASCADE;
-ALTER TABLE user_last_active
- DROP CONSTRAINT user_last_active_pkey CASCADE;
+ ALTER TABLE passwordless_devices
+ ADD CONSTRAINT passwordless_devices_pkey
+ PRIMARY KEY (app_id, tenant_id, device_id_hash);
-ALTER TABLE user_last_active
- ADD CONSTRAINT user_last_active_pkey
- PRIMARY KEY (app_id, user_id);
-```
+ ALTER TABLE passwordless_devices
+ DROP CONSTRAINT IF EXISTS passwordless_devices_tenant_id_fkey;
-
+ ALTER TABLE passwordless_devices
+ ADD CONSTRAINT passwordless_devices_tenant_id_fkey
+ FOREIGN KEY (app_id, tenant_id)
+ REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE;
-
+ DROP INDEX IF EXISTS passwordless_devices_email_index;
-If using MySQL
+ CREATE INDEX IF NOT EXISTS passwordless_devices_email_index ON passwordless_devices (app_id, tenant_id, email);
-#### Run the following SQL script
+ DROP INDEX IF EXISTS passwordless_devices_phone_number_index;
-```sql
--- Drop Foreign keys
+ CREATE INDEX IF NOT EXISTS passwordless_devices_phone_number_index ON passwordless_devices (app_id, tenant_id, phone_number);
-ALTER TABLE emailpassword_pswd_reset_tokens
- DROP FOREIGN KEY emailpassword_pswd_reset_tokens_ibfk_1;
+ CREATE INDEX IF NOT EXISTS passwordless_devices_tenant_id_index ON passwordless_devices (app_id, tenant_id);
-ALTER TABLE passwordless_codes
- DROP FOREIGN KEY passwordless_codes_ibfk_1;
+ ------------------------------------------------------------
-ALTER TABLE userid_mapping
- DROP FOREIGN KEY userid_mapping_ibfk_1;
+ ALTER TABLE passwordless_codes
+ ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public',
+ ADD COLUMN IF NOT EXISTS tenant_id VARCHAR(64) DEFAULT 'public';
-ALTER TABLE role_permissions
- DROP FOREIGN KEY role_permissions_ibfk_1;
+ ALTER TABLE passwordless_codes
+ DROP CONSTRAINT passwordless_codes_pkey CASCADE;
-ALTER TABLE user_roles
- DROP FOREIGN KEY user_roles_ibfk_1;
+ ALTER TABLE passwordless_codes
+ ADD CONSTRAINT passwordless_codes_pkey
+ PRIMARY KEY (app_id, tenant_id, code_id);
-ALTER TABLE dashboard_user_sessions
- DROP FOREIGN KEY dashboard_user_sessions_ibfk_1;
+ ALTER TABLE passwordless_codes
+ DROP CONSTRAINT IF EXISTS passwordless_codes_device_id_hash_fkey;
-ALTER TABLE totp_user_devices
- DROP FOREIGN KEY totp_user_devices_ibfk_1;
+ ALTER TABLE passwordless_codes
+ ADD CONSTRAINT passwordless_codes_device_id_hash_fkey
+ FOREIGN KEY (app_id, tenant_id, device_id_hash)
+ REFERENCES passwordless_devices (app_id, tenant_id, device_id_hash) ON DELETE CASCADE;
-ALTER TABLE totp_used_codes
- DROP FOREIGN KEY totp_used_codes_ibfk_1;
+ ALTER TABLE passwordless_codes
+ DROP CONSTRAINT passwordless_codes_link_code_hash_key;
--- General Tables
+ ALTER TABLE passwordless_codes
+ DROP CONSTRAINT IF EXISTS passwordless_codes_link_code_hash_key;
-CREATE TABLE IF NOT EXISTS apps (
- app_id VARCHAR(64) NOT NULL DEFAULT 'public',
- created_at_time BIGINT UNSIGNED,
- PRIMARY KEY(app_id)
-);
+ ALTER TABLE passwordless_codes
+ ADD CONSTRAINT passwordless_codes_link_code_hash_key
+ UNIQUE (app_id, tenant_id, link_code_hash);
-INSERT INTO apps (app_id, created_at_time)
- VALUES ('public', 0);
+ DROP INDEX IF EXISTS passwordless_codes_created_at_index;
-------------------------------------------------------------
+ CREATE INDEX IF NOT EXISTS passwordless_codes_created_at_index ON passwordless_codes (app_id, tenant_id, created_at);
-CREATE TABLE IF NOT EXISTS tenants (
- app_id VARCHAR(64) NOT NULL DEFAULT 'public',
- tenant_id VARCHAR(64) NOT NULL DEFAULT 'public',
- created_at_time BIGINT UNSIGNED,
- PRIMARY KEY (app_id, tenant_id),
- FOREIGN KEY(app_id)
- REFERENCES apps (app_id) ON DELETE CASCADE
-);
+ DROP INDEX IF EXISTS passwordless_codes_device_id_hash_index;
+ CREATE INDEX IF NOT EXISTS passwordless_codes_device_id_hash_index ON passwordless_codes (app_id, tenant_id, device_id_hash);
-INSERT INTO tenants (app_id, tenant_id, created_at_time)
- VALUES ('public', 'public', 0);
+ -- ThirdParty
-------------------------------------------------------------
+ ALTER TABLE thirdparty_users
+ ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public';
-ALTER TABLE key_value
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public',
- ADD COLUMN tenant_id VARCHAR(64) DEFAULT 'public';
+ ALTER TABLE thirdparty_users
+ DROP CONSTRAINT thirdparty_users_pkey CASCADE;
-ALTER TABLE key_value
- DROP PRIMARY KEY;
+ ALTER TABLE thirdparty_users
+ DROP CONSTRAINT IF EXISTS thirdparty_users_user_id_key CASCADE;
-ALTER TABLE key_value
- ADD PRIMARY KEY (app_id, tenant_id, name);
+ ALTER TABLE thirdparty_users
+ ADD CONSTRAINT thirdparty_users_pkey
+ PRIMARY KEY (app_id, user_id);
-ALTER TABLE key_value
- ADD FOREIGN KEY (app_id, tenant_id)
- REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE;
-
--- CREATE INDEX key_value_tenant_id_index ON key_value (app_id, tenant_id);
+ ALTER TABLE thirdparty_users
+ DROP CONSTRAINT IF EXISTS thirdparty_users_user_id_fkey;
-------------------------------------------------------------
+ ALTER TABLE thirdparty_users
+ ADD CONSTRAINT thirdparty_users_user_id_fkey
+ FOREIGN KEY (app_id, user_id)
+ REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE;
-CREATE TABLE IF NOT EXISTS app_id_to_user_id (
- app_id VARCHAR(64) NOT NULL DEFAULT 'public',
- user_id CHAR(36) NOT NULL,
- recipe_id VARCHAR(128) NOT NULL,
- PRIMARY KEY (app_id, user_id),
- FOREIGN KEY(app_id) REFERENCES apps (app_id) ON DELETE CASCADE
-);
+ DROP INDEX IF EXISTS thirdparty_users_thirdparty_user_id_index;
-INSERT INTO app_id_to_user_id (user_id, recipe_id)
- SELECT user_id, recipe_id
- FROM all_auth_recipe_users;
+ CREATE INDEX IF NOT EXISTS thirdparty_users_thirdparty_user_id_index ON thirdparty_users (app_id, third_party_id, third_party_user_id);
-------------------------------------------------------------
+ DROP INDEX IF EXISTS thirdparty_users_email_index;
-ALTER TABLE all_auth_recipe_users
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public',
- ADD COLUMN tenant_id VARCHAR(64) DEFAULT 'public';
+ CREATE INDEX IF NOT EXISTS thirdparty_users_email_index ON thirdparty_users (app_id, email);
-ALTER TABLE all_auth_recipe_users
- DROP PRIMARY KEY;
+ ------------------------------------------------------------
-ALTER TABLE all_auth_recipe_users
- ADD PRIMARY KEY (app_id, tenant_id, user_id);
+ CREATE TABLE IF NOT EXISTS thirdparty_user_to_tenant (
+ app_id VARCHAR(64) DEFAULT 'public',
+ tenant_id VARCHAR(64) DEFAULT 'public',
+ user_id CHAR(36) NOT NULL,
+ third_party_id VARCHAR(28) NOT NULL,
+ third_party_user_id VARCHAR(256) NOT NULL,
+ CONSTRAINT thirdparty_user_to_tenant_third_party_user_id_key
+ UNIQUE (app_id, tenant_id, third_party_id, third_party_user_id),
+ CONSTRAINT thirdparty_user_to_tenant_pkey
+ PRIMARY KEY (app_id, tenant_id, user_id),
+ CONSTRAINT thirdparty_user_to_tenant_user_id_fkey
+ FOREIGN KEY (app_id, tenant_id, user_id)
+ REFERENCES all_auth_recipe_users (app_id, tenant_id, user_id) ON DELETE CASCADE
+ );
-ALTER TABLE all_auth_recipe_users
- ADD FOREIGN KEY (app_id, tenant_id)
- REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE;
+ ALTER TABLE thirdparty_user_to_tenant
+ DROP CONSTRAINT IF EXISTS thirdparty_user_to_tenant_third_party_user_id_key;
-ALTER TABLE all_auth_recipe_users
- ADD FOREIGN KEY (app_id, user_id)
- REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE;
-
-ALTER TABLE all_auth_recipe_users
- DROP INDEX all_auth_recipe_users_pagination_index;
-
-CREATE INDEX all_auth_recipe_users_pagination_index ON all_auth_recipe_users (time_joined DESC, user_id DESC, tenant_id DESC, app_id DESC);
+ ALTER TABLE thirdparty_user_to_tenant
+ ADD CONSTRAINT thirdparty_user_to_tenant_third_party_user_id_key
+ UNIQUE (app_id, tenant_id, third_party_id, third_party_user_id);
--- Multitenancy
+ ALTER TABLE thirdparty_user_to_tenant
+ DROP CONSTRAINT IF EXISTS thirdparty_user_to_tenant_user_id_fkey;
-CREATE TABLE IF NOT EXISTS tenant_configs (
- connection_uri_domain VARCHAR(256) DEFAULT '',
- app_id VARCHAR(64) DEFAULT 'public',
- tenant_id VARCHAR(64) DEFAULT 'public',
- core_config TEXT,
- email_password_enabled BOOLEAN,
- passwordless_enabled BOOLEAN,
- third_party_enabled BOOLEAN,
- PRIMARY KEY (connection_uri_domain, app_id, tenant_id)
-);
-
-------------------------------------------------------------
+ ALTER TABLE thirdparty_user_to_tenant
+ ADD CONSTRAINT thirdparty_user_to_tenant_user_id_fkey
+ FOREIGN KEY (app_id, tenant_id, user_id)
+ REFERENCES all_auth_recipe_users (app_id, tenant_id, user_id) ON DELETE CASCADE;
-CREATE TABLE IF NOT EXISTS tenant_thirdparty_providers (
- connection_uri_domain VARCHAR(256) DEFAULT '',
- app_id VARCHAR(64) DEFAULT 'public',
- tenant_id VARCHAR(64) DEFAULT 'public',
- third_party_id VARCHAR(28) NOT NULL,
- name VARCHAR(64),
- authorization_endpoint TEXT,
- authorization_endpoint_query_params TEXT,
- token_endpoint TEXT,
- token_endpoint_body_params TEXT,
- user_info_endpoint TEXT,
- user_info_endpoint_query_params TEXT,
- user_info_endpoint_headers TEXT,
- jwks_uri TEXT,
- oidc_discovery_endpoint TEXT,
- require_email BOOLEAN,
- user_info_map_from_id_token_payload_user_id VARCHAR(64),
- user_info_map_from_id_token_payload_email VARCHAR(64),
- user_info_map_from_id_token_payload_email_verified VARCHAR(64),
- user_info_map_from_user_info_endpoint_user_id VARCHAR(64),
- user_info_map_from_user_info_endpoint_email VARCHAR(64),
- user_info_map_from_user_info_endpoint_email_verified VARCHAR(64),
- PRIMARY KEY (connection_uri_domain, app_id, tenant_id, third_party_id),
- FOREIGN KEY(connection_uri_domain, app_id, tenant_id)
- REFERENCES tenant_configs (connection_uri_domain, app_id, tenant_id) ON DELETE CASCADE
-);
+ INSERT INTO thirdparty_user_to_tenant (user_id, third_party_id, third_party_user_id)
+ SELECT user_id, third_party_id, third_party_user_id FROM thirdparty_users ON CONFLICT DO NOTHING;
-------------------------------------------------------------
+ -- UserIdMapping
-CREATE TABLE IF NOT EXISTS tenant_thirdparty_provider_clients (
- connection_uri_domain VARCHAR(256) DEFAULT '',
- app_id VARCHAR(64) DEFAULT 'public',
- tenant_id VARCHAR(64) DEFAULT 'public',
- third_party_id VARCHAR(28) NOT NULL,
- client_type VARCHAR(64) NOT NULL DEFAULT '',
- client_id VARCHAR(256) NOT NULL,
- client_secret TEXT,
- scope TEXT,
- force_pkce BOOLEAN,
- additional_config TEXT,
- PRIMARY KEY (connection_uri_domain, app_id, tenant_id, third_party_id, client_type),
- FOREIGN KEY (connection_uri_domain, app_id, tenant_id, third_party_id)
- REFERENCES tenant_thirdparty_providers (connection_uri_domain, app_id, tenant_id, third_party_id) ON DELETE CASCADE
-);
+ ALTER TABLE userid_mapping
+ ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public';
+ ALTER TABLE userid_mapping
+ DROP CONSTRAINT IF EXISTS userid_mapping_pkey CASCADE;
--- Session
+ ALTER TABLE userid_mapping
+ ADD CONSTRAINT userid_mapping_pkey
+ PRIMARY KEY (app_id, supertokens_user_id, external_user_id);
-ALTER TABLE session_info
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public',
- ADD COLUMN tenant_id VARCHAR(64) DEFAULT 'public';
+ ALTER TABLE userid_mapping
+ DROP CONSTRAINT IF EXISTS userid_mapping_supertokens_user_id_key;
-ALTER TABLE session_info
- DROP PRIMARY KEY;
+ ALTER TABLE userid_mapping
+ ADD CONSTRAINT userid_mapping_supertokens_user_id_key
+ UNIQUE (app_id, supertokens_user_id);
-ALTER TABLE session_info
- ADD PRIMARY KEY (app_id, tenant_id, session_handle);
+ ALTER TABLE userid_mapping
+ DROP CONSTRAINT IF EXISTS userid_mapping_external_user_id_key;
-ALTER TABLE session_info
- ADD FOREIGN KEY (app_id, tenant_id)
- REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE;
+ ALTER TABLE userid_mapping
+ ADD CONSTRAINT userid_mapping_external_user_id_key
+ UNIQUE (app_id, external_user_id);
-CREATE INDEX session_expiry_index ON session_info (expires_at);
+ ALTER TABLE userid_mapping
+ DROP CONSTRAINT IF EXISTS userid_mapping_supertokens_user_id_fkey;
-------------------------------------------------------------
+ ALTER TABLE userid_mapping
+ ADD CONSTRAINT userid_mapping_supertokens_user_id_fkey
+ FOREIGN KEY (app_id, supertokens_user_id)
+ REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE;
-ALTER TABLE session_access_token_signing_keys
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+ CREATE INDEX IF NOT EXISTS userid_mapping_supertokens_user_id_index ON userid_mapping (app_id, supertokens_user_id);
-ALTER TABLE session_access_token_signing_keys
- DROP PRIMARY KEY;
+ -- UserRoles
-ALTER TABLE session_access_token_signing_keys
- ADD PRIMARY KEY (app_id, created_at_time);
+ ALTER TABLE roles
+ ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public';
-ALTER TABLE session_access_token_signing_keys
- ADD FOREIGN KEY (app_id)
- REFERENCES apps (app_id) ON DELETE CASCADE;
+ ALTER TABLE roles
+ DROP CONSTRAINT roles_pkey CASCADE;
--- JWT
+ ALTER TABLE roles
+ ADD CONSTRAINT roles_pkey
+ PRIMARY KEY (app_id, role);
-ALTER TABLE jwt_signing_keys
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+ ALTER TABLE roles
+ DROP CONSTRAINT IF EXISTS roles_app_id_fkey;
-ALTER TABLE jwt_signing_keys
- DROP PRIMARY KEY;
+ ALTER TABLE roles
+ ADD CONSTRAINT roles_app_id_fkey
+ FOREIGN KEY (app_id)
+ REFERENCES apps (app_id) ON DELETE CASCADE;
-ALTER TABLE jwt_signing_keys
- ADD PRIMARY KEY (app_id, key_id);
+ CREATE INDEX IF NOT EXISTS roles_app_id_index ON roles (app_id);
-ALTER TABLE jwt_signing_keys
- ADD FOREIGN KEY (app_id)
- REFERENCES apps (app_id) ON DELETE CASCADE;
+ ------------------------------------------------------------
--- EmailVerification
+ ALTER TABLE role_permissions
+ ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public';
-ALTER TABLE emailverification_verified_emails
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+ ALTER TABLE role_permissions
+ DROP CONSTRAINT role_permissions_pkey CASCADE;
-ALTER TABLE emailverification_verified_emails
- DROP PRIMARY KEY;
+ ALTER TABLE role_permissions
+ ADD CONSTRAINT role_permissions_pkey
+ PRIMARY KEY (app_id, role, permission);
-ALTER TABLE emailverification_verified_emails
- ADD PRIMARY KEY (app_id, user_id, email);
+ ALTER TABLE role_permissions
+ DROP CONSTRAINT IF EXISTS role_permissions_role_fkey;
-ALTER TABLE emailverification_verified_emails
- ADD FOREIGN KEY (app_id)
- REFERENCES apps (app_id) ON DELETE CASCADE;
+ ALTER TABLE role_permissions
+ ADD CONSTRAINT role_permissions_role_fkey
+ FOREIGN KEY (app_id, role)
+ REFERENCES roles (app_id, role) ON DELETE CASCADE;
-------------------------------------------------------------
+ DROP INDEX IF EXISTS role_permissions_permission_index;
-ALTER TABLE emailverification_tokens
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public',
- ADD COLUMN tenant_id VARCHAR(64) DEFAULT 'public';
+ CREATE INDEX IF NOT EXISTS role_permissions_permission_index ON role_permissions (app_id, permission);
-ALTER TABLE emailverification_tokens
- DROP PRIMARY KEY;
+ CREATE INDEX IF NOT EXISTS role_permissions_role_index ON role_permissions (app_id, role);
-ALTER TABLE emailverification_tokens
- ADD PRIMARY KEY (app_id, tenant_id, user_id, email, token);
+ ------------------------------------------------------------
-ALTER TABLE emailverification_tokens
- ADD FOREIGN KEY (app_id, tenant_id)
- REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE;
+ ALTER TABLE user_roles
+ ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public',
+ ADD COLUMN IF NOT EXISTS tenant_id VARCHAR(64) DEFAULT 'public';
--- EmailPassword
+ ALTER TABLE user_roles
+ DROP CONSTRAINT user_roles_pkey CASCADE;
-ALTER TABLE emailpassword_users
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+ ALTER TABLE user_roles
+ ADD CONSTRAINT user_roles_pkey
+ PRIMARY KEY (app_id, tenant_id, user_id, role);
-ALTER TABLE emailpassword_users
- DROP PRIMARY KEY;
+ ALTER TABLE user_roles
+ DROP CONSTRAINT IF EXISTS user_roles_tenant_id_fkey;
-ALTER TABLE emailpassword_users
- DROP INDEX email;
+ ALTER TABLE user_roles
+ ADD CONSTRAINT user_roles_tenant_id_fkey
+ FOREIGN KEY (app_id, tenant_id)
+ REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE;
-ALTER TABLE emailpassword_users
- ADD PRIMARY KEY (app_id, user_id);
+ ALTER TABLE user_roles
+ DROP CONSTRAINT IF EXISTS user_roles_role_fkey;
-ALTER TABLE emailpassword_users
- ADD FOREIGN KEY (app_id, user_id)
- REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE;
+ ALTER TABLE user_roles
+ ADD CONSTRAINT user_roles_role_fkey
+ FOREIGN KEY (app_id, role)
+ REFERENCES roles (app_id, role) ON DELETE CASCADE;
--- ------------------------------------------------------------
+ DROP INDEX IF EXISTS user_roles_role_index;
-CREATE TABLE IF NOT EXISTS emailpassword_user_to_tenant (
- app_id VARCHAR(64) DEFAULT 'public',
- tenant_id VARCHAR(64) DEFAULT 'public',
- user_id CHAR(36) NOT NULL,
- email VARCHAR(256) NOT NULL,
- CONSTRAINT email
- UNIQUE (app_id, tenant_id, email),
- PRIMARY KEY (app_id, tenant_id, user_id),
- CONSTRAINT FOREIGN KEY (app_id, tenant_id, user_id)
- REFERENCES all_auth_recipe_users (app_id, tenant_id, user_id) ON DELETE CASCADE
-);
+ CREATE INDEX IF NOT EXISTS user_roles_role_index ON user_roles (app_id, tenant_id, role);
-INSERT INTO emailpassword_user_to_tenant (user_id, email)
- SELECT user_id, email FROM emailpassword_users;
+ CREATE INDEX IF NOT EXISTS user_roles_tenant_id_index ON user_roles (app_id, tenant_id);
-------------------------------------------------------------
+ CREATE INDEX IF NOT EXISTS user_roles_app_id_role_index ON user_roles (app_id, role);
-ALTER TABLE emailpassword_pswd_reset_tokens
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+ -- UserMetadata
-ALTER TABLE emailpassword_pswd_reset_tokens
- DROP PRIMARY KEY;
+ ALTER TABLE user_metadata
+ ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public';
-ALTER TABLE emailpassword_pswd_reset_tokens
- ADD PRIMARY KEY (app_id, user_id, token);
+ ALTER TABLE user_metadata
+ DROP CONSTRAINT user_metadata_pkey CASCADE;
-ALTER TABLE emailpassword_pswd_reset_tokens
- ADD FOREIGN KEY (app_id, user_id)
- REFERENCES emailpassword_users (app_id, user_id) ON DELETE CASCADE;
+ ALTER TABLE user_metadata
+ ADD CONSTRAINT user_metadata_pkey
+ PRIMARY KEY (app_id, user_id);
--- Passwordless
+ ALTER TABLE user_metadata
+ DROP CONSTRAINT IF EXISTS user_metadata_app_id_fkey;
-ALTER TABLE passwordless_users
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+ ALTER TABLE user_metadata
+ ADD CONSTRAINT user_metadata_app_id_fkey
+ FOREIGN KEY (app_id)
+ REFERENCES apps (app_id) ON DELETE CASCADE;
-ALTER TABLE passwordless_users
- DROP PRIMARY KEY;
+ CREATE INDEX IF NOT EXISTS user_metadata_app_id_index ON user_metadata (app_id);
-ALTER TABLE passwordless_users
- ADD PRIMARY KEY (app_id, user_id);
+ -- Dashboard
-ALTER TABLE passwordless_users
- DROP INDEX email;
+ ALTER TABLE dashboard_users
+ ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public';
-ALTER TABLE passwordless_users
- DROP INDEX phone_number;
+ ALTER TABLE dashboard_users
+ DROP CONSTRAINT dashboard_users_pkey CASCADE;
-ALTER TABLE passwordless_users
- ADD FOREIGN KEY (app_id, user_id)
- REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE;
+ ALTER TABLE dashboard_users
+ ADD CONSTRAINT dashboard_users_pkey
+ PRIMARY KEY (app_id, user_id);
-------------------------------------------------------------
+ ALTER TABLE dashboard_users
+ DROP CONSTRAINT IF EXISTS dashboard_users_email_key;
-CREATE TABLE IF NOT EXISTS passwordless_user_to_tenant (
- app_id VARCHAR(64) DEFAULT 'public',
- tenant_id VARCHAR(64) DEFAULT 'public',
- user_id CHAR(36) NOT NULL,
- email VARCHAR(256),
- phone_number VARCHAR(256),
- CONSTRAINT email
- UNIQUE (app_id, tenant_id, email),
- CONSTRAINT phone_number
- UNIQUE (app_id, tenant_id, phone_number),
- PRIMARY KEY (app_id, tenant_id, user_id),
- FOREIGN KEY (app_id, tenant_id, user_id)
- REFERENCES all_auth_recipe_users (app_id, tenant_id, user_id) ON DELETE CASCADE
-);
+ ALTER TABLE dashboard_users
+ ADD CONSTRAINT dashboard_users_email_key
+ UNIQUE (app_id, email);
-INSERT INTO passwordless_user_to_tenant (user_id, email, phone_number)
- SELECT user_id, email, phone_number FROM passwordless_users;
+ ALTER TABLE dashboard_users
+ DROP CONSTRAINT IF EXISTS dashboard_users_app_id_fkey;
-------------------------------------------------------------
+ ALTER TABLE dashboard_users
+ ADD CONSTRAINT dashboard_users_app_id_fkey
+ FOREIGN KEY (app_id)
+ REFERENCES apps (app_id) ON DELETE CASCADE;
-ALTER TABLE passwordless_devices
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public',
- ADD COLUMN tenant_id VARCHAR(64) DEFAULT 'public';
+ CREATE INDEX IF NOT EXISTS dashboard_users_app_id_index ON dashboard_users (app_id);
-ALTER TABLE passwordless_devices
- DROP PRIMARY KEY;
+ ------------------------------------------------------------
-ALTER TABLE passwordless_devices
- ADD PRIMARY KEY (app_id, tenant_id, device_id_hash);
+ ALTER TABLE dashboard_user_sessions
+ ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public';
-ALTER TABLE passwordless_devices
- ADD FOREIGN KEY (app_id, tenant_id)
- REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE;
+ ALTER TABLE dashboard_user_sessions
+ DROP CONSTRAINT dashboard_user_sessions_pkey CASCADE;
-ALTER TABLE passwordless_devices
- DROP INDEX passwordless_devices_email_index;
+ ALTER TABLE dashboard_user_sessions
+ ADD CONSTRAINT dashboard_user_sessions_pkey
+ PRIMARY KEY (app_id, session_id);
-CREATE INDEX passwordless_devices_email_index ON passwordless_devices (app_id, tenant_id, email);
+ ALTER TABLE dashboard_user_sessions
+ DROP CONSTRAINT IF EXISTS dashboard_user_sessions_user_id_fkey;
-ALTER TABLE passwordless_devices
- DROP INDEX passwordless_devices_phone_number_index;
+ ALTER TABLE dashboard_user_sessions
+ ADD CONSTRAINT dashboard_user_sessions_user_id_fkey
+ FOREIGN KEY (app_id, user_id)
+ REFERENCES dashboard_users (app_id, user_id) ON DELETE CASCADE;
-CREATE INDEX passwordless_devices_phone_number_index ON passwordless_devices (app_id, tenant_id, phone_number);
+ CREATE INDEX IF NOT EXISTS dashboard_user_sessions_user_id_index ON dashboard_user_sessions (app_id, user_id);
-------------------------------------------------------------
+ -- TOTP
-ALTER TABLE passwordless_codes
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public',
- ADD COLUMN tenant_id VARCHAR(64) DEFAULT 'public';
+ ALTER TABLE totp_users
+ ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public';
-ALTER TABLE passwordless_codes
- DROP PRIMARY KEY;
+ ALTER TABLE totp_users
+ DROP CONSTRAINT totp_users_pkey CASCADE;
-ALTER TABLE passwordless_codes
- ADD PRIMARY KEY (app_id, tenant_id, code_id);
+ ALTER TABLE totp_users
+ ADD CONSTRAINT totp_users_pkey
+ PRIMARY KEY (app_id, user_id);
-ALTER TABLE passwordless_codes
- DROP INDEX device_id_hash;
+ ALTER TABLE totp_users
+ DROP CONSTRAINT IF EXISTS totp_users_app_id_fkey;
-ALTER TABLE passwordless_codes
- ADD FOREIGN KEY (app_id, tenant_id, device_id_hash)
- REFERENCES passwordless_devices (app_id, tenant_id, device_id_hash) ON DELETE CASCADE;
+ ALTER TABLE totp_users
+ ADD CONSTRAINT totp_users_app_id_fkey
+ FOREIGN KEY (app_id)
+ REFERENCES apps (app_id) ON DELETE CASCADE;
-ALTER TABLE passwordless_codes
- DROP INDEX link_code_hash;
+ CREATE INDEX IF NOT EXISTS totp_users_app_id_index ON totp_users (app_id);
-ALTER TABLE passwordless_codes
- ADD CONSTRAINT link_code_hash
- UNIQUE (app_id, tenant_id, link_code_hash);
+ ------------------------------------------------------------
-ALTER TABLE passwordless_codes
- DROP INDEX passwordless_codes_created_at_index;
+ ALTER TABLE totp_user_devices
+ ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public';
-CREATE INDEX passwordless_codes_created_at_index ON passwordless_codes (app_id, tenant_id, created_at);
+ ALTER TABLE totp_user_devices
+ DROP CONSTRAINT totp_user_devices_pkey;
--- ThirdParty
+ ALTER TABLE totp_user_devices
+ ADD CONSTRAINT totp_user_devices_pkey
+ PRIMARY KEY (app_id, user_id, device_name);
-ALTER TABLE thirdparty_users
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+ ALTER TABLE totp_user_devices
+ DROP CONSTRAINT IF EXISTS totp_user_devices_user_id_fkey;
-ALTER TABLE thirdparty_users
- DROP PRIMARY KEY;
+ ALTER TABLE totp_user_devices
+ ADD CONSTRAINT totp_user_devices_user_id_fkey
+ FOREIGN KEY (app_id, user_id)
+ REFERENCES totp_users (app_id, user_id) ON DELETE CASCADE;
-ALTER TABLE thirdparty_users
- DROP INDEX user_id;
+ CREATE INDEX IF NOT EXISTS totp_user_devices_user_id_index ON totp_user_devices (app_id, user_id);
-ALTER TABLE thirdparty_users
- ADD PRIMARY KEY (app_id, user_id);
+ ------------------------------------------------------------
-ALTER TABLE thirdparty_users
- ADD FOREIGN KEY (app_id, user_id)
- REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE;
+ ALTER TABLE totp_used_codes
+ ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public',
+ ADD COLUMN IF NOT EXISTS tenant_id VARCHAR(64) DEFAULT 'public';
--- ALTER TABLE thirdparty_users
--- DROP INDEX thirdparty_users_thirdparty_user_id_index;
+ ALTER TABLE totp_used_codes
+ DROP CONSTRAINT totp_used_codes_pkey CASCADE;
-CREATE INDEX thirdparty_users_thirdparty_user_id_index ON thirdparty_users (app_id, third_party_id, third_party_user_id);
+ ALTER TABLE totp_used_codes
+ ADD CONSTRAINT totp_used_codes_pkey
+ PRIMARY KEY (app_id, tenant_id, user_id, created_time_ms);
--- ALTER TABLE thirdparty_users
--- DROP INDEX thirdparty_users_email_index;
+ ALTER TABLE totp_used_codes
+ DROP CONSTRAINT IF EXISTS totp_used_codes_user_id_fkey;
-CREATE INDEX thirdparty_users_email_index ON thirdparty_users (app_id, email);
+ ALTER TABLE totp_used_codes
+ ADD CONSTRAINT totp_used_codes_user_id_fkey
+ FOREIGN KEY (app_id, user_id)
+ REFERENCES totp_users (app_id, user_id) ON DELETE CASCADE;
-------------------------------------------------------------
+ ALTER TABLE totp_used_codes
+ DROP CONSTRAINT IF EXISTS totp_used_codes_tenant_id_fkey;
-CREATE TABLE IF NOT EXISTS thirdparty_user_to_tenant (
- app_id VARCHAR(64) DEFAULT 'public',
- tenant_id VARCHAR(64) DEFAULT 'public',
- user_id CHAR(36) NOT NULL,
- third_party_id VARCHAR(28) NOT NULL,
- third_party_user_id VARCHAR(256) NOT NULL,
- CONSTRAINT third_party_user_id
- UNIQUE (app_id, tenant_id, third_party_id, third_party_user_id),
- PRIMARY KEY (app_id, tenant_id, user_id),
- FOREIGN KEY (app_id, tenant_id, user_id)
- REFERENCES all_auth_recipe_users (app_id, tenant_id, user_id) ON DELETE CASCADE
-);
+ ALTER TABLE totp_used_codes
+ ADD CONSTRAINT totp_used_codes_tenant_id_fkey
+ FOREIGN KEY (app_id, tenant_id)
+ REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE;
-INSERT INTO thirdparty_user_to_tenant (user_id, third_party_id, third_party_user_id)
- SELECT user_id, third_party_id, third_party_user_id FROM thirdparty_users;
+ DROP INDEX IF EXISTS totp_used_codes_expiry_time_ms_index;
--- UserIdMapping
+ CREATE INDEX IF NOT EXISTS totp_used_codes_expiry_time_ms_index ON totp_used_codes (app_id, tenant_id, expiry_time_ms);
-ALTER TABLE userid_mapping
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+ CREATE INDEX IF NOT EXISTS totp_used_codes_user_id_index ON totp_used_codes (app_id, user_id);
-ALTER TABLE userid_mapping
- DROP PRIMARY KEY;
+ CREATE INDEX IF NOT EXISTS totp_used_codes_tenant_id_index ON totp_used_codes (app_id, tenant_id);
-ALTER TABLE userid_mapping
- ADD PRIMARY KEY (app_id, supertokens_user_id, external_user_id);
+ -- ActiveUsers
-ALTER TABLE userid_mapping
- DROP INDEX supertokens_user_id;
+ ALTER TABLE user_last_active
+ ADD COLUMN IF NOT EXISTS app_id VARCHAR(64) DEFAULT 'public';
-ALTER TABLE userid_mapping
- ADD CONSTRAINT supertokens_user_id
- UNIQUE (app_id, supertokens_user_id);
+ ALTER TABLE user_last_active
+ DROP CONSTRAINT user_last_active_pkey CASCADE;
-ALTER TABLE userid_mapping
- DROP INDEX external_user_id;
+ ALTER TABLE user_last_active
+ ADD CONSTRAINT user_last_active_pkey
+ PRIMARY KEY (app_id, user_id);
-ALTER TABLE userid_mapping
- ADD CONSTRAINT external_user_id
- UNIQUE (app_id, external_user_id);
+ ALTER TABLE user_last_active
+ DROP CONSTRAINT IF EXISTS user_last_active_app_id_fkey;
-ALTER TABLE userid_mapping
- ADD FOREIGN KEY (app_id, supertokens_user_id)
- REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE;
+ ALTER TABLE user_last_active
+ ADD CONSTRAINT user_last_active_app_id_fkey
+ FOREIGN KEY (app_id)
+ REFERENCES apps (app_id) ON DELETE CASCADE;
--- UserRoles
+ CREATE INDEX IF NOT EXISTS user_last_active_app_id_index ON user_last_active (app_id);
-ALTER TABLE roles
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
-
-ALTER TABLE roles
- DROP PRIMARY KEY;
-
-ALTER TABLE roles
- ADD PRIMARY KEY (app_id, role);
-
-ALTER TABLE roles
- ADD FOREIGN KEY (app_id)
- REFERENCES apps (app_id) ON DELETE CASCADE;
-
-------------------------------------------------------------
-
-ALTER TABLE role_permissions
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
-
-ALTER TABLE role_permissions
- DROP PRIMARY KEY;
-
-ALTER TABLE role_permissions
- ADD PRIMARY KEY (app_id, role, permission);
-
-ALTER TABLE role_permissions
- ADD FOREIGN KEY (app_id, role)
- REFERENCES roles (app_id, role) ON DELETE CASCADE;
-
-ALTER TABLE role_permissions
- DROP INDEX role_permissions_permission_index;
-
-CREATE INDEX role_permissions_permission_index ON role_permissions (app_id, permission);
-
-------------------------------------------------------------
-
-ALTER TABLE user_roles
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public',
- ADD COLUMN tenant_id VARCHAR(64) DEFAULT 'public';
-
-ALTER TABLE user_roles
- DROP PRIMARY KEY;
-
-ALTER TABLE user_roles
- ADD PRIMARY KEY (app_id, tenant_id, user_id, role);
-
-ALTER TABLE user_roles
- ADD FOREIGN KEY (app_id, role)
- REFERENCES roles (app_id, role) ON DELETE CASCADE;
-
-ALTER TABLE user_roles
- ADD FOREIGN KEY (app_id, tenant_id)
- REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE;
-
-ALTER TABLE user_roles
- DROP INDEX user_roles_role_index;
-
-CREATE INDEX user_roles_role_index ON user_roles (app_id, tenant_id, role);
-
--- UserMetadata
-
-ALTER TABLE user_metadata
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
-
-ALTER TABLE user_metadata
- DROP PRIMARY KEY;
-
-ALTER TABLE user_metadata
- ADD PRIMARY KEY (app_id, user_id);
-
-ALTER TABLE user_metadata
- ADD FOREIGN KEY (app_id)
- REFERENCES apps (app_id) ON DELETE CASCADE;
-
--- Dashboard
-
-ALTER TABLE dashboard_users
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
-
-ALTER TABLE dashboard_users
- DROP PRIMARY KEY;
-
-ALTER TABLE dashboard_users
- ADD PRIMARY KEY (app_id, user_id);
-
-ALTER TABLE dashboard_users
- DROP INDEX email;
-
-ALTER TABLE dashboard_users
- ADD CONSTRAINT email
- UNIQUE (app_id, email);
-
-ALTER TABLE dashboard_users
- ADD FOREIGN KEY (app_id)
- REFERENCES apps (app_id) ON DELETE CASCADE;
-
-------------------------------------------------------------
-
-ALTER TABLE dashboard_user_sessions
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
-
-ALTER TABLE dashboard_user_sessions
- DROP PRIMARY KEY;
-
-ALTER TABLE dashboard_user_sessions
- ADD PRIMARY KEY (app_id, session_id);
-
-ALTER TABLE dashboard_user_sessions
- DROP INDEX user_id;
-
-ALTER TABLE dashboard_user_sessions
- ADD FOREIGN KEY (app_id, user_id)
- REFERENCES dashboard_users (app_id, user_id) ON DELETE CASCADE;
-
--- TOTP
-
-ALTER TABLE totp_users
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
-
-ALTER TABLE totp_users
- DROP PRIMARY KEY;
-
-ALTER TABLE totp_users
- ADD PRIMARY KEY (app_id, user_id);
-
-ALTER TABLE totp_users
- ADD FOREIGN KEY (app_id)
- REFERENCES apps (app_id) ON DELETE CASCADE;
-
-------------------------------------------------------------
-
-ALTER TABLE totp_user_devices
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
-
-ALTER TABLE totp_user_devices
- DROP PRIMARY KEY;
-
-ALTER TABLE totp_user_devices
- ADD PRIMARY KEY (app_id, user_id, device_name);
-
-ALTER TABLE totp_user_devices
- ADD FOREIGN KEY (app_id, user_id)
- REFERENCES totp_users (app_id, user_id) ON DELETE CASCADE;
-
-------------------------------------------------------------
-
-ALTER TABLE totp_used_codes
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public',
- ADD COLUMN tenant_id VARCHAR(64) DEFAULT 'public';
-
-ALTER TABLE totp_used_codes
- DROP PRIMARY KEY;
-
-ALTER TABLE totp_used_codes
- ADD PRIMARY KEY (app_id, tenant_id, user_id, created_time_ms);
-
-ALTER TABLE totp_used_codes
- ADD FOREIGN KEY (app_id, user_id)
- REFERENCES totp_users (app_id, user_id) ON DELETE CASCADE;
-
-ALTER TABLE totp_used_codes
- ADD FOREIGN KEY (app_id, tenant_id)
- REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE;
-
-ALTER TABLE totp_used_codes
- DROP INDEX totp_used_codes_expiry_time_ms_index;
-
-CREATE INDEX totp_used_codes_expiry_time_ms_index ON totp_used_codes (app_id, tenant_id, expiry_time_ms);
-
--- ActiveUsers
-
-ALTER TABLE user_last_active
- ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
-
-ALTER TABLE user_last_active
- DROP PRIMARY KEY;
-
-ALTER TABLE user_last_active
- ADD PRIMARY KEY (app_id, user_id);
-
-ALTER TABLE user_last_active
- ADD FOREIGN KEY (app_id)
- REFERENCES apps (app_id) ON DELETE CASCADE;
-```
+ ```
+
+
+
+
+
+ If using MySQL
+
+ #### Run the following SQL script
+
+ ```sql
+ -- Drop Foreign keys
+
+ ALTER TABLE emailpassword_pswd_reset_tokens
+ DROP FOREIGN KEY emailpassword_pswd_reset_tokens_ibfk_1;
+
+ ALTER TABLE passwordless_codes
+ DROP FOREIGN KEY passwordless_codes_ibfk_1;
+
+ ALTER TABLE userid_mapping
+ DROP FOREIGN KEY userid_mapping_ibfk_1;
+
+ ALTER TABLE role_permissions
+ DROP FOREIGN KEY role_permissions_ibfk_1;
+
+ ALTER TABLE user_roles
+ DROP FOREIGN KEY user_roles_ibfk_1;
+
+ ALTER TABLE dashboard_user_sessions
+ DROP FOREIGN KEY dashboard_user_sessions_ibfk_1;
+
+ ALTER TABLE totp_user_devices
+ DROP FOREIGN KEY totp_user_devices_ibfk_1;
+
+ ALTER TABLE totp_used_codes
+ DROP FOREIGN KEY totp_used_codes_ibfk_1;
+
+ -- General Tables
+
+ CREATE TABLE IF NOT EXISTS apps (
+ app_id VARCHAR(64) NOT NULL DEFAULT 'public',
+ created_at_time BIGINT UNSIGNED,
+ PRIMARY KEY(app_id)
+ );
+
+ INSERT INTO apps (app_id, created_at_time)
+ VALUES ('public', 0);
+
+ ------------------------------------------------------------
+
+ CREATE TABLE IF NOT EXISTS tenants (
+ app_id VARCHAR(64) NOT NULL DEFAULT 'public',
+ tenant_id VARCHAR(64) NOT NULL DEFAULT 'public',
+ created_at_time BIGINT UNSIGNED,
+ PRIMARY KEY (app_id, tenant_id),
+ FOREIGN KEY(app_id)
+ REFERENCES apps (app_id) ON DELETE CASCADE
+ );
+
+ INSERT INTO tenants (app_id, tenant_id, created_at_time)
+ VALUES ('public', 'public', 0);
+
+ ------------------------------------------------------------
+
+ ALTER TABLE key_value
+ ADD COLUMN app_id VARCHAR(64) DEFAULT 'public',
+ ADD COLUMN tenant_id VARCHAR(64) DEFAULT 'public';
+
+ ALTER TABLE key_value
+ DROP PRIMARY KEY;
+
+ ALTER TABLE key_value
+ ADD PRIMARY KEY (app_id, tenant_id, name);
+
+ ALTER TABLE key_value
+ ADD FOREIGN KEY (app_id, tenant_id)
+ REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE;
+
+ -- CREATE INDEX key_value_tenant_id_index ON key_value (app_id, tenant_id);
+
+ ------------------------------------------------------------
+
+ CREATE TABLE IF NOT EXISTS app_id_to_user_id (
+ app_id VARCHAR(64) NOT NULL DEFAULT 'public',
+ user_id CHAR(36) NOT NULL,
+ recipe_id VARCHAR(128) NOT NULL,
+ PRIMARY KEY (app_id, user_id),
+ FOREIGN KEY(app_id) REFERENCES apps (app_id) ON DELETE CASCADE
+ );
+
+ INSERT INTO app_id_to_user_id (user_id, recipe_id)
+ SELECT user_id, recipe_id
+ FROM all_auth_recipe_users;
+
+ ------------------------------------------------------------
+
+ ALTER TABLE all_auth_recipe_users
+ ADD COLUMN app_id VARCHAR(64) DEFAULT 'public',
+ ADD COLUMN tenant_id VARCHAR(64) DEFAULT 'public';
+
+ ALTER TABLE all_auth_recipe_users
+ DROP PRIMARY KEY;
+
+ ALTER TABLE all_auth_recipe_users
+ ADD PRIMARY KEY (app_id, tenant_id, user_id);
+
+ ALTER TABLE all_auth_recipe_users
+ ADD FOREIGN KEY (app_id, tenant_id)
+ REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE;
+
+ ALTER TABLE all_auth_recipe_users
+ ADD FOREIGN KEY (app_id, user_id)
+ REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE;
+
+ ALTER TABLE all_auth_recipe_users
+ DROP INDEX all_auth_recipe_users_pagination_index;
+
+ CREATE INDEX all_auth_recipe_users_pagination_index ON all_auth_recipe_users (time_joined DESC, user_id DESC, tenant_id DESC, app_id DESC);
+
+ -- Multitenancy
+
+ CREATE TABLE IF NOT EXISTS tenant_configs (
+ connection_uri_domain VARCHAR(256) DEFAULT '',
+ app_id VARCHAR(64) DEFAULT 'public',
+ tenant_id VARCHAR(64) DEFAULT 'public',
+ core_config TEXT,
+ email_password_enabled BOOLEAN,
+ passwordless_enabled BOOLEAN,
+ third_party_enabled BOOLEAN,
+ PRIMARY KEY (connection_uri_domain, app_id, tenant_id)
+ );
+
+ ------------------------------------------------------------
+
+ CREATE TABLE IF NOT EXISTS tenant_thirdparty_providers (
+ connection_uri_domain VARCHAR(256) DEFAULT '',
+ app_id VARCHAR(64) DEFAULT 'public',
+ tenant_id VARCHAR(64) DEFAULT 'public',
+ third_party_id VARCHAR(28) NOT NULL,
+ name VARCHAR(64),
+ authorization_endpoint TEXT,
+ authorization_endpoint_query_params TEXT,
+ token_endpoint TEXT,
+ token_endpoint_body_params TEXT,
+ user_info_endpoint TEXT,
+ user_info_endpoint_query_params TEXT,
+ user_info_endpoint_headers TEXT,
+ jwks_uri TEXT,
+ oidc_discovery_endpoint TEXT,
+ require_email BOOLEAN,
+ user_info_map_from_id_token_payload_user_id VARCHAR(64),
+ user_info_map_from_id_token_payload_email VARCHAR(64),
+ user_info_map_from_id_token_payload_email_verified VARCHAR(64),
+ user_info_map_from_user_info_endpoint_user_id VARCHAR(64),
+ user_info_map_from_user_info_endpoint_email VARCHAR(64),
+ user_info_map_from_user_info_endpoint_email_verified VARCHAR(64),
+ PRIMARY KEY (connection_uri_domain, app_id, tenant_id, third_party_id),
+ FOREIGN KEY(connection_uri_domain, app_id, tenant_id)
+ REFERENCES tenant_configs (connection_uri_domain, app_id, tenant_id) ON DELETE CASCADE
+ );
+
+ ------------------------------------------------------------
+
+ CREATE TABLE IF NOT EXISTS tenant_thirdparty_provider_clients (
+ connection_uri_domain VARCHAR(256) DEFAULT '',
+ app_id VARCHAR(64) DEFAULT 'public',
+ tenant_id VARCHAR(64) DEFAULT 'public',
+ third_party_id VARCHAR(28) NOT NULL,
+ client_type VARCHAR(64) NOT NULL DEFAULT '',
+ client_id VARCHAR(256) NOT NULL,
+ client_secret TEXT,
+ scope TEXT,
+ force_pkce BOOLEAN,
+ additional_config TEXT,
+ PRIMARY KEY (connection_uri_domain, app_id, tenant_id, third_party_id, client_type),
+ FOREIGN KEY (connection_uri_domain, app_id, tenant_id, third_party_id)
+ REFERENCES tenant_thirdparty_providers (connection_uri_domain, app_id, tenant_id, third_party_id) ON DELETE CASCADE
+ );
+
+
+ -- Session
+
+ ALTER TABLE session_info
+ ADD COLUMN app_id VARCHAR(64) DEFAULT 'public',
+ ADD COLUMN tenant_id VARCHAR(64) DEFAULT 'public';
+
+ ALTER TABLE session_info
+ DROP PRIMARY KEY;
+
+ ALTER TABLE session_info
+ ADD PRIMARY KEY (app_id, tenant_id, session_handle);
+
+ ALTER TABLE session_info
+ ADD FOREIGN KEY (app_id, tenant_id)
+ REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE;
+
+ CREATE INDEX session_expiry_index ON session_info (expires_at);
+
+ ------------------------------------------------------------
+
+ ALTER TABLE session_access_token_signing_keys
+ ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+
+ ALTER TABLE session_access_token_signing_keys
+ DROP PRIMARY KEY;
+
+ ALTER TABLE session_access_token_signing_keys
+ ADD PRIMARY KEY (app_id, created_at_time);
+
+ ALTER TABLE session_access_token_signing_keys
+ ADD FOREIGN KEY (app_id)
+ REFERENCES apps (app_id) ON DELETE CASCADE;
+
+ -- JWT
+
+ ALTER TABLE jwt_signing_keys
+ ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+
+ ALTER TABLE jwt_signing_keys
+ DROP PRIMARY KEY;
+
+ ALTER TABLE jwt_signing_keys
+ ADD PRIMARY KEY (app_id, key_id);
+
+ ALTER TABLE jwt_signing_keys
+ ADD FOREIGN KEY (app_id)
+ REFERENCES apps (app_id) ON DELETE CASCADE;
+
+ -- EmailVerification
+
+ ALTER TABLE emailverification_verified_emails
+ ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+
+ ALTER TABLE emailverification_verified_emails
+ DROP PRIMARY KEY;
+
+ ALTER TABLE emailverification_verified_emails
+ ADD PRIMARY KEY (app_id, user_id, email);
+
+ ALTER TABLE emailverification_verified_emails
+ ADD FOREIGN KEY (app_id)
+ REFERENCES apps (app_id) ON DELETE CASCADE;
+
+ ------------------------------------------------------------
+
+ ALTER TABLE emailverification_tokens
+ ADD COLUMN app_id VARCHAR(64) DEFAULT 'public',
+ ADD COLUMN tenant_id VARCHAR(64) DEFAULT 'public';
+
+ ALTER TABLE emailverification_tokens
+ DROP PRIMARY KEY;
+
+ ALTER TABLE emailverification_tokens
+ ADD PRIMARY KEY (app_id, tenant_id, user_id, email, token);
+
+ ALTER TABLE emailverification_tokens
+ ADD FOREIGN KEY (app_id, tenant_id)
+ REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE;
+
+ -- EmailPassword
+
+ ALTER TABLE emailpassword_users
+ ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+
+ ALTER TABLE emailpassword_users
+ DROP PRIMARY KEY;
+
+ ALTER TABLE emailpassword_users
+ DROP INDEX email;
+
+ ALTER TABLE emailpassword_users
+ ADD PRIMARY KEY (app_id, user_id);
+
+ ALTER TABLE emailpassword_users
+ ADD FOREIGN KEY (app_id, user_id)
+ REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE;
+
+ -- ------------------------------------------------------------
+
+ CREATE TABLE IF NOT EXISTS emailpassword_user_to_tenant (
+ app_id VARCHAR(64) DEFAULT 'public',
+ tenant_id VARCHAR(64) DEFAULT 'public',
+ user_id CHAR(36) NOT NULL,
+ email VARCHAR(256) NOT NULL,
+ CONSTRAINT email
+ UNIQUE (app_id, tenant_id, email),
+ PRIMARY KEY (app_id, tenant_id, user_id),
+ CONSTRAINT FOREIGN KEY (app_id, tenant_id, user_id)
+ REFERENCES all_auth_recipe_users (app_id, tenant_id, user_id) ON DELETE CASCADE
+ );
+
+ INSERT INTO emailpassword_user_to_tenant (user_id, email)
+ SELECT user_id, email FROM emailpassword_users;
+
+ ------------------------------------------------------------
+
+ ALTER TABLE emailpassword_pswd_reset_tokens
+ ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+
+ ALTER TABLE emailpassword_pswd_reset_tokens
+ DROP PRIMARY KEY;
+
+ ALTER TABLE emailpassword_pswd_reset_tokens
+ ADD PRIMARY KEY (app_id, user_id, token);
+
+ ALTER TABLE emailpassword_pswd_reset_tokens
+ ADD FOREIGN KEY (app_id, user_id)
+ REFERENCES emailpassword_users (app_id, user_id) ON DELETE CASCADE;
+
+ -- Passwordless
+
+ ALTER TABLE passwordless_users
+ ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+
+ ALTER TABLE passwordless_users
+ DROP PRIMARY KEY;
+
+ ALTER TABLE passwordless_users
+ ADD PRIMARY KEY (app_id, user_id);
+
+ ALTER TABLE passwordless_users
+ DROP INDEX email;
+
+ ALTER TABLE passwordless_users
+ DROP INDEX phone_number;
+
+ ALTER TABLE passwordless_users
+ ADD FOREIGN KEY (app_id, user_id)
+ REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE;
+
+ ------------------------------------------------------------
+
+ CREATE TABLE IF NOT EXISTS passwordless_user_to_tenant (
+ app_id VARCHAR(64) DEFAULT 'public',
+ tenant_id VARCHAR(64) DEFAULT 'public',
+ user_id CHAR(36) NOT NULL,
+ email VARCHAR(256),
+ phone_number VARCHAR(256),
+ CONSTRAINT email
+ UNIQUE (app_id, tenant_id, email),
+ CONSTRAINT phone_number
+ UNIQUE (app_id, tenant_id, phone_number),
+ PRIMARY KEY (app_id, tenant_id, user_id),
+ FOREIGN KEY (app_id, tenant_id, user_id)
+ REFERENCES all_auth_recipe_users (app_id, tenant_id, user_id) ON DELETE CASCADE
+ );
+
+ INSERT INTO passwordless_user_to_tenant (user_id, email, phone_number)
+ SELECT user_id, email, phone_number FROM passwordless_users;
+
+ ------------------------------------------------------------
+
+ ALTER TABLE passwordless_devices
+ ADD COLUMN app_id VARCHAR(64) DEFAULT 'public',
+ ADD COLUMN tenant_id VARCHAR(64) DEFAULT 'public';
+
+ ALTER TABLE passwordless_devices
+ DROP PRIMARY KEY;
+
+ ALTER TABLE passwordless_devices
+ ADD PRIMARY KEY (app_id, tenant_id, device_id_hash);
+
+ ALTER TABLE passwordless_devices
+ ADD FOREIGN KEY (app_id, tenant_id)
+ REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE;
+
+ ALTER TABLE passwordless_devices
+ DROP INDEX passwordless_devices_email_index;
+
+ CREATE INDEX passwordless_devices_email_index ON passwordless_devices (app_id, tenant_id, email);
+
+ ALTER TABLE passwordless_devices
+ DROP INDEX passwordless_devices_phone_number_index;
+
+ CREATE INDEX passwordless_devices_phone_number_index ON passwordless_devices (app_id, tenant_id, phone_number);
+
+ ------------------------------------------------------------
+
+ ALTER TABLE passwordless_codes
+ ADD COLUMN app_id VARCHAR(64) DEFAULT 'public',
+ ADD COLUMN tenant_id VARCHAR(64) DEFAULT 'public';
+
+ ALTER TABLE passwordless_codes
+ DROP PRIMARY KEY;
+
+ ALTER TABLE passwordless_codes
+ ADD PRIMARY KEY (app_id, tenant_id, code_id);
+
+ ALTER TABLE passwordless_codes
+ DROP INDEX device_id_hash;
+
+ ALTER TABLE passwordless_codes
+ ADD FOREIGN KEY (app_id, tenant_id, device_id_hash)
+ REFERENCES passwordless_devices (app_id, tenant_id, device_id_hash) ON DELETE CASCADE;
+
+ ALTER TABLE passwordless_codes
+ DROP INDEX link_code_hash;
+
+ ALTER TABLE passwordless_codes
+ ADD CONSTRAINT link_code_hash
+ UNIQUE (app_id, tenant_id, link_code_hash);
+
+ ALTER TABLE passwordless_codes
+ DROP INDEX passwordless_codes_created_at_index;
+
+ CREATE INDEX passwordless_codes_created_at_index ON passwordless_codes (app_id, tenant_id, created_at);
+
+ -- ThirdParty
+
+ ALTER TABLE thirdparty_users
+ ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+
+ ALTER TABLE thirdparty_users
+ DROP PRIMARY KEY;
+
+ ALTER TABLE thirdparty_users
+ DROP INDEX user_id;
+
+ ALTER TABLE thirdparty_users
+ ADD PRIMARY KEY (app_id, user_id);
+
+ ALTER TABLE thirdparty_users
+ ADD FOREIGN KEY (app_id, user_id)
+ REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE;
+
+ -- ALTER TABLE thirdparty_users
+ -- DROP INDEX thirdparty_users_thirdparty_user_id_index;
+
+ CREATE INDEX thirdparty_users_thirdparty_user_id_index ON thirdparty_users (app_id, third_party_id, third_party_user_id);
+
+ -- ALTER TABLE thirdparty_users
+ -- DROP INDEX thirdparty_users_email_index;
+
+ CREATE INDEX thirdparty_users_email_index ON thirdparty_users (app_id, email);
+
+ ------------------------------------------------------------
+
+ CREATE TABLE IF NOT EXISTS thirdparty_user_to_tenant (
+ app_id VARCHAR(64) DEFAULT 'public',
+ tenant_id VARCHAR(64) DEFAULT 'public',
+ user_id CHAR(36) NOT NULL,
+ third_party_id VARCHAR(28) NOT NULL,
+ third_party_user_id VARCHAR(256) NOT NULL,
+ CONSTRAINT third_party_user_id
+ UNIQUE (app_id, tenant_id, third_party_id, third_party_user_id),
+ PRIMARY KEY (app_id, tenant_id, user_id),
+ FOREIGN KEY (app_id, tenant_id, user_id)
+ REFERENCES all_auth_recipe_users (app_id, tenant_id, user_id) ON DELETE CASCADE
+ );
+
+ INSERT INTO thirdparty_user_to_tenant (user_id, third_party_id, third_party_user_id)
+ SELECT user_id, third_party_id, third_party_user_id FROM thirdparty_users;
+
+ -- UserIdMapping
+
+ ALTER TABLE userid_mapping
+ ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+
+ ALTER TABLE userid_mapping
+ DROP PRIMARY KEY;
+
+ ALTER TABLE userid_mapping
+ ADD PRIMARY KEY (app_id, supertokens_user_id, external_user_id);
+
+ ALTER TABLE userid_mapping
+ DROP INDEX supertokens_user_id;
+
+ ALTER TABLE userid_mapping
+ ADD CONSTRAINT supertokens_user_id
+ UNIQUE (app_id, supertokens_user_id);
+
+ ALTER TABLE userid_mapping
+ DROP INDEX external_user_id;
+
+ ALTER TABLE userid_mapping
+ ADD CONSTRAINT external_user_id
+ UNIQUE (app_id, external_user_id);
+
+ ALTER TABLE userid_mapping
+ ADD FOREIGN KEY (app_id, supertokens_user_id)
+ REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE;
+
+ -- UserRoles
+
+ ALTER TABLE roles
+ ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+
+ ALTER TABLE roles
+ DROP PRIMARY KEY;
+
+ ALTER TABLE roles
+ ADD PRIMARY KEY (app_id, role);
+
+ ALTER TABLE roles
+ ADD FOREIGN KEY (app_id)
+ REFERENCES apps (app_id) ON DELETE CASCADE;
+
+ ------------------------------------------------------------
+
+ ALTER TABLE role_permissions
+ ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+
+ ALTER TABLE role_permissions
+ DROP PRIMARY KEY;
+
+ ALTER TABLE role_permissions
+ ADD PRIMARY KEY (app_id, role, permission);
+
+ ALTER TABLE role_permissions
+ ADD FOREIGN KEY (app_id, role)
+ REFERENCES roles (app_id, role) ON DELETE CASCADE;
+
+ ALTER TABLE role_permissions
+ DROP INDEX role_permissions_permission_index;
+
+ CREATE INDEX role_permissions_permission_index ON role_permissions (app_id, permission);
+
+ ------------------------------------------------------------
+
+ ALTER TABLE user_roles
+ ADD COLUMN app_id VARCHAR(64) DEFAULT 'public',
+ ADD COLUMN tenant_id VARCHAR(64) DEFAULT 'public';
+
+ ALTER TABLE user_roles
+ DROP PRIMARY KEY;
+
+ ALTER TABLE user_roles
+ ADD PRIMARY KEY (app_id, tenant_id, user_id, role);
+
+ ALTER TABLE user_roles
+ ADD FOREIGN KEY (app_id, role)
+ REFERENCES roles (app_id, role) ON DELETE CASCADE;
+
+ ALTER TABLE user_roles
+ ADD FOREIGN KEY (app_id, tenant_id)
+ REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE;
+
+ ALTER TABLE user_roles
+ DROP INDEX user_roles_role_index;
+
+ CREATE INDEX user_roles_role_index ON user_roles (app_id, tenant_id, role);
+
+ -- UserMetadata
+
+ ALTER TABLE user_metadata
+ ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+
+ ALTER TABLE user_metadata
+ DROP PRIMARY KEY;
+
+ ALTER TABLE user_metadata
+ ADD PRIMARY KEY (app_id, user_id);
+
+ ALTER TABLE user_metadata
+ ADD FOREIGN KEY (app_id)
+ REFERENCES apps (app_id) ON DELETE CASCADE;
+
+ -- Dashboard
+
+ ALTER TABLE dashboard_users
+ ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+
+ ALTER TABLE dashboard_users
+ DROP PRIMARY KEY;
+
+ ALTER TABLE dashboard_users
+ ADD PRIMARY KEY (app_id, user_id);
+
+ ALTER TABLE dashboard_users
+ DROP INDEX email;
+
+ ALTER TABLE dashboard_users
+ ADD CONSTRAINT email
+ UNIQUE (app_id, email);
+
+ ALTER TABLE dashboard_users
+ ADD FOREIGN KEY (app_id)
+ REFERENCES apps (app_id) ON DELETE CASCADE;
+
+ ------------------------------------------------------------
+
+ ALTER TABLE dashboard_user_sessions
+ ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+
+ ALTER TABLE dashboard_user_sessions
+ DROP PRIMARY KEY;
+
+ ALTER TABLE dashboard_user_sessions
+ ADD PRIMARY KEY (app_id, session_id);
+
+ ALTER TABLE dashboard_user_sessions
+ DROP INDEX user_id;
+
+ ALTER TABLE dashboard_user_sessions
+ ADD FOREIGN KEY (app_id, user_id)
+ REFERENCES dashboard_users (app_id, user_id) ON DELETE CASCADE;
+
+ -- TOTP
+
+ ALTER TABLE totp_users
+ ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+
+ ALTER TABLE totp_users
+ DROP PRIMARY KEY;
+
+ ALTER TABLE totp_users
+ ADD PRIMARY KEY (app_id, user_id);
+
+ ALTER TABLE totp_users
+ ADD FOREIGN KEY (app_id)
+ REFERENCES apps (app_id) ON DELETE CASCADE;
+
+ ------------------------------------------------------------
+
+ ALTER TABLE totp_user_devices
+ ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+
+ ALTER TABLE totp_user_devices
+ DROP PRIMARY KEY;
+
+ ALTER TABLE totp_user_devices
+ ADD PRIMARY KEY (app_id, user_id, device_name);
+
+ ALTER TABLE totp_user_devices
+ ADD FOREIGN KEY (app_id, user_id)
+ REFERENCES totp_users (app_id, user_id) ON DELETE CASCADE;
+
+ ------------------------------------------------------------
+
+ ALTER TABLE totp_used_codes
+ ADD COLUMN app_id VARCHAR(64) DEFAULT 'public',
+ ADD COLUMN tenant_id VARCHAR(64) DEFAULT 'public';
+
+ ALTER TABLE totp_used_codes
+ DROP PRIMARY KEY;
+
+ ALTER TABLE totp_used_codes
+ ADD PRIMARY KEY (app_id, tenant_id, user_id, created_time_ms);
+
+ ALTER TABLE totp_used_codes
+ ADD FOREIGN KEY (app_id, user_id)
+ REFERENCES totp_users (app_id, user_id) ON DELETE CASCADE;
+
+ ALTER TABLE totp_used_codes
+ ADD FOREIGN KEY (app_id, tenant_id)
+ REFERENCES tenants (app_id, tenant_id) ON DELETE CASCADE;
+
+ ALTER TABLE totp_used_codes
+ DROP INDEX totp_used_codes_expiry_time_ms_index;
+
+ CREATE INDEX totp_used_codes_expiry_time_ms_index ON totp_used_codes (app_id, tenant_id, expiry_time_ms);
+
+ -- ActiveUsers
+
+ ALTER TABLE user_last_active
+ ADD COLUMN app_id VARCHAR(64) DEFAULT 'public';
+
+ ALTER TABLE user_last_active
+ DROP PRIMARY KEY;
+
+ ALTER TABLE user_last_active
+ ADD PRIMARY KEY (app_id, user_id);
+
+ ALTER TABLE user_last_active
+ ADD FOREIGN KEY (app_id)
+ REFERENCES apps (app_id) ON DELETE CASCADE;
+ ```
+
+
-
+4. Start the new instance(s) of the core (version 6.0.0)
## [5.0.0] - 2023-04-05
diff --git a/config.yaml b/config.yaml
index a86039a8d..e65a47024 100644
--- a/config.yaml
+++ b/config.yaml
@@ -141,3 +141,7 @@ core_config_version: 0
# what database information is shown to / modifiable by the dev when they query the core to get the information about
# their tenants. It only exposes that information when this key is used instead of the regular api_keys config.
# supertokens_saas_secret:
+
+# (OPTIONAL | Default: null). This is used when the core needs to assume a specific CDI version when CDI version is not
+# specified in the request. When set to null, the core will assume the latest version of the CDI.
+# supertokens_default_cdi_version:
diff --git a/devConfig.yaml b/devConfig.yaml
index 78f7b79b8..f51d8b9f1 100644
--- a/devConfig.yaml
+++ b/devConfig.yaml
@@ -142,3 +142,7 @@ disable_telemetry: true
# what database information is shown to / modifiable by the dev when they query the core to get the information about
# their tenants. It only exposes that information when this key is used instead of the regular api_keys config.
# supertokens_saas_secret:
+
+# (OPTIONAL | Default: null). This is used when the core needs to assume a specific CDI version when CDI version is not
+# specified in the request. When set to null, the core will assume the latest version of the CDI.
+# supertokens_default_cdi_version:
diff --git a/src/main/java/io/supertokens/config/CoreConfig.java b/src/main/java/io/supertokens/config/CoreConfig.java
index 52d599f1e..036416d41 100644
--- a/src/main/java/io/supertokens/config/CoreConfig.java
+++ b/src/main/java/io/supertokens/config/CoreConfig.java
@@ -28,6 +28,8 @@
import io.supertokens.exceptions.QuitProgramException;
import io.supertokens.pluginInterface.LOG_LEVEL;
import io.supertokens.pluginInterface.exceptions.InvalidConfigException;
+import io.supertokens.utils.SemVer;
+import io.supertokens.webserver.WebserverAPI;
import org.apache.catalina.filters.RemoteAddrFilter;
import org.jetbrains.annotations.TestOnly;
@@ -148,6 +150,9 @@ public class CoreConfig {
@JsonProperty
private String supertokens_saas_secret = null;
+ @JsonProperty
+ private String supertokens_default_cdi_version = null;
+
private Set allowedLogLevels = null;
public static Set getValidFields() {
@@ -554,6 +559,18 @@ void validate(Main main) throws InvalidConfigException {
}
}
}
+
+ if (supertokens_default_cdi_version != null) {
+ try {
+ SemVer version = new SemVer(supertokens_default_cdi_version);
+
+ if (!WebserverAPI.supportedVersions.contains(version)) {
+ throw new InvalidConfigException("supertokens_default_cdi_version is not a supported version");
+ }
+ } catch (IllegalArgumentException e) {
+ throw new InvalidConfigException("supertokens_default_cdi_version is not a valid semantic version");
+ }
+ }
}
public void createLoggingFile(Main main) throws IOException {
@@ -636,6 +653,11 @@ static void assertThatCertainConfigIsNotSetForAppOrTenants(JsonObject config) th
throw new InvalidConfigException(
"supertokens_saas_secret can only be set via the core's base config setting");
}
+
+ if (config.has("supertokens_default_cdi_version")) {
+ throw new InvalidConfigException(
+ "supertokens_default_cdi_version can only be set via the core's base config setting");
+ }
}
void assertThatConfigFromSameAppIdAreNotConflicting(CoreConfig other) throws InvalidConfigException {
@@ -718,5 +740,9 @@ void assertThatConfigFromSameAppIdAreNotConflicting(CoreConfig other) throws Inv
}
}
}
+
+ public String getDefaultCDIVersion() {
+ return this.supertokens_default_cdi_version;
+ }
}
diff --git a/src/main/java/io/supertokens/webserver/WebserverAPI.java b/src/main/java/io/supertokens/webserver/WebserverAPI.java
index 1fc03a1d7..c579b2fa2 100644
--- a/src/main/java/io/supertokens/webserver/WebserverAPI.java
+++ b/src/main/java/io/supertokens/webserver/WebserverAPI.java
@@ -461,10 +461,17 @@ protected String getRIDFromRequest(HttpServletRequest req) {
protected SemVer getVersionFromRequest(HttpServletRequest req) {
String version = req.getHeader("cdi-version");
- if (version == null) {
- return getLatestCDIVersion();
+
+ if (version != null) {
+ return new SemVer(version);
}
- return new SemVer(version);
+
+ String defaultCDIVersion = Config.getBaseConfig(main).getDefaultCDIVersion();
+ if (defaultCDIVersion != null) {
+ return new SemVer(defaultCDIVersion);
+ }
+
+ return getLatestCDIVersion();
}
public static class BadRequestException extends Exception {
diff --git a/src/test/java/io/supertokens/test/CDIVersionTest.java b/src/test/java/io/supertokens/test/CDIVersionTest.java
new file mode 100644
index 000000000..2b3bc717d
--- /dev/null
+++ b/src/test/java/io/supertokens/test/CDIVersionTest.java
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2023, VRAI Labs and/or its affiliates. All rights reserved.
+ *
+ * This software is licensed under the Apache License, Version 2.0 (the
+ * "License") as published by the Apache Software Foundation.
+ *
+ * You may not use this file except in compliance with the License. You may
+ * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package io.supertokens.test;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import io.supertokens.ProcessState;
+import io.supertokens.httpRequest.HttpRequest;
+import io.supertokens.test.httpRequest.HttpRequestForTesting;
+import io.supertokens.utils.SemVer;
+import io.supertokens.webserver.Webserver;
+import io.supertokens.webserver.WebserverAPI;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+
+import java.io.IOException;
+import java.util.HashMap;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.junit.Assert.*;
+
+public class CDIVersionTest {
+ @Rule
+ public TestRule watchman = Utils.getOnFailure();
+
+ @AfterClass
+ public static void afterTesting() {
+ Utils.afterTesting();
+ }
+
+ @Before
+ public void beforeEach() {
+ Utils.reset();
+ }
+
+ @Test
+ public void testThatAPIUsesLatestVersionByDefault() throws Exception {
+ String[] args = {"../"};
+ TestingProcessManager.TestingProcess process = TestingProcessManager.start(args);
+ assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED));
+
+ Webserver.getInstance(process.getProcess()).addAPI(new WebserverAPI(process.getProcess(), "") {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public boolean checkAPIKey(HttpServletRequest req) {
+ return false;
+ }
+
+ @Override
+ public String getPath() {
+ return "/version-test";
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ SemVer version = getVersionFromRequest(req);
+
+ super.sendTextResponse(200, version.toString(), resp);
+ }
+ });
+
+ String response = HttpRequestForTesting.sendGETRequest(process.getProcess(), "",
+ "http://localhost:3567/version-test", new HashMap<>(), 1000, 1000, null,
+ null, "");
+ assertEquals(WebserverAPI.getLatestCDIVersion().toString(), response);
+
+ process.kill();
+ assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STOPPED));
+ }
+
+ @Test
+ public void testThatAPIUsesVersionSpecifiedInTheRequest() throws Exception {
+ String[] args = {"../"};
+ TestingProcessManager.TestingProcess process = TestingProcessManager.start(args);
+ assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED));
+
+ Webserver.getInstance(process.getProcess()).addAPI(new WebserverAPI(process.getProcess(), "") {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public boolean checkAPIKey(HttpServletRequest req) {
+ return false;
+ }
+
+ @Override
+ public String getPath() {
+ return "/version-test";
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ SemVer version = getVersionFromRequest(req);
+
+ super.sendTextResponse(200, version.toString(), resp);
+ }
+ });
+
+ String response = HttpRequestForTesting.sendGETRequest(process.getProcess(), "",
+ "http://localhost:3567/version-test", new HashMap<>(), 1000, 1000, null,
+ "2.21", "");
+ assertEquals("2.21", response);
+
+ response = HttpRequestForTesting.sendGETRequest(process.getProcess(), "",
+ "http://localhost:3567/version-test", new HashMap<>(), 1000, 1000, null,
+ "2.10", "");
+ assertEquals("2.10", response);
+
+ process.kill();
+ assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STOPPED));
+ }
+
+ @Test
+ public void testThatAPIUsesVersionSpecifiedInConfigAsDefault() throws Exception {
+ String[] args = {"../"};
+
+ TestingProcessManager.TestingProcess process = TestingProcessManager.start(args, false);
+ Utils.setValueInConfig("supertokens_default_cdi_version", "2.21");
+ process.startProcess();
+
+ assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED));
+
+ Webserver.getInstance(process.getProcess()).addAPI(new WebserverAPI(process.getProcess(), "") {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public boolean checkAPIKey(HttpServletRequest req) {
+ return false;
+ }
+
+ @Override
+ public String getPath() {
+ return "/version-test";
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ SemVer version = getVersionFromRequest(req);
+
+ super.sendTextResponse(200, version.toString(), resp);
+ }
+ });
+
+ String response = HttpRequestForTesting.sendGETRequest(process.getProcess(), "",
+ "http://localhost:3567/version-test", new HashMap<>(), 1000, 1000, null,
+ null, "");
+ assertEquals("2.21", response);
+
+ process.kill();
+ assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STOPPED));
+ }
+
+ @Test
+ public void testThatAPIUsesVersionSpecifiedInRequestWhenTheConfigIsPresent() throws Exception {
+ String[] args = {"../"};
+
+ TestingProcessManager.TestingProcess process = TestingProcessManager.start(args, false);
+ Utils.setValueInConfig("supertokens_default_cdi_version", "2.21");
+ process.startProcess();
+
+ assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED));
+
+ Webserver.getInstance(process.getProcess()).addAPI(new WebserverAPI(process.getProcess(), "") {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public boolean checkAPIKey(HttpServletRequest req) {
+ return false;
+ }
+
+ @Override
+ public String getPath() {
+ return "/version-test";
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ SemVer version = getVersionFromRequest(req);
+
+ super.sendTextResponse(200, version.toString(), resp);
+ }
+ });
+
+ String response = HttpRequestForTesting.sendGETRequest(process.getProcess(), "",
+ "http://localhost:3567/version-test", new HashMap<>(), 1000, 1000, null,
+ "2.10", "");
+ assertEquals("2.10", response);
+
+ process.kill();
+ assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STOPPED));
+ }
+
+ @Test
+ public void testJWKSEndpointWorksInAllCases() throws Exception {
+ {
+ String[] args = {"../"};
+
+ TestingProcessManager.TestingProcess process = TestingProcessManager.start(args, false);
+ process.startProcess();
+ assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED));
+
+ {
+ // check regular output
+ JsonObject response = HttpRequest.sendGETRequest(process.getProcess(), "", "http://localhost:3567/.well-known/jwks.json", null,
+ 1000, 1000, null);
+
+ assertEquals(response.entrySet().size(), 1);
+
+ assertTrue(response.has("keys"));
+ JsonArray keys = response.get("keys").getAsJsonArray();
+ assertEquals(keys.size(), 2);
+ }
+
+ {
+ JsonObject oldResponse = HttpRequestForTesting.sendGETRequest(process.getProcess(), "",
+ "http://localhost:3567/recipe/jwt/jwks", null, 1000, 1000, null, Utils.getCdiVersionStringLatestForTests(),
+ "jwt");
+
+ JsonArray oldKeys = oldResponse.getAsJsonArray("keys");
+ assertEquals(oldKeys.size(), 2); // 1 static + 1 dynamic key
+ }
+
+ process.kill();
+ assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STOPPED));
+ }
+
+ {
+ String[] args = {"../"};
+
+ TestingProcessManager.TestingProcess process = TestingProcessManager.start(args, false);
+ Utils.setValueInConfig("supertokens_default_cdi_version", "2.9");
+ process.startProcess();
+ assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED));
+
+ {
+ // check regular output
+ JsonObject response = HttpRequest.sendGETRequest(process.getProcess(), "", "http://localhost:3567/.well-known/jwks.json", null,
+ 1000, 1000, null);
+
+ assertEquals(response.entrySet().size(), 1);
+
+ assertTrue(response.has("keys"));
+ JsonArray keys = response.get("keys").getAsJsonArray();
+ assertEquals(keys.size(), 2);
+ }
+
+ {
+ JsonObject oldResponse = HttpRequestForTesting.sendGETRequest(process.getProcess(), "",
+ "http://localhost:3567/recipe/jwt/jwks", null, 1000, 1000, null, Utils.getCdiVersionStringLatestForTests(),
+ "jwt");
+
+ JsonArray oldKeys = oldResponse.getAsJsonArray("keys");
+ assertEquals(oldKeys.size(), 2); // 1 static + 1 dynamic key
+ }
+
+ process.kill();
+ assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STOPPED));
+ }
+ }
+
+ @Test
+ public void testInvalidSemanticVersion() throws Exception {
+ String[] args = {"../"};
+
+ TestingProcessManager.TestingProcess process = TestingProcessManager.start(args, false);
+ Utils.setValueInConfig("supertokens_default_cdi_version", "2.x");
+ process.startProcess();
+
+ ProcessState.EventAndException state = process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.INIT_FAILURE);
+ assertNotNull(state);
+
+ assertEquals("supertokens_default_cdi_version is not a valid semantic version", state.exception.getCause().getMessage());
+ process.kill();
+ assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STOPPED));
+ }
+
+ @Test
+ public void testUnsupportedVersion() throws Exception {
+ String[] args = {"../"};
+
+ TestingProcessManager.TestingProcess process = TestingProcessManager.start(args, false);
+ Utils.setValueInConfig("supertokens_default_cdi_version", "2.1");
+ process.startProcess();
+
+ ProcessState.EventAndException state = process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.INIT_FAILURE);
+ assertNotNull(state);
+
+ assertEquals("supertokens_default_cdi_version is not a supported version", state.exception.getCause().getMessage());
+ process.kill();
+ assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STOPPED));
+ }
+}
diff --git a/src/test/java/io/supertokens/test/multitenant/api/TestTenantIdIsNotPresentForOlderCDI.java b/src/test/java/io/supertokens/test/multitenant/api/TestTenantIdIsNotPresentForOlderCDI.java
index 023c09086..3bfc81caf 100644
--- a/src/test/java/io/supertokens/test/multitenant/api/TestTenantIdIsNotPresentForOlderCDI.java
+++ b/src/test/java/io/supertokens/test/multitenant/api/TestTenantIdIsNotPresentForOlderCDI.java
@@ -341,7 +341,7 @@ public static JsonObject listUsers(TenantIdentifier sourceTenant, String paginat
}
JsonObject response = HttpRequestForTesting.sendGETRequest(main, "",
HttpRequestForTesting.getMultitenantUrl(sourceTenant, "/users"),
- params, 1000000, 1000000, null,
+ params, 1000, 1000, null,
SemVer.v2_21.get(), null);
assertEquals("OK", response.getAsJsonPrimitive("status").getAsString());