Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
陈曦
sub2api
Commits
7a9488ff
"backend/vscode:/vscode.git/clone" did not exist on "452e55a53c7a22c3e4a0da2421d19cfb6819de96"
Commit
7a9488ff
authored
Apr 21, 2026
by
IanShaw027
Browse files
Add legacy identity safety remediation migration
parent
c297d011
Changes
2
Hide whitespace changes
Inline
Side-by-side
backend/internal/repository/auth_identity_legacy_migration_integration_test.go
View file @
7a9488ff
...
...
@@ -200,6 +200,252 @@ FROM auth_identity_migration_reports
var
afterCount
int
require
.
NoError
(
t
,
tx
.
QueryRowContext
(
ctx
,
`
SELECT COUNT(*)
FROM auth_identity_migration_reports
`
)
.
Scan
(
&
afterCount
))
require
.
Equal
(
t
,
beforeCount
,
afterCount
)
}
func
TestAuthIdentityLegacyExternalSafetyMigration_ReportsConflictsAndDowngradesInvalidJSON
(
t
*
testing
.
T
)
{
tx
:=
testTx
(
t
)
ctx
:=
context
.
Background
()
migrationPath
:=
filepath
.
Join
(
".."
,
".."
,
"migrations"
,
"116_auth_identity_legacy_external_safety_reports.sql"
)
migrationSQL
,
err
:=
os
.
ReadFile
(
migrationPath
)
require
.
NoError
(
t
,
err
)
_
,
err
=
tx
.
ExecContext
(
ctx
,
`
CREATE TABLE IF NOT EXISTS user_external_identities (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL,
provider TEXT NOT NULL,
provider_user_id TEXT NOT NULL,
provider_union_id TEXT NULL,
provider_username TEXT NOT NULL DEFAULT '',
display_name TEXT NOT NULL DEFAULT '',
profile_url TEXT NOT NULL DEFAULT '',
avatar_url TEXT NOT NULL DEFAULT '',
metadata TEXT NOT NULL DEFAULT '{}',
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);
TRUNCATE TABLE
auth_identity_channels,
auth_identities,
auth_identity_migration_reports,
user_external_identities,
users
RESTART IDENTITY;
`
)
require
.
NoError
(
t
,
err
)
userIDs
:=
make
([]
int64
,
0
,
8
)
for
_
,
email
:=
range
[]
string
{
"linuxdo-conflict-legacy@example.com"
,
"linuxdo-conflict-owner@example.com"
,
"wechat-conflict-legacy@example.com"
,
"wechat-conflict-owner@example.com"
,
"wechat-channel-legacy@example.com"
,
"wechat-channel-owner@example.com"
,
"linuxdo-invalid-json@example.com"
,
"wechat-openid-invalid-json@example.com"
,
}
{
var
userID
int64
require
.
NoError
(
t
,
tx
.
QueryRowContext
(
ctx
,
`
INSERT INTO users (email, password_hash, role, status, balance, concurrency)
VALUES ($1, 'hash', 'user', 'active', 0, 1)
RETURNING id`
,
email
)
.
Scan
(
&
userID
))
userIDs
=
append
(
userIDs
,
userID
)
}
linuxdoConflictLegacyUserID
:=
userIDs
[
0
]
linuxdoConflictOwnerUserID
:=
userIDs
[
1
]
wechatConflictLegacyUserID
:=
userIDs
[
2
]
wechatConflictOwnerUserID
:=
userIDs
[
3
]
wechatChannelLegacyUserID
:=
userIDs
[
4
]
wechatChannelOwnerUserID
:=
userIDs
[
5
]
linuxdoInvalidJSONUserID
:=
userIDs
[
6
]
wechatInvalidOpenIDUserID
:=
userIDs
[
7
]
require
.
NoError
(
t
,
tx
.
QueryRowContext
(
ctx
,
`
INSERT INTO auth_identities (user_id, provider_type, provider_key, provider_subject, metadata)
VALUES ($1, 'linuxdo', 'linuxdo', 'linuxdo-conflict', '{}'::jsonb)
RETURNING id`
,
linuxdoConflictOwnerUserID
)
.
Scan
(
new
(
int64
)))
require
.
NoError
(
t
,
tx
.
QueryRowContext
(
ctx
,
`
INSERT INTO auth_identities (user_id, provider_type, provider_key, provider_subject, metadata)
VALUES ($1, 'wechat', 'wechat-main', 'union-conflict', '{}'::jsonb)
RETURNING id`
,
wechatConflictOwnerUserID
)
.
Scan
(
new
(
int64
)))
var
wechatChannelOwnerIdentityID
int64
require
.
NoError
(
t
,
tx
.
QueryRowContext
(
ctx
,
`
INSERT INTO auth_identities (user_id, provider_type, provider_key, provider_subject, metadata)
VALUES ($1, 'wechat', 'wechat-main', 'union-channel-owner', '{}'::jsonb)
RETURNING id`
,
wechatChannelOwnerUserID
)
.
Scan
(
&
wechatChannelOwnerIdentityID
))
require
.
NoError
(
t
,
tx
.
QueryRowContext
(
ctx
,
`
INSERT INTO auth_identity_channels (
identity_id,
provider_type,
provider_key,
channel,
channel_app_id,
channel_subject,
metadata
)
VALUES ($1, 'wechat', 'wechat-main', 'oa', 'wx-app-conflict', 'openid-channel-conflict', '{}'::jsonb)
RETURNING id`
,
wechatChannelOwnerIdentityID
)
.
Scan
(
new
(
int64
)))
var
linuxdoConflictLegacyID
int64
require
.
NoError
(
t
,
tx
.
QueryRowContext
(
ctx
,
`
INSERT INTO user_external_identities (
user_id,
provider,
provider_user_id,
provider_union_id,
provider_username,
display_name,
metadata
) VALUES ($1, 'linuxdo', 'linuxdo-conflict', NULL, 'legacy-linuxdo', 'Legacy LinuxDo Conflict', '{"source":"legacy"}')
RETURNING id
`
,
linuxdoConflictLegacyUserID
)
.
Scan
(
&
linuxdoConflictLegacyID
))
var
wechatConflictLegacyID
int64
require
.
NoError
(
t
,
tx
.
QueryRowContext
(
ctx
,
`
INSERT INTO user_external_identities (
user_id,
provider,
provider_user_id,
provider_union_id,
provider_username,
display_name,
metadata
) VALUES ($1, 'wechat', 'openid-union-conflict', 'union-conflict', 'legacy-wechat', 'Legacy WeChat Conflict', '{"channel":"oa","appid":"wx-app-conflict-canon"}')
RETURNING id
`
,
wechatConflictLegacyUserID
)
.
Scan
(
&
wechatConflictLegacyID
))
var
wechatChannelConflictLegacyID
int64
require
.
NoError
(
t
,
tx
.
QueryRowContext
(
ctx
,
`
INSERT INTO user_external_identities (
user_id,
provider,
provider_user_id,
provider_union_id,
provider_username,
display_name,
metadata
) VALUES ($1, 'wechat', 'openid-channel-conflict', 'union-channel-legacy', 'legacy-wechat-channel', 'Legacy WeChat Channel Conflict', '{"channel":"oa","appid":"wx-app-conflict"}')
RETURNING id
`
,
wechatChannelLegacyUserID
)
.
Scan
(
&
wechatChannelConflictLegacyID
))
var
linuxdoInvalidJSONLegacyID
int64
require
.
NoError
(
t
,
tx
.
QueryRowContext
(
ctx
,
`
INSERT INTO user_external_identities (
user_id,
provider,
provider_user_id,
provider_union_id,
provider_username,
display_name,
metadata
) VALUES ($1, 'linuxdo', 'linuxdo-invalid-json', NULL, 'legacy-linuxdo-invalid', 'Legacy LinuxDo Invalid JSON', '{invalid')
RETURNING id
`
,
linuxdoInvalidJSONUserID
)
.
Scan
(
&
linuxdoInvalidJSONLegacyID
))
var
wechatInvalidOpenIDLegacyID
int64
require
.
NoError
(
t
,
tx
.
QueryRowContext
(
ctx
,
`
INSERT INTO user_external_identities (
user_id,
provider,
provider_user_id,
provider_union_id,
provider_username,
display_name,
metadata
) VALUES ($1, 'wechat', 'openid-invalid-json-only', NULL, 'legacy-wechat-invalid', 'Legacy WeChat Invalid JSON', '{still-invalid')
RETURNING id
`
,
wechatInvalidOpenIDUserID
)
.
Scan
(
&
wechatInvalidOpenIDLegacyID
))
_
,
err
=
tx
.
ExecContext
(
ctx
,
string
(
migrationSQL
))
require
.
NoError
(
t
,
err
)
var
linuxdoConflictReportCount
int
require
.
NoError
(
t
,
tx
.
QueryRowContext
(
ctx
,
`
SELECT COUNT(*)
FROM auth_identity_migration_reports
WHERE report_type = 'legacy_external_identity_conflict'
AND report_key = $1
`
,
"legacy_external_identity:"
+
strconv
.
FormatInt
(
linuxdoConflictLegacyID
,
10
))
.
Scan
(
&
linuxdoConflictReportCount
))
require
.
Equal
(
t
,
1
,
linuxdoConflictReportCount
)
var
wechatConflictReportCount
int
require
.
NoError
(
t
,
tx
.
QueryRowContext
(
ctx
,
`
SELECT COUNT(*)
FROM auth_identity_migration_reports
WHERE report_type = 'legacy_external_identity_conflict'
AND report_key = $1
`
,
"legacy_external_identity:"
+
strconv
.
FormatInt
(
wechatConflictLegacyID
,
10
))
.
Scan
(
&
wechatConflictReportCount
))
require
.
Equal
(
t
,
1
,
wechatConflictReportCount
)
var
channelConflictReportCount
int
require
.
NoError
(
t
,
tx
.
QueryRowContext
(
ctx
,
`
SELECT COUNT(*)
FROM auth_identity_migration_reports
WHERE report_type = 'legacy_external_channel_conflict'
AND report_key = $1
`
,
"legacy_external_identity:"
+
strconv
.
FormatInt
(
wechatChannelConflictLegacyID
,
10
))
.
Scan
(
&
channelConflictReportCount
))
require
.
Equal
(
t
,
1
,
channelConflictReportCount
)
var
invalidJSONReportCount
int
require
.
NoError
(
t
,
tx
.
QueryRowContext
(
ctx
,
`
SELECT COUNT(*)
FROM auth_identity_migration_reports
WHERE report_type = 'legacy_external_identity_invalid_metadata_json'
AND report_key IN ($1, $2)
`
,
"legacy_external_identity:"
+
strconv
.
FormatInt
(
linuxdoInvalidJSONLegacyID
,
10
),
"legacy_external_identity:"
+
strconv
.
FormatInt
(
wechatInvalidOpenIDLegacyID
,
10
))
.
Scan
(
&
invalidJSONReportCount
))
require
.
Equal
(
t
,
2
,
invalidJSONReportCount
)
var
linuxdoInvalidIdentityCount
int
require
.
NoError
(
t
,
tx
.
QueryRowContext
(
ctx
,
`
SELECT COUNT(*)
FROM auth_identities
WHERE user_id = $1
AND provider_type = 'linuxdo'
AND provider_key = 'linuxdo'
AND provider_subject = 'linuxdo-invalid-json'
`
,
linuxdoInvalidJSONUserID
)
.
Scan
(
&
linuxdoInvalidIdentityCount
))
require
.
Equal
(
t
,
1
,
linuxdoInvalidIdentityCount
)
var
wechatOpenIDOnlyReportCount
int
require
.
NoError
(
t
,
tx
.
QueryRowContext
(
ctx
,
`
SELECT COUNT(*)
FROM auth_identity_migration_reports
WHERE report_type = 'wechat_openid_only_requires_remediation'
AND report_key = $1
`
,
"legacy_external_identity:"
+
strconv
.
FormatInt
(
wechatInvalidOpenIDLegacyID
,
10
))
.
Scan
(
&
wechatOpenIDOnlyReportCount
))
require
.
Equal
(
t
,
1
,
wechatOpenIDOnlyReportCount
)
}
func
TestAuthIdentityLegacyExternalSafetyMigration_IsSafeWhenLegacyTableMissing
(
t
*
testing
.
T
)
{
tx
:=
testTx
(
t
)
ctx
:=
context
.
Background
()
migrationPath
:=
filepath
.
Join
(
".."
,
".."
,
"migrations"
,
"116_auth_identity_legacy_external_safety_reports.sql"
)
migrationSQL
,
err
:=
os
.
ReadFile
(
migrationPath
)
require
.
NoError
(
t
,
err
)
var
beforeCount
int
require
.
NoError
(
t
,
tx
.
QueryRowContext
(
ctx
,
`
SELECT COUNT(*)
FROM auth_identity_migration_reports
`
)
.
Scan
(
&
beforeCount
))
_
,
err
=
tx
.
ExecContext
(
ctx
,
string
(
migrationSQL
))
require
.
NoError
(
t
,
err
)
var
afterCount
int
require
.
NoError
(
t
,
tx
.
QueryRowContext
(
ctx
,
`
SELECT COUNT(*)
FROM auth_identity_migration_reports
`
)
.
Scan
(
&
afterCount
))
require
.
Equal
(
t
,
beforeCount
,
afterCount
)
...
...
backend/migrations/116_auth_identity_legacy_external_safety_reports.sql
0 → 100644
View file @
7a9488ff
CREATE
OR
REPLACE
FUNCTION
public
.
__migration_116_safe_legacy_metadata_jsonb
(
input_text
TEXT
)
RETURNS
JSONB
LANGUAGE
plpgsql
AS
$$
DECLARE
parsed
JSONB
;
BEGIN
IF
input_text
IS
NULL
OR
BTRIM
(
input_text
)
=
''
THEN
RETURN
'{}'
::
jsonb
;
END
IF
;
BEGIN
parsed
:
=
input_text
::
jsonb
;
EXCEPTION
WHEN
OTHERS
THEN
RETURN
'{}'
::
jsonb
;
END
;
IF
jsonb_typeof
(
parsed
)
=
'object'
THEN
RETURN
parsed
;
END
IF
;
RETURN
jsonb_build_object
(
'_legacy_metadata_raw_json'
,
parsed
);
END
;
$$
;
CREATE
OR
REPLACE
FUNCTION
public
.
__migration_116_is_valid_legacy_metadata_jsonb
(
input_text
TEXT
)
RETURNS
BOOLEAN
LANGUAGE
plpgsql
AS
$$
DECLARE
parsed
JSONB
;
BEGIN
IF
input_text
IS
NULL
OR
BTRIM
(
input_text
)
=
''
THEN
RETURN
TRUE
;
END
IF
;
parsed
:
=
input_text
::
jsonb
;
RETURN
TRUE
;
EXCEPTION
WHEN
OTHERS
THEN
RETURN
FALSE
;
END
;
$$
;
DO
$$
BEGIN
IF
to_regclass
(
'public.user_external_identities'
)
IS
NULL
THEN
RETURN
;
END
IF
;
EXECUTE
$
sql
$
INSERT
INTO
auth_identity_migration_reports
(
report_type
,
report_key
,
details
)
SELECT
'legacy_external_identity_invalid_metadata_json'
,
'legacy_external_identity:'
||
uei
.
id
::
text
,
jsonb_build_object
(
'legacy_identity_id'
,
uei
.
id
,
'user_id'
,
uei
.
user_id
,
'provider'
,
LOWER
(
BTRIM
(
COALESCE
(
uei
.
provider
,
''
))),
'provider_user_id'
,
BTRIM
(
COALESCE
(
uei
.
provider_user_id
,
''
)),
'provider_union_id'
,
BTRIM
(
COALESCE
(
uei
.
provider_union_id
,
''
)),
'reason'
,
'legacy metadata is not valid JSON; migration downgraded metadata to empty object'
,
'raw_metadata'
,
LEFT
(
BTRIM
(
COALESCE
(
uei
.
metadata
,
''
)),
1000
),
'migration'
,
'116_auth_identity_legacy_external_safety_reports'
)
FROM
user_external_identities
AS
uei
JOIN
users
AS
u
ON
u
.
id
=
uei
.
user_id
WHERE
u
.
deleted_at
IS
NULL
AND
BTRIM
(
COALESCE
(
uei
.
metadata
,
''
))
<>
''
AND
NOT
public
.
__migration_116_is_valid_legacy_metadata_jsonb
(
uei
.
metadata
)
ON
CONFLICT
(
report_type
,
report_key
)
DO
NOTHING
;
$
sql
$
;
EXECUTE
$
sql
$
INSERT
INTO
auth_identity_migration_reports
(
report_type
,
report_key
,
details
)
SELECT
'legacy_external_identity_conflict'
,
'legacy_external_identity:'
||
legacy
.
id
::
text
,
legacy
.
metadata_json
||
jsonb_build_object
(
'legacy_identity_id'
,
legacy
.
id
,
'legacy_user_id'
,
legacy
.
user_id
,
'existing_identity_id'
,
ai
.
id
,
'existing_user_id'
,
ai
.
user_id
,
'provider_type'
,
legacy
.
provider_type
,
'provider_key'
,
legacy
.
provider_key
,
'provider_subject'
,
legacy
.
provider_subject
,
'reason'
,
'legacy canonical identity subject already belongs to another user'
,
'migration'
,
'116_auth_identity_legacy_external_safety_reports'
)
FROM
(
SELECT
uei
.
id
,
uei
.
user_id
,
LOWER
(
BTRIM
(
COALESCE
(
uei
.
provider
,
''
)))
AS
provider_type
,
CASE
WHEN
LOWER
(
BTRIM
(
COALESCE
(
uei
.
provider
,
''
)))
=
'wechat'
THEN
'wechat-main'
ELSE
'linuxdo'
END
AS
provider_key
,
CASE
WHEN
LOWER
(
BTRIM
(
COALESCE
(
uei
.
provider
,
''
)))
=
'wechat'
THEN
BTRIM
(
COALESCE
(
uei
.
provider_union_id
,
''
))
ELSE
BTRIM
(
COALESCE
(
uei
.
provider_user_id
,
''
))
END
AS
provider_subject
,
BTRIM
(
COALESCE
(
uei
.
provider_user_id
,
''
))
AS
provider_user_id
,
BTRIM
(
COALESCE
(
uei
.
provider_union_id
,
''
))
AS
provider_union_id
,
BTRIM
(
COALESCE
(
uei
.
provider_username
,
''
))
AS
provider_username
,
BTRIM
(
COALESCE
(
uei
.
display_name
,
''
))
AS
display_name
,
public
.
__migration_116_safe_legacy_metadata_jsonb
(
uei
.
metadata
)
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
,
''
)))
IN
(
'linuxdo'
,
'wechat'
)
AND
(
(
LOWER
(
BTRIM
(
COALESCE
(
uei
.
provider
,
''
)))
=
'linuxdo'
AND
BTRIM
(
COALESCE
(
uei
.
provider_user_id
,
''
))
<>
''
)
OR
(
LOWER
(
BTRIM
(
COALESCE
(
uei
.
provider
,
''
)))
=
'wechat'
AND
BTRIM
(
COALESCE
(
uei
.
provider_union_id
,
''
))
<>
''
)
)
)
AS
legacy
JOIN
auth_identities
AS
ai
ON
ai
.
provider_type
=
legacy
.
provider_type
AND
ai
.
provider_key
=
legacy
.
provider_key
AND
ai
.
provider_subject
=
legacy
.
provider_subject
WHERE
ai
.
user_id
<>
legacy
.
user_id
ON
CONFLICT
(
report_type
,
report_key
)
DO
NOTHING
;
$
sql
$
;
EXECUTE
$
sql
$
INSERT
INTO
auth_identities
(
user_id
,
provider_type
,
provider_key
,
provider_subject
,
verified_at
,
metadata
)
SELECT
legacy
.
user_id
,
legacy
.
provider_type
,
legacy
.
provider_key
,
legacy
.
provider_subject
,
legacy
.
verified_at
,
legacy
.
metadata_json
||
jsonb_build_object
(
'legacy_identity_id'
,
legacy
.
id
,
'provider_user_id'
,
legacy
.
provider_user_id
,
'provider_union_id'
,
NULLIF
(
legacy
.
provider_union_id
,
''
),
'provider_username'
,
legacy
.
provider_username
,
'display_name'
,
legacy
.
display_name
,
'migration'
,
'116_auth_identity_legacy_external_safety_reports'
)
FROM
(
SELECT
uei
.
id
,
uei
.
user_id
,
LOWER
(
BTRIM
(
COALESCE
(
uei
.
provider
,
''
)))
AS
provider_type
,
CASE
WHEN
LOWER
(
BTRIM
(
COALESCE
(
uei
.
provider
,
''
)))
=
'wechat'
THEN
'wechat-main'
ELSE
'linuxdo'
END
AS
provider_key
,
CASE
WHEN
LOWER
(
BTRIM
(
COALESCE
(
uei
.
provider
,
''
)))
=
'wechat'
THEN
BTRIM
(
COALESCE
(
uei
.
provider_union_id
,
''
))
ELSE
BTRIM
(
COALESCE
(
uei
.
provider_user_id
,
''
))
END
AS
provider_subject
,
BTRIM
(
COALESCE
(
uei
.
provider_user_id
,
''
))
AS
provider_user_id
,
BTRIM
(
COALESCE
(
uei
.
provider_union_id
,
''
))
AS
provider_union_id
,
BTRIM
(
COALESCE
(
uei
.
provider_username
,
''
))
AS
provider_username
,
BTRIM
(
COALESCE
(
uei
.
display_name
,
''
))
AS
display_name
,
public
.
__migration_116_safe_legacy_metadata_jsonb
(
uei
.
metadata
)
AS
metadata_json
,
COALESCE
(
uei
.
updated_at
,
uei
.
created_at
,
NOW
())
AS
verified_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
,
''
)))
IN
(
'linuxdo'
,
'wechat'
)
AND
(
(
LOWER
(
BTRIM
(
COALESCE
(
uei
.
provider
,
''
)))
=
'linuxdo'
AND
BTRIM
(
COALESCE
(
uei
.
provider_user_id
,
''
))
<>
''
)
OR
(
LOWER
(
BTRIM
(
COALESCE
(
uei
.
provider
,
''
)))
=
'wechat'
AND
BTRIM
(
COALESCE
(
uei
.
provider_union_id
,
''
))
<>
''
)
)
)
AS
legacy
LEFT
JOIN
auth_identities
AS
ai
ON
ai
.
provider_type
=
legacy
.
provider_type
AND
ai
.
provider_key
=
legacy
.
provider_key
AND
ai
.
provider_subject
=
legacy
.
provider_subject
WHERE
ai
.
id
IS
NULL
ON
CONFLICT
(
provider_type
,
provider_key
,
provider_subject
)
DO
NOTHING
;
$
sql
$
;
EXECUTE
$
sql
$
INSERT
INTO
auth_identity_migration_reports
(
report_type
,
report_key
,
details
)
SELECT
'legacy_external_channel_conflict'
,
'legacy_external_identity:'
||
legacy
.
id
::
text
,
legacy
.
metadata_json
||
jsonb_build_object
(
'legacy_identity_id'
,
legacy
.
id
,
'legacy_user_id'
,
legacy
.
user_id
,
'existing_channel_id'
,
channel
.
id
,
'existing_identity_id'
,
existing_ai
.
id
,
'existing_user_id'
,
existing_ai
.
user_id
,
'provider_type'
,
'wechat'
,
'provider_key'
,
'wechat-main'
,
'provider_subject'
,
legacy
.
provider_union_id
,
'channel'
,
legacy
.
channel
,
'channel_app_id'
,
legacy
.
channel_app_id
,
'channel_subject'
,
legacy
.
provider_user_id
,
'reason'
,
'legacy channel subject already belongs to another user'
,
'migration'
,
'116_auth_identity_legacy_external_safety_reports'
)
FROM
(
SELECT
uei
.
id
,
uei
.
user_id
,
BTRIM
(
COALESCE
(
uei
.
provider_user_id
,
''
))
AS
provider_user_id
,
BTRIM
(
COALESCE
(
uei
.
provider_union_id
,
''
))
AS
provider_union_id
,
public
.
__migration_116_safe_legacy_metadata_jsonb
(
uei
.
metadata
)
AS
metadata_json
,
BTRIM
(
COALESCE
(
public
.
__migration_116_safe_legacy_metadata_jsonb
(
uei
.
metadata
)
->>
'channel'
,
''
))
AS
channel
,
BTRIM
(
COALESCE
(
public
.
__migration_116_safe_legacy_metadata_jsonb
(
uei
.
metadata
)
->>
'channel_app_id'
,
public
.
__migration_116_safe_legacy_metadata_jsonb
(
uei
.
metadata
)
->>
'appid'
,
public
.
__migration_116_safe_legacy_metadata_jsonb
(
uei
.
metadata
)
->>
'app_id'
,
''
))
AS
channel_app_id
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
,
''
))
<>
''
AND
BTRIM
(
COALESCE
(
uei
.
provider_user_id
,
''
))
<>
''
)
AS
legacy
JOIN
auth_identities
AS
legacy_ai
ON
legacy_ai
.
user_id
=
legacy
.
user_id
AND
legacy_ai
.
provider_type
=
'wechat'
AND
legacy_ai
.
provider_key
=
'wechat-main'
AND
legacy_ai
.
provider_subject
=
legacy
.
provider_union_id
JOIN
auth_identity_channels
AS
channel
ON
channel
.
provider_type
=
'wechat'
AND
channel
.
provider_key
=
'wechat-main'
AND
channel
.
channel
=
legacy
.
channel
AND
channel
.
channel_app_id
=
legacy
.
channel_app_id
AND
channel
.
channel_subject
=
legacy
.
provider_user_id
JOIN
auth_identities
AS
existing_ai
ON
existing_ai
.
id
=
channel
.
identity_id
WHERE
legacy
.
channel
<>
''
AND
legacy
.
channel_app_id
<>
''
AND
existing_ai
.
user_id
<>
legacy
.
user_id
ON
CONFLICT
(
report_type
,
report_key
)
DO
NOTHING
;
$
sql
$
;
EXECUTE
$
sql
$
INSERT
INTO
auth_identity_channels
(
identity_id
,
provider_type
,
provider_key
,
channel
,
channel_app_id
,
channel_subject
,
metadata
)
SELECT
legacy_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'
,
'116_auth_identity_legacy_external_safety_reports'
)
FROM
(
SELECT
uei
.
user_id
,
BTRIM
(
COALESCE
(
uei
.
provider_user_id
,
''
))
AS
provider_user_id
,
BTRIM
(
COALESCE
(
uei
.
provider_union_id
,
''
))
AS
provider_union_id
,
public
.
__migration_116_safe_legacy_metadata_jsonb
(
uei
.
metadata
)
AS
metadata_json
,
BTRIM
(
COALESCE
(
public
.
__migration_116_safe_legacy_metadata_jsonb
(
uei
.
metadata
)
->>
'channel'
,
''
))
AS
channel
,
BTRIM
(
COALESCE
(
public
.
__migration_116_safe_legacy_metadata_jsonb
(
uei
.
metadata
)
->>
'channel_app_id'
,
public
.
__migration_116_safe_legacy_metadata_jsonb
(
uei
.
metadata
)
->>
'appid'
,
public
.
__migration_116_safe_legacy_metadata_jsonb
(
uei
.
metadata
)
->>
'app_id'
,
''
))
AS
channel_app_id
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
,
''
))
<>
''
AND
BTRIM
(
COALESCE
(
uei
.
provider_user_id
,
''
))
<>
''
)
AS
legacy
JOIN
auth_identities
AS
legacy_ai
ON
legacy_ai
.
user_id
=
legacy
.
user_id
AND
legacy_ai
.
provider_type
=
'wechat'
AND
legacy_ai
.
provider_key
=
'wechat-main'
AND
legacy_ai
.
provider_subject
=
legacy
.
provider_union_id
LEFT
JOIN
auth_identity_channels
AS
channel
ON
channel
.
provider_type
=
'wechat'
AND
channel
.
provider_key
=
'wechat-main'
AND
channel
.
channel
=
legacy
.
channel
AND
channel
.
channel_app_id
=
legacy
.
channel_app_id
AND
channel
.
channel_subject
=
legacy
.
provider_user_id
WHERE
legacy
.
channel
<>
''
AND
legacy
.
channel_app_id
<>
''
AND
channel
.
id
IS
NULL
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'
,
'116_auth_identity_legacy_external_safety_reports'
)
FROM
(
SELECT
uei
.
id
,
uei
.
user_id
,
BTRIM
(
COALESCE
(
uei
.
provider_user_id
,
''
))
AS
provider_user_id
,
public
.
__migration_116_safe_legacy_metadata_jsonb
(
uei
.
metadata
)
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
$$
;
DROP
FUNCTION
IF
EXISTS
public
.
__migration_116_is_valid_legacy_metadata_jsonb
(
TEXT
);
DROP
FUNCTION
IF
EXISTS
public
.
__migration_116_safe_legacy_metadata_jsonb
(
TEXT
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment