Skip to content

Commit

Permalink
Merge pull request #719 from supertokens/db-schema
Browse files Browse the repository at this point in the history
fix: account linking db schema for postgres and mysql
  • Loading branch information
rishabhpoddar authored Sep 25, 2023
2 parents 77083ad + c219c9e commit e84495d
Show file tree
Hide file tree
Showing 24 changed files with 672 additions and 72 deletions.
32 changes: 28 additions & 4 deletions v2/community/database-setup/mysql.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -175,23 +175,46 @@ CREATE TABLE `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_or_recipe_user_id` char(36) NOT NULL,
`is_linked_or_is_a_primary_user` BOOLEAN NOT NULL DEFAULT FALSE,
PRIMARY KEY (`app_id`,`user_id`),
CONSTRAINT `app_id_to_user_id_ibfk_1` FOREIGN KEY (`app_id`) REFERENCES `apps` (`app_id`) ON DELETE CASCADE
FOREIGN KEY (`app_id`) REFERENCES `apps` (`app_id`) ON DELETE CASCADE,
FOREIGN KEY (`app_id`, `primary_or_recipe_user_id`) REFERENCES `app_id_to_user_id` (`app_id`, `user_id`) ON DELETE CASCADE
);

CREATE TABLE `all_auth_recipe_users` (
`app_id` varchar(64) NOT NULL DEFAULT 'public',
`tenant_id` varchar(64) NOT NULL DEFAULT 'public',
`user_id` char(36) NOT NULL,
`primary_or_recipe_user_id` char(36) NOT NULL,
`is_linked_or_is_a_primary_user` BOOLEAN NOT NULL DEFAULT FALSE,
`recipe_id` varchar(128) NOT NULL,
`time_joined` bigint unsigned NOT NULL,
`primary_or_recipe_user_time_joined` bigint unsigned NOT NULL,
PRIMARY KEY (`app_id`,`tenant_id`,`user_id`),
KEY `app_id` (`app_id`,`user_id`),
FOREIGN KEY (`app_id`, `tenant_id`) REFERENCES `tenants` (`app_id`, `tenant_id`) ON DELETE CASCADE,
FOREIGN KEY (`app_id`, `user_id`) REFERENCES `app_id_to_user_id` (`app_id`, `user_id`) ON DELETE CASCADE
FOREIGN KEY (`app_id`, `user_id`) REFERENCES `app_id_to_user_id` (`app_id`, `user_id`) ON DELETE CASCADE,
FOREIGN KEY (`app_id`, `primary_or_recipe_user_id`) REFERENCES `app_id_to_user_id` (`app_id`, `user_id`) ON DELETE CASCADE
);

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 all_auth_recipe_users_pagination_index1 ON all_auth_recipe_users
(app_id, tenant_id, primary_or_recipe_user_time_joined DESC, primary_or_recipe_user_id DESC);

CREATE INDEX all_auth_recipe_users_pagination_index2 ON all_auth_recipe_users
(app_id, tenant_id, primary_or_recipe_user_time_joined ASC, primary_or_recipe_user_id DESC);

CREATE INDEX all_auth_recipe_users_pagination_index3 ON all_auth_recipe_users
(recipe_id, app_id, tenant_id, primary_or_recipe_user_time_joined DESC, primary_or_recipe_user_id DESC);

CREATE INDEX all_auth_recipe_users_pagination_index4 ON all_auth_recipe_users
(recipe_id, app_id, tenant_id, primary_or_recipe_user_time_joined ASC, primary_or_recipe_user_id DESC);

CREATE INDEX all_auth_recipe_users_primary_user_id_index ON all_auth_recipe_users
(primary_or_recipe_user_id, app_id);

CREATE INDEX all_auth_recipe_users_recipe_id_index ON all_auth_recipe_users
(app_id, recipe_id, tenant_id);

