Files
sub2api/backend/migrations/115_auth_identity_legacy_external_backfill.sql
2026-04-21 00:13:40 +08:00

188 lines
6.3 KiB
SQL

DO $$
BEGIN
IF to_regclass('public.user_external_identities') IS NULL THEN
RETURN;
END IF;
EXECUTE $sql$
INSERT INTO auth_identities (
user_id,
provider_type,
provider_key,
provider_subject,
verified_at,
metadata
)
SELECT
legacy.user_id,
'linuxdo',
'linuxdo',
legacy.provider_user_id,
COALESCE(legacy.updated_at, legacy.created_at, NOW()),
legacy.metadata_json || jsonb_build_object(
'legacy_identity_id', legacy.id,
'provider_user_id', legacy.provider_user_id,
'provider_username', legacy.provider_username,
'display_name', legacy.display_name,
'migration', '115_auth_identity_legacy_external_backfill'
)
FROM (
SELECT
uei.id,
uei.user_id,
BTRIM(uei.provider_user_id) AS provider_user_id,
BTRIM(uei.provider_username) AS provider_username,
BTRIM(uei.display_name) AS display_name,
COALESCE(NULLIF(BTRIM(COALESCE(uei.metadata, '')), '')::jsonb, '{}'::jsonb) AS metadata_json,
uei.created_at,
uei.updated_at
FROM user_external_identities AS uei
JOIN users AS u ON u.id = uei.user_id
WHERE u.deleted_at IS NULL
AND LOWER(BTRIM(COALESCE(uei.provider, ''))) = 'linuxdo'
AND BTRIM(COALESCE(uei.provider_user_id, '')) <> ''
) AS legacy
ON CONFLICT (provider_type, provider_key, provider_subject) DO NOTHING;
$sql$;
EXECUTE $sql$
INSERT INTO auth_identities (
user_id,
provider_type,
provider_key,
provider_subject,
verified_at,
metadata
)
SELECT
legacy.user_id,
'wechat',
'wechat-main',
legacy.provider_union_id,
COALESCE(legacy.updated_at, legacy.created_at, NOW()),
legacy.metadata_json || jsonb_build_object(
'legacy_identity_id', legacy.id,
'openid', legacy.provider_user_id,
'unionid', legacy.provider_union_id,
'provider_user_id', legacy.provider_user_id,
'provider_union_id', legacy.provider_union_id,
'provider_username', legacy.provider_username,
'display_name', legacy.display_name,
'migration', '115_auth_identity_legacy_external_backfill'
)
FROM (
SELECT
uei.id,
uei.user_id,
BTRIM(uei.provider_user_id) AS provider_user_id,
BTRIM(uei.provider_union_id) AS provider_union_id,
BTRIM(uei.provider_username) AS provider_username,
BTRIM(uei.display_name) AS display_name,
COALESCE(NULLIF(BTRIM(COALESCE(uei.metadata, '')), '')::jsonb, '{}'::jsonb) AS metadata_json,
uei.created_at,
uei.updated_at
FROM user_external_identities AS uei
JOIN users AS u ON u.id = uei.user_id
WHERE u.deleted_at IS NULL
AND LOWER(BTRIM(COALESCE(uei.provider, ''))) = 'wechat'
AND BTRIM(COALESCE(uei.provider_union_id, '')) <> ''
) AS legacy
ON CONFLICT (provider_type, provider_key, provider_subject) DO NOTHING;
$sql$;
EXECUTE $sql$
INSERT INTO auth_identity_channels (
identity_id,
provider_type,
provider_key,
channel,
channel_app_id,
channel_subject,
metadata
)
SELECT
ai.id,
'wechat',
'wechat-main',
legacy.channel,
legacy.channel_app_id,
legacy.provider_user_id,
legacy.metadata_json || jsonb_build_object(
'openid', legacy.provider_user_id,
'unionid', legacy.provider_union_id,
'migration', '115_auth_identity_legacy_external_backfill'
)
FROM (
SELECT
uei.user_id,
BTRIM(uei.provider_user_id) AS provider_user_id,
BTRIM(uei.provider_union_id) AS provider_union_id,
BTRIM(COALESCE(meta.metadata_json ->> 'channel', '')) AS channel,
BTRIM(COALESCE(meta.metadata_json ->> 'channel_app_id', meta.metadata_json ->> 'appid', meta.metadata_json ->> 'app_id', '')) AS channel_app_id,
meta.metadata_json
FROM user_external_identities AS uei
JOIN users AS u ON u.id = uei.user_id
CROSS JOIN LATERAL (
SELECT COALESCE(NULLIF(BTRIM(COALESCE(uei.metadata, '')), '')::jsonb, '{}'::jsonb) AS metadata_json
) AS meta
WHERE u.deleted_at IS NULL
AND LOWER(BTRIM(COALESCE(uei.provider, ''))) = 'wechat'
AND BTRIM(COALESCE(uei.provider_union_id, '')) <> ''
) AS legacy
JOIN auth_identities AS ai
ON ai.user_id = legacy.user_id
AND ai.provider_type = 'wechat'
AND ai.provider_key = 'wechat-main'
AND ai.provider_subject = legacy.provider_union_id
WHERE legacy.channel <> ''
AND legacy.channel_app_id <> ''
AND legacy.provider_user_id <> ''
ON CONFLICT DO NOTHING;
$sql$;
EXECUTE $sql$
INSERT INTO auth_identity_migration_reports (report_type, report_key, details)
SELECT
'wechat_openid_only_requires_remediation',
'legacy_external_identity:' || legacy.id::text,
legacy.metadata_json || jsonb_build_object(
'legacy_identity_id', legacy.id,
'user_id', legacy.user_id,
'openid', legacy.provider_user_id,
'reason', 'legacy user_external_identities row only has openid and cannot be canonicalized offline',
'migration', '115_auth_identity_legacy_external_backfill'
)
FROM (
SELECT
uei.id,
uei.user_id,
BTRIM(uei.provider_user_id) AS provider_user_id,
COALESCE(NULLIF(BTRIM(COALESCE(uei.metadata, '')), '')::jsonb, '{}'::jsonb) AS metadata_json
FROM user_external_identities AS uei
JOIN users AS u ON u.id = uei.user_id
WHERE u.deleted_at IS NULL
AND LOWER(BTRIM(COALESCE(uei.provider, ''))) = 'wechat'
AND BTRIM(COALESCE(uei.provider_user_id, '')) <> ''
AND BTRIM(COALESCE(uei.provider_union_id, '')) = ''
) AS legacy
ON CONFLICT (report_type, report_key) DO NOTHING;
$sql$;
END $$;
INSERT INTO auth_identity_migration_reports (report_type, report_key, details)
SELECT
'wechat_openid_only_requires_remediation',
'synthetic_auth_identity:' || ai.id::text,
COALESCE(ai.metadata, '{}'::jsonb) || jsonb_build_object(
'auth_identity_id', ai.id,
'user_id', ai.user_id,
'provider_subject', ai.provider_subject,
'reason', 'synthetic wechat auth identity still lacks unionid metadata and needs remediation',
'migration', '115_auth_identity_legacy_external_backfill'
)
FROM auth_identities AS ai
WHERE ai.provider_type = 'wechat'
AND COALESCE(ai.metadata ->> 'backfill_source', '') = 'synthetic_email'
AND BTRIM(COALESCE(ai.metadata ->> 'unionid', '')) = ''
ON CONFLICT (report_type, report_key) DO NOTHING;