refactor: read user profile fields from profile table

This commit is contained in:
richjohnrambo
2026-09-21 13:44:04 +08:00
parent d398467fb9
commit 5f717c2162
9 changed files with 117 additions and 203 deletions
-90
View File
@@ -156,12 +156,6 @@ func ensureUserIdentitySchema(db *sqlx.DB) error {
if err = backfillProfileEmails(ctx, conn, usersScoped); err != nil {
return err
}
if err = backfillProfileDisplay(ctx, conn, usersScoped); err != nil {
return err
}
if err = backfillUserPublicFromProfile(ctx, conn, usersScoped); err != nil {
return err
}
}
indexName := "users_phone"
@@ -490,90 +484,6 @@ func backfillProfileEmails(ctx context.Context, conn *sqlx.Conn, usersScoped boo
return nil
}
func backfillProfileDisplay(ctx context.Context, conn *sqlx.Conn, usersScoped bool) error {
profilesScoped, err := identityColumnExists(ctx, conn, "im_user_profiles", "tenant_id")
if err != nil {
return err
}
if profilesScoped != usersScoped {
return errors.New("mysql: im_users and im_user_profiles tenant scope mismatch")
}
nicknameExpr := `COALESCE(
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(u.public,'$.display_name')), ''),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(u.public,'$.nickname')), ''),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(u.public,'$.fn')), ''),
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(u.public,'$.name')), '')
)`
avatarExpr := `COALESCE(
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(u.public,'$.avatar_file_id')), '')
)`
if usersScoped {
if _, err = conn.ExecContext(ctx, `INSERT IGNORE INTO im_user_profiles(id,tenant_id,user_id,nickname,avatar_file_id,public_account)
SELECT u.id,u.tenant_id,u.id,COALESCE(`+nicknameExpr+`,''),COALESCE(`+avatarExpr+`,''),''
FROM im_users AS u
WHERE `+nicknameExpr+` IS NOT NULL OR `+avatarExpr+` IS NOT NULL`); err != nil {
return err
}
_, err = conn.ExecContext(ctx, `UPDATE im_user_profiles AS p
JOIN im_users AS u ON u.tenant_id=p.tenant_id AND u.id=p.user_id
SET p.nickname=IF(p.nickname='' AND `+nicknameExpr+` IS NOT NULL, `+nicknameExpr+`, p.nickname),
p.avatar_file_id=IF(p.avatar_file_id='' AND `+avatarExpr+` IS NOT NULL, `+avatarExpr+`, p.avatar_file_id)
WHERE (p.nickname='' AND `+nicknameExpr+` IS NOT NULL) OR (p.avatar_file_id='' AND `+avatarExpr+` IS NOT NULL)`)
return err
}
if _, err = conn.ExecContext(ctx, `INSERT IGNORE INTO im_user_profiles(id,user_id,nickname,avatar_file_id,public_account)
SELECT u.id,u.id,COALESCE(`+nicknameExpr+`,''),COALESCE(`+avatarExpr+`,''),''
FROM im_users AS u
WHERE `+nicknameExpr+` IS NOT NULL OR `+avatarExpr+` IS NOT NULL`); err != nil {
return err
}
_, err = conn.ExecContext(ctx, `UPDATE im_user_profiles AS p
JOIN im_users AS u ON u.id=p.user_id
SET p.nickname=IF(p.nickname='' AND `+nicknameExpr+` IS NOT NULL, `+nicknameExpr+`, p.nickname),
p.avatar_file_id=IF(p.avatar_file_id='' AND `+avatarExpr+` IS NOT NULL, `+avatarExpr+`, p.avatar_file_id)
WHERE (p.nickname='' AND `+nicknameExpr+` IS NOT NULL) OR (p.avatar_file_id='' AND `+avatarExpr+` IS NOT NULL)`)
return err
}
func backfillUserPublicFromProfile(ctx context.Context, conn *sqlx.Conn, usersScoped bool) error {
profilesScoped, err := identityColumnExists(ctx, conn, "im_user_profiles", "tenant_id")
if err != nil {
return err
}
if profilesScoped != usersScoped {
return errors.New("mysql: im_users and im_user_profiles tenant scope mismatch")
}
publicDoc := "COALESCE(NULLIF(u.public,''), JSON_OBJECT())"
nicknamePatch := `u.public=JSON_SET(` + publicDoc + `,
'$.display_name',p.nickname,'$.nickname',p.nickname,'$.fn',p.nickname,'$.name',p.nickname)`
avatarPatch := `u.public=JSON_SET(` + publicDoc + `,'$.avatar_file_id',p.avatar_file_id)`
accountPatch := `u.public=JSON_SET(` + publicDoc + `,'$.public_account',p.public_account)`
join := "JOIN im_users AS u ON u.id=p.user_id"
if usersScoped {
join = "JOIN im_users AS u ON u.tenant_id=p.tenant_id AND u.id=p.user_id"
}
for _, query := range []string{
`UPDATE im_user_profiles AS p ` + join + `
SET ` + nicknamePatch + `
WHERE p.nickname<>'' AND (
COALESCE(JSON_UNQUOTE(JSON_EXTRACT(u.public,'$.display_name')),'')<>p.nickname OR
COALESCE(JSON_UNQUOTE(JSON_EXTRACT(u.public,'$.nickname')),'')<>p.nickname OR
COALESCE(JSON_UNQUOTE(JSON_EXTRACT(u.public,'$.fn')),'')<>p.nickname OR
COALESCE(JSON_UNQUOTE(JSON_EXTRACT(u.public,'$.name')),'')<>p.nickname)`,
`UPDATE im_user_profiles AS p ` + join + `
SET ` + avatarPatch + `
WHERE p.avatar_file_id<>'' AND COALESCE(JSON_UNQUOTE(JSON_EXTRACT(u.public,'$.avatar_file_id')),'')<>p.avatar_file_id`,
`UPDATE im_user_profiles AS p ` + join + `
SET ` + accountPatch + `
WHERE p.public_account<>'' AND COALESCE(JSON_UNQUOTE(JSON_EXTRACT(u.public,'$.public_account')),'')<>p.public_account`,
} {
if _, err = conn.ExecContext(ctx, query); err != nil {
return err
}
}
return nil
}
func identityCandidates(ctx context.Context, conn *sqlx.Conn, scoped bool, method string) ([]identityValue, error) {
var out []identityValue
appendQuery := func(query string, args ...any) error {