CREATE TABLE `userid_mapping` (
`app_id` varchar(64) NOT NULL DEFAULT 'public',
Expand Down Expand Up @@ -286,9 +309,10 @@ CREATE TABLE `emailpassword_pswd_reset_tokens` (
`user_id` char(36) NOT NULL,
`token` varchar(128) NOT NULL,
`token_expiry` bigint unsigned NOT NULL,
`email` varchar(256),
PRIMARY KEY (`app_id`,`user_id`,`token`),
UNIQUE KEY `token` (`token`),
FOREIGN KEY (`app_id`, `user_id`) REFERENCES `emailpassword_users` (`app_id`, `user_id`) ON DELETE CASCADE ON UPDATE CASCADE
FOREIGN KEY (`app_id`, `user_id`) REFERENCES `app_id_to_user_id` (`app_id`, `user_id`) ON DELETE CASCADE ON UPDATE CASCADE
);

CREATE INDEX `emailpassword_password_reset_token_expiry_index` ON `emailpassword_pswd_reset_tokens` (`token_expiry`);
Expand Down
30 changes: 28 additions & 2 deletions v2/community/database-setup/postgresql.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,10 @@ CREATE TABLE app_id_to_user_id (
app_id VARCHAR(64) DEFAULT 'public' NOT NULL,
user_id character(36) NOT NULL,
recipe_id VARCHAR(128) NOT NULL,
primary_or_recipe_user_id CHAR(36) NOT NULL,
is_linked_or_is_a_primary_user BOOLEAN NOT NULL DEFAULT FALSE,
CONSTRAINT app_id_to_user_id_pkey PRIMARY KEY (app_id, user_id),
CONSTRAINT app_id_to_user_id_primary_or_recipe_user_id_fkey FOREIGN KEY(app_id, primary_or_recipe_user_id) REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE,
CONSTRAINT app_id_to_user_id_app_id_fkey FOREIGN KEY (app_id) REFERENCES public.apps(app_id) ON DELETE CASCADE
);
Expand All @@ -198,14 +201,36 @@ CREATE TABLE all_auth_recipe_users (
app_id VARCHAR(64) DEFAULT 'public' NOT NULL,
tenant_id VARCHAR(64) DEFAULT 'public' NOT NULL,
user_id character(36) NOT NULL,
primary_or_recipe_user_id CHAR(36) NOT NULL,
is_linked_or_is_a_primary_user BOOLEAN NOT NULL DEFAULT FALSE,
recipe_id VARCHAR(128) NOT NULL,
time_joined BIGINT NOT NULL,
primary_or_recipe_user_time_joined BIGINT NOT NULL,
CONSTRAINT all_auth_recipe_users_pkey PRIMARY KEY (app_id, tenant_id, user_id),
CONSTRAINT all_auth_recipe_users_tenant_id_fkey FOREIGN KEY (app_id, tenant_id) REFERENCES public.tenants(app_id, tenant_id) ON DELETE CASCADE,
CONSTRAINT all_auth_recipe_users_primary_or_recipe_user_id_fkey FOREIGN KEY(app_id, primary_or_recipe_user_id) REFERENCES public.app_id_to_user_id (app_id, user_id) ON DELETE CASCADE,
CONSTRAINT all_auth_recipe_users_user_id_fkey FOREIGN KEY (app_id, user_id) REFERENCES public.app_id_to_user_id(app_id, user_id) ON DELETE CASCADE
);
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 all_auth_recipe_users_pagination_index1 ON all_auth_recipe_users
(app_id, tenant_id, primary_or_recipe_user_time_joined DESC, primary_or_recipe_user_id DESC);
CREATE INDEX all_auth_recipe_users_pagination_index2 ON all_auth_recipe_users
(app_id, tenant_id, primary_or_recipe_user_time_joined ASC, primary_or_recipe_user_id DESC);
CREATE INDEX all_auth_recipe_users_pagination_index3 ON all_auth_recipe_users
(recipe_id, app_id, tenant_id, primary_or_recipe_user_time_joined DESC, primary_or_recipe_user_id DESC);
CREATE INDEX all_auth_recipe_users_pagination_index4 ON all_auth_recipe_users
(recipe_id, app_id, tenant_id, primary_or_recipe_user_time_joined ASC, primary_or_recipe_user_id DESC);
CREATE INDEX all_auth_recipe_users_primary_user_id_index ON all_auth_recipe_users
(primary_or_recipe_user_id, app_id);
CREATE INDEX all_auth_recipe_users_recipe_id_index ON all_auth_recipe_users
(app_id, recipe_id, tenant_id);
CREATE INDEX all_auth_recipe_user_id_index ON all_auth_recipe_users (app_id, user_id);
Expand Down Expand Up @@ -315,9 +340,10 @@ CREATE TABLE emailpassword_pswd_reset_tokens (
user_id character(36) NOT NULL,
token VARCHAR(128) NOT NULL,
token_expiry BIGINT NOT NULL,
email VARCHAR(256),
CONSTRAINT emailpassword_pswd_reset_tokens_pkey PRIMARY KEY (app_id, user_id, token),
CONSTRAINT emailpassword_pswd_reset_tokens_token_key UNIQUE (token),
CONSTRAINT emailpassword_pswd_reset_tokens_user_id_fkey FOREIGN KEY (app_id, user_id) REFERENCES public.emailpassword_users(app_id, user_id) ON UPDATE CASCADE ON DELETE CASCADE
CONSTRAINT emailpassword_pswd_reset_tokens_user_id_fkey FOREIGN KEY (app_id, user_id) REFERENCES public.app_id_to_user_id(app_id, user_id) ON UPDATE CASCADE ON DELETE CASCADE
);
CREATE INDEX emailpassword_password_reset_token_expiry_index ON emailpassword_pswd_reset_tokens (token_expiry);
Expand Down
32 changes: 28 additions & 4 deletions v2/emailpassword/custom-ui/init/database-setup/mysql.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -175,23 +175,46 @@ CREATE TABLE `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_or_recipe_user_id` char(36) NOT NULL,
`is_linked_or_is_a_primary_user` BOOLEAN NOT NULL DEFAULT FALSE,
PRIMARY KEY (`app_id`,`user_id`),
CONSTRAINT `app_id_to_user_id_ibfk_1` FOREIGN KEY (`app_id`) REFERENCES `apps` (`app_id`) ON DELETE CASCADE
FOREIGN KEY (`app_id`) REFERENCES `apps` (`app_id`) ON DELETE CASCADE,
FOREIGN KEY (`app_id`, `primary_or_recipe_user_id`) REFERENCES `app_id_to_user_id` (`app_id`, `user_id`) ON DELETE CASCADE
);

