56 lines
2.3 KiB
PL/PgSQL
56 lines
2.3 KiB
PL/PgSQL
-- ============================================================
|
||
-- Migration 049: 创建 social_accounts 表 (第三方社交账号绑定)
|
||
--
|
||
-- 支持微信 / Google / Apple 等第三方 OAuth 登录。
|
||
-- 一个用户可绑定多个 Provider,通过 userId 外键关联到 users 表。
|
||
--
|
||
-- openid: Provider 内唯一(微信 openid 每个 App 不同)
|
||
-- unionid: 微信开放平台跨 App 唯一标识(优先用于用户查找)
|
||
-- raw_data: 完整 provider 响应(JSONB),保留全量信息备用
|
||
-- ============================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS social_accounts (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||
provider VARCHAR(20) NOT NULL,
|
||
openid VARCHAR(128) NOT NULL,
|
||
unionid VARCHAR(128),
|
||
nickname VARCHAR(100),
|
||
avatar_url VARCHAR(500),
|
||
raw_data JSONB,
|
||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
);
|
||
|
||
-- provider + openid 唯一索引(防止同一 App 下重复绑定)
|
||
CREATE UNIQUE INDEX IF NOT EXISTS idx_social_provider_openid
|
||
ON social_accounts(provider, openid);
|
||
|
||
-- provider + unionid 索引(优先用 unionid 查找用户)
|
||
CREATE INDEX IF NOT EXISTS idx_social_provider_unionid
|
||
ON social_accounts(provider, unionid)
|
||
WHERE unionid IS NOT NULL;
|
||
|
||
-- userId 索引(查某用户绑定了哪些 provider)
|
||
CREATE INDEX IF NOT EXISTS idx_social_user_id
|
||
ON social_accounts(user_id);
|
||
|
||
-- updated_at 自动更新触发器
|
||
CREATE OR REPLACE FUNCTION update_social_accounts_updated_at()
|
||
RETURNS TRIGGER AS $$
|
||
BEGIN
|
||
NEW.updated_at = NOW();
|
||
RETURN NEW;
|
||
END;
|
||
$$ LANGUAGE plpgsql;
|
||
|
||
CREATE TRIGGER trg_social_accounts_updated_at
|
||
BEFORE UPDATE ON social_accounts
|
||
FOR EACH ROW EXECUTE FUNCTION update_social_accounts_updated_at();
|
||
|
||
COMMENT ON TABLE social_accounts IS '第三方社交账号绑定记录(微信/Google/Apple 等)';
|
||
COMMENT ON COLUMN social_accounts.provider IS 'Provider 标识: wechat | google | apple';
|
||
COMMENT ON COLUMN social_accounts.openid IS 'Provider 内用户唯一 ID(微信 openid)';
|
||
COMMENT ON COLUMN social_accounts.unionid IS '微信开放平台跨 App 唯一标识(优先用于查找)';
|
||
COMMENT ON COLUMN social_accounts.raw_data IS 'Provider 原始响应(JSONB),保留全量数据';
|