package logic import ( "context" "strconv" "lone-services/pkg/modelbase" "lone-services/pkg/utils" "lone-services/pkg/validate" user "lone-services/rpc/user/pb" "lone-services/services/user/internal/dao" "lone-services/services/user/internal/model" "lone-services/services/user/internal/svc" "lone-services/services/user/validator" "github.com/zeromicro/go-zero/core/logx" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "gorm.io/gorm" ) type EnsureBizIdentityLogic struct { ctx context.Context svcCtx *svc.ServiceContext logx.Logger } func NewEnsureBizIdentityLogic(ctx context.Context, svcCtx *svc.ServiceContext) *EnsureBizIdentityLogic { return &EnsureBizIdentityLogic{ ctx: ctx, svcCtx: svcCtx, Logger: logx.WithContext(ctx), } } func (l *EnsureBizIdentityLogic) EnsureBizIdentity(in *user.EnsureBizIdentityReq) (*user.EnsureBizIdentityData, error) { var req validator.EnsureBizIdentityValidator if msg := validate.ValidateFromProto(in, &req); msg != utils.StringEmpty { return nil, status.Error(codes.InvalidArgument, msg) } var client dao.Client clientModel := model.ClientModel{}.Init() if err := clientModel.GetOne(modelbase.Params{ Eq: map[string]string{ "code": req.ClientCode, "status": strconv.Itoa(int(dao.StatusEnabled)), }, }, &client); err != nil { l.Errorf("ensure identity client: %v", err) return nil, status.Error(codes.Internal, utils.Fail.Msg) } if client.Id < utils.NumberOne { return nil, status.Error(codes.InvalidArgument, "端配置不存在或已禁用") } encryptMobile, encErr := utils.EncryptPhone(req.Mobile) if encErr != nil { l.Errorf("ensure identity encrypt mobile: %v", encErr) return nil, status.Error(codes.Internal, utils.ErrorEncryptAesError.Msg) } var ( userId int64 created bool name = req.Name ) txErr := l.svcCtx.DB.WithContext(l.ctx).Transaction(func(tx *gorm.DB) error { userModel := model.UserModel{}.Init() userModel.Base = userModel.Base.WithTX(tx) var exist dao.UserRow if err := userModel.GetOne(modelbase.Params{ Eq: map[string]string{"mobile": encryptMobile}, }, &exist); err != nil { return err } if exist.Id > utils.NumberZero { userId = exist.Id if name == utils.StringEmpty { name = exist.Name } if exist.Status == dao.StatusDisabled { return status.Error(codes.FailedPrecondition, "用户已禁用") } } else { birthday, bErr := utils.ParseDateOnly(req.Birthday) if bErr != nil { return status.Error(codes.InvalidArgument, "生日格式不正确") } add := dao.UserCreate{ Mobile: encryptMobile, Name: req.Name, Avatar: req.Avatar, Gender: uint8(req.Gender), Birthday: birthday, Status: dao.StatusEnabled, } if err := userModel.Create(&add); err != nil { return err } userId = add.Id created = true } if req.CredentialType != utils.StringEmpty { if err := ensureCredential(tx, userId, req, encryptMobile); err != nil { return err } } return ensureUserClient(tx, userId, req.ClientCode) }) if txErr != nil { if st, ok := status.FromError(txErr); ok { return nil, st.Err() } l.Errorf("ensure identity tx: %v", txErr) return nil, status.Error(codes.Internal, utils.Fail.Msg) } return &user.EnsureBizIdentityData{ UserId: userId, Created: created, Mobile: encryptMobile, Name: name, }, nil } func ensureCredential(tx *gorm.DB, userId int64, req validator.EnsureBizIdentityValidator, encryptMobile string) error { identifier := req.Identifier if identifier == utils.StringEmpty { identifier = encryptMobile } secret := utils.StringEmpty if req.Secret != utils.StringEmpty { hashed, err := utils.EncryptPassword(req.Secret) if err != nil { return err } secret = hashed } credModel := model.UserCredentialModel{}.Init() credModel.Base = credModel.Base.WithTX(tx) var exist dao.UserCredential if err := credModel.GetOne(modelbase.Params{ Eq: map[string]string{ "credential_type": req.CredentialType, "identifier": identifier, }, }, &exist); err != nil { return err } if exist.Id > utils.NumberZero { if exist.UserId != userId { return status.Error(codes.AlreadyExists, "登录凭证已被其他用户占用") } if secret == utils.StringEmpty { return nil } _, err := credModel.Edit(modelbase.Params{ Eq: map[string]string{"id": strconv.FormatInt(exist.Id, utils.NumberTen)}, }, map[string]interface{}{ "secret": secret, "status": dao.StatusEnabled, }) return err } return credModel.Create(&dao.UserCredential{ UserId: userId, CredentialType: req.CredentialType, Identifier: identifier, Secret: secret, ExtraJson: dao.ExtraJsonEmpty, Status: dao.StatusEnabled, }) } func ensureUserClient(tx *gorm.DB, userId int64, clientCode string) error { clientModel := model.UserClientModel{}.Init() clientModel.Base = clientModel.Base.WithTX(tx) var exist dao.UserClient if err := clientModel.GetOne(modelbase.Params{ Eq: map[string]string{ "user_id": strconv.FormatInt(userId, utils.NumberTen), "client_code": clientCode, }, }, &exist); err != nil { return err } if exist.Id > utils.NumberZero { if exist.Status == dao.StatusEnabled { return nil } _, err := clientModel.Edit(modelbase.Params{ Eq: map[string]string{"id": strconv.FormatInt(exist.Id, utils.NumberTen)}, }, map[string]interface{}{"status": dao.StatusEnabled}) return err } return clientModel.Create(&dao.UserClient{ UserId: userId, ClientCode: clientCode, Status: dao.StatusEnabled, OpenedAt: utils.Now(), }) }