CREATE TABLE `all_auth_recipe_users` (
`app_id` varchar(64) NOT NULL DEFAULT 'public',
`tenant_id` varchar(64) NOT NULL DEFAULT 'public',
`user_id` char(36) NOT NULL,
`primary_or_recipe_user_id` char(36) NOT NULL,
`is_linked_or_is_a_primary_user` BOOLEAN NOT NULL DEFAULT FALSE,
`recipe_id` varchar(128) NOT NULL,
`time_joined` bigint unsigned NOT NULL,
`primary_or_recipe_user_time_joined` bigint unsigned NOT NULL,
PRIMARY KEY (`app_id`,`tenant_id`,`user_id`),
KEY `app_id` (`app_id`,`user_id`),
FOREIGN KEY (`app_id`, `tenant_id`) REFERENCES `tenants` (`app_id`, `tenant_id`) ON DELETE CASCADE,
FOREIGN KEY (`app_id`, `user_id`) REFERENCES `app_id_to_user_id` (`app_id`, `user_id`) ON DELETE CASCADE
FOREIGN KEY (`app_id`, `user_id`) REFERENCES `app_id_to_user_id` (`app_id`, `user_id`) ON DELETE CASCADE,
FOREIGN KEY (`app_id`, `primary_or_recipe_user_id`) REFERENCES `app_id_to_user_id` (`app_id`, `user_id`) ON DELETE CASCADE
);

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 all_auth_recipe_users_pagination_index1 ON all_auth_recipe_users
(app_id, tenant_id, primary_or_recipe_user_time_joined DESC, primary_or_recipe_user_id DESC);

