108_auth_identity_foundation_core.sql 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. ALTER TABLE users
  2. ADD COLUMN IF NOT EXISTS signup_source VARCHAR(20) NOT NULL DEFAULT 'email',
  3. ADD COLUMN IF NOT EXISTS last_login_at TIMESTAMPTZ NULL,
  4. ADD COLUMN IF NOT EXISTS last_active_at TIMESTAMPTZ NULL;
  5. UPDATE users
  6. SET signup_source = 'email'
  7. WHERE signup_source IS NULL OR signup_source = '';
  8. DO $$
  9. BEGIN
  10. IF NOT EXISTS (
  11. SELECT 1
  12. FROM pg_constraint
  13. WHERE conname = 'users_signup_source_check'
  14. ) THEN
  15. ALTER TABLE users
  16. ADD CONSTRAINT users_signup_source_check
  17. CHECK (signup_source IN ('email', 'linuxdo', 'wechat', 'oidc'));
  18. END IF;
  19. END $$;
  20. CREATE TABLE IF NOT EXISTS auth_identities (
  21. id BIGSERIAL PRIMARY KEY,
  22. user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  23. provider_type VARCHAR(20) NOT NULL,
  24. provider_key TEXT NOT NULL,
  25. provider_subject TEXT NOT NULL,
  26. verified_at TIMESTAMPTZ NULL,
  27. issuer TEXT NULL,
  28. metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
  29. created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  30. updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  31. CONSTRAINT auth_identities_provider_type_check
  32. CHECK (provider_type IN ('email', 'linuxdo', 'wechat', 'oidc'))
  33. );
  34. CREATE UNIQUE INDEX IF NOT EXISTS auth_identities_provider_subject_key
  35. ON auth_identities (provider_type, provider_key, provider_subject);
  36. CREATE INDEX IF NOT EXISTS auth_identities_user_id_idx
  37. ON auth_identities (user_id);
  38. CREATE INDEX IF NOT EXISTS auth_identities_user_provider_idx
  39. ON auth_identities (user_id, provider_type);
  40. CREATE TABLE IF NOT EXISTS auth_identity_channels (
  41. id BIGSERIAL PRIMARY KEY,
  42. identity_id BIGINT NOT NULL REFERENCES auth_identities(id) ON DELETE CASCADE,
  43. provider_type VARCHAR(20) NOT NULL,
  44. provider_key TEXT NOT NULL,
  45. channel VARCHAR(20) NOT NULL,
  46. channel_app_id TEXT NOT NULL,
  47. channel_subject TEXT NOT NULL,
  48. metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
  49. created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  50. updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  51. CONSTRAINT auth_identity_channels_provider_type_check
  52. CHECK (provider_type IN ('email', 'linuxdo', 'wechat', 'oidc'))
  53. );
  54. CREATE UNIQUE INDEX IF NOT EXISTS auth_identity_channels_channel_key
  55. ON auth_identity_channels (provider_type, provider_key, channel, channel_app_id, channel_subject);
  56. CREATE INDEX IF NOT EXISTS auth_identity_channels_identity_id_idx
  57. ON auth_identity_channels (identity_id);
  58. CREATE TABLE IF NOT EXISTS pending_auth_sessions (
  59. id BIGSERIAL PRIMARY KEY,
  60. session_token VARCHAR(255) NOT NULL,
  61. intent VARCHAR(40) NOT NULL,
  62. provider_type VARCHAR(20) NOT NULL,
  63. provider_key TEXT NOT NULL,
  64. provider_subject TEXT NOT NULL,
  65. target_user_id BIGINT NULL REFERENCES users(id) ON DELETE SET NULL,
  66. redirect_to TEXT NOT NULL DEFAULT '',
  67. resolved_email TEXT NOT NULL DEFAULT '',
  68. registration_password_hash TEXT NOT NULL DEFAULT '',
  69. upstream_identity_claims JSONB NOT NULL DEFAULT '{}'::jsonb,
  70. local_flow_state JSONB NOT NULL DEFAULT '{}'::jsonb,
  71. browser_session_key TEXT NOT NULL DEFAULT '',
  72. completion_code_hash TEXT NOT NULL DEFAULT '',
  73. completion_code_expires_at TIMESTAMPTZ NULL,
  74. email_verified_at TIMESTAMPTZ NULL,
  75. password_verified_at TIMESTAMPTZ NULL,
  76. totp_verified_at TIMESTAMPTZ NULL,
  77. expires_at TIMESTAMPTZ NOT NULL,
  78. consumed_at TIMESTAMPTZ NULL,
  79. created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  80. updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  81. CONSTRAINT pending_auth_sessions_intent_check
  82. CHECK (intent IN ('login', 'bind_current_user', 'adopt_existing_user_by_email')),
  83. CONSTRAINT pending_auth_sessions_provider_type_check
  84. CHECK (provider_type IN ('email', 'linuxdo', 'wechat', 'oidc'))
  85. );
  86. CREATE UNIQUE INDEX IF NOT EXISTS pending_auth_sessions_session_token_key
  87. ON pending_auth_sessions (session_token);
  88. CREATE INDEX IF NOT EXISTS pending_auth_sessions_target_user_id_idx
  89. ON pending_auth_sessions (target_user_id);
  90. CREATE INDEX IF NOT EXISTS pending_auth_sessions_expires_at_idx
  91. ON pending_auth_sessions (expires_at);
  92. CREATE INDEX IF NOT EXISTS pending_auth_sessions_provider_idx
  93. ON pending_auth_sessions (provider_type, provider_key, provider_subject);
  94. CREATE INDEX IF NOT EXISTS pending_auth_sessions_completion_code_idx
  95. ON pending_auth_sessions (completion_code_hash);
  96. CREATE TABLE IF NOT EXISTS identity_adoption_decisions (
  97. id BIGSERIAL PRIMARY KEY,
  98. pending_auth_session_id BIGINT NOT NULL REFERENCES pending_auth_sessions(id) ON DELETE CASCADE,
  99. identity_id BIGINT NULL REFERENCES auth_identities(id) ON DELETE SET NULL,
  100. adopt_display_name BOOLEAN NOT NULL DEFAULT FALSE,
  101. adopt_avatar BOOLEAN NOT NULL DEFAULT FALSE,
  102. decided_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  103. created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  104. updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
  105. );
  106. CREATE UNIQUE INDEX IF NOT EXISTS identity_adoption_decisions_pending_auth_session_id_key
  107. ON identity_adoption_decisions (pending_auth_session_id);
  108. CREATE INDEX IF NOT EXISTS identity_adoption_decisions_identity_id_idx
  109. ON identity_adoption_decisions (identity_id);
  110. CREATE TABLE IF NOT EXISTS auth_identity_migration_reports (
  111. id BIGSERIAL PRIMARY KEY,
  112. report_type VARCHAR(40) NOT NULL,
  113. report_key TEXT NOT NULL,
  114. details JSONB NOT NULL DEFAULT '{}'::jsonb,
  115. created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
  116. );
  117. CREATE INDEX IF NOT EXISTS auth_identity_migration_reports_type_idx
  118. ON auth_identity_migration_reports (report_type);
  119. CREATE UNIQUE INDEX IF NOT EXISTS auth_identity_migration_reports_type_key
  120. ON auth_identity_migration_reports (report_type, report_key);