92 lines
3.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package auth
import (
"context"
"database/sql"
"hyapp/pkg/appcode"
"hyapp/pkg/xerr"
authdomain "hyapp/services/user-service/internal/domain/auth"
invitedomain "hyapp/services/user-service/internal/domain/invite"
userdomain "hyapp/services/user-service/internal/domain/user"
invitestorage "hyapp/services/user-service/internal/storage/mysql/invite"
"hyapp/services/user-service/internal/storage/mysql/shared"
userstorage "hyapp/services/user-service/internal/storage/mysql/user"
)
func (r *Repository) FindThirdPartyIdentity(ctx context.Context, provider string, providerSubject string) (authdomain.ThirdPartyIdentity, error) {
var identity authdomain.ThirdPartyIdentity
err := r.db.QueryRowContext(ctx, `
SELECT app_code, user_id, provider, provider_subject, COALESCE(provider_union_id, ''), created_at_ms, updated_at_ms
FROM third_party_identities
WHERE app_code = ? AND provider = ? AND provider_subject = ?
`, appcode.FromContext(ctx), provider, providerSubject).Scan(&identity.AppCode, &identity.UserID, &identity.Provider, &identity.ProviderSubject, &identity.ProviderUnionID, &identity.CreatedAtMs, &identity.UpdatedAtMs)
if err == sql.ErrNoRows {
// 未绑定三方身份时由 service 转入注册路径。
return authdomain.ThirdPartyIdentity{}, xerr.New(xerr.NotFound, "third-party identity not found")
}
if err != nil {
return authdomain.ThirdPartyIdentity{}, err
}
return identity, nil
}
func (r *Repository) FindUserIDByRegisterDeviceID(ctx context.Context, appCode string, deviceID string) (int64, error) {
var userID int64
err := r.db.QueryRowContext(ctx, `
SELECT user_id
FROM users
WHERE app_code = ? AND register_device_id = ?
LIMIT 1
`, appcode.Normalize(appCode), deviceID).Scan(&userID)
if err == sql.ErrNoRows {
// 未查到占用者时service 才允许新三方身份走注册事务。
return 0, xerr.New(xerr.NotFound, "registered device not found")
}
if err != nil {
return 0, err
}
return userID, nil
}
// CreateThirdPartyUser 原子创建用户、默认短号、三方身份和首个 session。
func (r *Repository) CreateThirdPartyUser(ctx context.Context, user userdomain.User, identity userdomain.Identity, thirdParty authdomain.ThirdPartyIdentity, session authdomain.Session, inviteBind invitedomain.BindCommand) error {
// 三方首次登录注册必须同时写用户、默认短号、三方绑定和首个 session。
tx, err := r.db.BeginTx(ctx, nil)
if err != nil {
return err
}
defer tx.Rollback()
if err := userstorage.InsertUserIdentity(ctx, tx, user, identity); err != nil {
// 默认短号冲突由 service 重试。
return mapAuthDuplicateError(err)
}
if _, err := invitestorage.EnsurePrimaryCodeForUser(ctx, tx, user.AppCode, user.UserID, user.CreatedAtMs); err != nil {
return err
}
if _, err := invitestorage.BindRelation(ctx, tx, inviteBind); err != nil {
return err
}
_, err = tx.ExecContext(ctx, `
INSERT INTO third_party_identities (app_code, user_id, provider, provider_subject, provider_union_id, created_at_ms, updated_at_ms)
VALUES (?, ?, ?, ?, ?, ?, ?)
`, appcode.Normalize(thirdParty.AppCode), thirdParty.UserID, thirdParty.Provider, thirdParty.ProviderSubject, shared.NullableString(thirdParty.ProviderUnionID), thirdParty.CreatedAtMs, thirdParty.UpdatedAtMs)
if err != nil {
return mapAuthDuplicateError(err)
}
if err := insertSession(ctx, tx, session); err != nil {
// session 插入失败会回滚用户和三方绑定。
return err
}
return tx.Commit()
}
// RecordLoginAudit 写登录审计;调用方不会让审计失败影响主链路。