CREATE INDEX all_auth_recipe_users_pagination_index2 ON all_auth_recipe_users
(app_id, tenant_id, primary_or_recipe_user_time_joined ASC, primary_or_recipe_user_id DESC);

CREATE INDEX all_auth_recipe_users_pagination_index3 ON all_auth_recipe_users
(recipe_id, app_id, tenant_id, primary_or_recipe_user_time_joined DESC, primary_or_recipe_user_id DESC);

CREATE INDEX all_auth_recipe_users_pagination_index4 ON all_auth_recipe_users
(recipe_id, app_id, tenant_id, primary_or_recipe_user_time_joined ASC, primary_or_recipe_user_id DESC);

CREATE INDEX all_auth_recipe_users_primary_user_id_index ON all_auth_recipe_users
(primary_or_recipe_user_id, app_id);

CREATE INDEX all_auth_recipe_users_recipe_id_index ON all_auth_recipe_users
(app_id, recipe_id, tenant_id);

CREATE TABLE `userid_mapping` (
`app_id` varchar(64) NOT NULL DEFAULT 'public',
Expand Down Expand Up @@ -286,9 +309,10 @@ CREATE TABLE `emailpassword_pswd_reset_tokens` (
`user_id` char(36) NOT NULL,
`token` varchar(128) NOT NULL,
`token_expiry` bigint unsigned NOT NULL,
`email` varchar(256),
PRIMARY KEY (`app_id`,`user_id`,`token`),
UNIQUE KEY `token` (`token`),
FOREIGN KEY (`app_id`, `user_id`) REFERENCES `emailpassword_users` (`app_id`, `user_id`) ON DELETE CASCADE ON UPDATE CASCADE
FOREIGN KEY (`app_id`, `user_id`) REFERENCES `app_id_to_user_id` (`app_id`, `user_id`) ON DELETE CASCADE ON UPDATE CASCADE
);

CREATE INDEX `emailpassword_password_reset_token_expiry_index` ON `emailpassword_pswd_reset_tokens` (`token_expiry`);
Expand Down
30 changes: 28 additions & 2 deletions v2/emailpassword/custom-ui/init/database-setup/postgresql.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,10 @@ CREATE TABLE app_id_to_user_id (
app_id VARCHAR(64) DEFAULT 'public' NOT NULL,
user_id character(36) NOT NULL,
recipe_id VARCHAR(128) NOT NULL,
primary_or_recipe_user_id CHAR(36) NOT NULL,
is_linked_or_is_a_primary_user BOOLEAN NOT NULL DEFAULT FALSE,
CONSTRAINT app_id_to_user_id_pkey PRIMARY KEY (app_id, user_id),
CONSTRAINT app_id_to_user_id_primary_or_recipe_user_id_fkey FOREIGN KEY(app_id, primary_or_recipe_user_id) REFERENCES app_id_to_user_id (app_id, user_id) ON DELETE CASCADE,
CONSTRAINT app_id_to_user_id_app_id_fkey FOREIGN KEY (app_id) REFERENCES public.apps(app_id) ON DELETE CASCADE
);
Expand All @@ -198,14 +201,36 @@ CREATE TABLE all_auth_recipe_users (
app_id VARCHAR(64) DEFAULT 'public' NOT NULL,
tenant_id VARCHAR(64) DEFAULT 'public' NOT NULL,
user_id character(36) NOT NULL,
primary_or_recipe_user_id CHAR(36) NOT NULL,
is_linked_or_is_a_primary_user BOOLEAN NOT NULL DEFAULT FALSE,
recipe_id VARCHAR(128) NOT NULL,
time_joined BIGINT NOT NULL,
primary_or_recipe_user_time_joined BIGINT NOT NULL,
CONSTRAINT all_auth_recipe_users_pkey PRIMARY KEY (app_id, tenant_id, user_id),
CONSTRAINT all_auth_recipe_users_tenant_id_fkey FOREIGN KEY (app_id, tenant_id) REFERENCES public.tenants(app_id, tenant_id) ON DELETE CASCADE,
CONSTRAINT all_auth_recipe_users_primary_or_recipe_user_id_fkey FOREIGN KEY(app_id, primary_or_recipe_user_id) REFERENCES public.app_id_to_user_id (app_id, user_id) ON DELETE CASCADE,
CONSTRAINT all_auth_recipe_users_user_id_fkey FOREIGN KEY (app_id, user_id) REFERENCES public.app_id_to_user_id(app_id, user_id) ON DELETE CASCADE
);
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 all_auth_recipe_users_pagination_index1 ON all_auth_recipe_users
(app_id, tenant_id, primary_or_recipe_user_time_joined DESC, primary_or_recipe_user_id DESC);
CREATE INDEX all_auth_recipe_users_pagination_index2 ON all_auth_recipe_users
(app_id, tenant_id, primary_or_recipe_user_time_joined ASC, primary_or_recipe_user_id DESC);
CREATE INDEX all_auth_recipe_users_pagination_index3 ON all_auth_recipe_users
(recipe_id, app_id, tenant_id, primary_or_recipe_user_time_joined DESC, primary_or_recipe_user_id DESC);
CREATE INDEX all_auth_recipe_users_pagination_index4 ON all_auth_recipe_users
(recipe_id, app_id, tenant_id, primary_or_recipe_user_time_joined ASC, primary_or_recipe_user_id DESC);
CREATE INDEX all_auth_recipe_users_primary_user_id_index ON all_auth_recipe_users
(primary_or_recipe_user_id, app_id);
CREATE INDEX all_auth_recipe_users_recipe_id_index ON all_auth_recipe_users
(app_id, recipe_id, tenant_id);
CREATE INDEX all_auth_recipe_user_id_index ON all_auth_recipe_users (app_id, user_id);
Expand Down Expand Up @@ -315,9 +340,10 @@ CREATE TABLE emailpassword_pswd_reset_tokens (
user_id character(36) NOT NULL,
token VARCHAR(128) NOT NULL,
token_expiry BIGINT NOT NULL,
email VARCHAR(256),
CONSTRAINT emailpassword_pswd_reset_tokens_pkey PRIMARY KEY (app_id, user_id, token),
CONSTRAINT emailpassword_pswd_reset_tokens_token_key UNIQUE (token),
CONSTRAINT emailpassword_pswd_reset_tokens_user_id_fkey FOREIGN KEY (app_id, user_id) REFERENCES public.emailpassword_users(app_id, user_id) ON UPDATE CASCADE ON DELETE CASCADE
CONSTRAINT emailpassword_pswd_reset_tokens_user_id_fkey FOREIGN KEY (app_id, user_id) REFERENCES public.app_id_to_user_id(app_id, user_id) ON UPDATE CASCADE ON DELETE CASCADE
);
CREATE INDEX emailpassword_password_reset_token_expiry_index ON emailpassword_pswd_reset_tokens (token_expiry);
Expand Down
32 changes: 28 additions & 4 deletions v2/emailpassword/pre-built-ui/setup/database-setup/mysql.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -175,23 +175,46 @@ CREATE TABLE `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_or_recipe_user_id` char(36) NOT NULL,
`is_linked_or_is_a_primary_user` BOOLEAN NOT NULL DEFAULT FALSE,
PRIMARY KEY (`app_id`,`user_id`),
CONSTRAINT `app_id_to_user_id_ibfk_1` FOREIGN KEY (`app_id`) REFERENCES `apps` (`app_id`) ON DELETE CASCADE
FOREIGN KEY (`app_id`) REFERENCES `apps` (`app_id`) ON DELETE CASCADE,
FOREIGN KEY (`app_id`, `primary_or_recipe_user_id`) REFERENCES `app_id_to_user_id` (`app_id`, `user_id`) ON DELETE CASCADE
);

CREATE TABLE `all_auth_recipe_users` (
`app_id` varchar(64) NOT NULL DEFAULT 'public',
`tenant_id` varchar(64) NOT NULL DEFAULT 'public',
`user_id` char(36) NOT NULL,
`primary_or_recipe_user_id` char(36) NOT NULL,
`is_linked_or_is_a_primary_user` BOOLEAN NOT NULL DEFAULT FALSE,
`recipe_id` varchar(128) NOT NULL,
`time_joined` bigint unsigned NOT NULL,
`primary_or_recipe_user_time_joined` bigint unsigned NOT NULL,
PRIMARY KEY (`app_id`,`tenant_id`,`user_id`),
KEY `app_id` (`app_id`,`user_id`),
FOREIGN KEY (`app_id`, `tenant_id`) REFERENCES `tenants` (`app_id`, `tenant_id`) ON DELETE CASCADE,
FOREIGN KEY (`app_id`, `user_id`) REFERENCES `app_id_to_user_id` (`app_id`, `user_id`) ON DELETE CASCADE
FOREIGN KEY (`app_id`, `user_id`) REFERENCES `app_id_to_user_id` (`app_id`, `user_id`) ON DELETE CASCADE,
FOREIGN KEY (`app_id`, `primary_or_recipe_user_id`) REFERENCES `app_id_to_user_id` (`app_id`, `user_id`) ON DELETE CASCADE
);

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 all_auth_recipe_users_pagination_index1 ON all_auth_recipe_users
(app_id, tenant_id, primary_or_recipe_user_time_joined DESC, primary_or_recipe_user_id DESC);

CREATE INDEX all_auth_recipe_users_pagination_index2 ON all_auth_recipe_users
(app_id, tenant_id, primary_or_recipe_user_time_joined ASC, primary_or_recipe_user_id DESC);

CREATE INDEX all_auth_recipe_users_pagination_index3 ON all_auth_recipe_users
(recipe_id, app_id, tenant_id, primary_or_recipe_user_time_joined DESC, primary_or_recipe_user_id DESC);

CREATE INDEX all_auth_recipe_users_pagination_index4 ON all_auth_recipe_users
(recipe_id, app_id, tenant_id, primary_or_recipe_user_time_joined ASC, primary_or_recipe_user_id DESC);

CREATE INDEX all_auth_recipe_users_primary_user_id_index ON all_auth_recipe_users
(primary_or_recipe_user_id, app_id);

CREATE INDEX all_auth_recipe_users_recipe_id_index ON all_auth_recipe_users
(app_id, recipe_id, tenant_id);

CREATE TABLE `userid_mapping` (
`app_id` varchar(64) NOT NULL DEFAULT 'public',
Expand Down Expand Up @@ -286,9 +309,10 @@ CREATE TABLE `emailpassword_pswd_reset_tokens` (
`user_id` char(36) NOT NULL,
`token` varchar(128) NOT NULL,
`token_expiry` bigint unsigned NOT NULL,
`email` varchar(256),
PRIMARY KEY (`app_id`,`user_id`,`token`),
UNIQUE KEY `token` (`token`),
FOREIGN KEY (`app_id`, `user_id`) REFERENCES `emailpassword_users` (`app_id`, `user_id`) ON DELETE CASCADE ON UPDATE CASCADE
FOREIGN KEY (`app_id`, `user_id`) REFERENCES `app_id_to_user_id` (`app_id`, `user_id`) ON DELETE CASCADE ON UPDATE CASCADE
);

CREATE INDEX `emailpassword_password_reset_token_expiry_index` ON `emailpassword_pswd_reset_tokens` (`token_expiry`);
Expand Down
Loading

0 comments on commit e84495d

Please sign in to comment.