From 052425970a4de1e9bc73a36f1448b34c7d995427 Mon Sep 17 00:00:00 2001 From: zzw <1464003642@qq.com> Date: Wed, 16 Sep 2026 15:19:54 +0800 Subject: [PATCH] fix: internal user --- rpc/user/pb/user.pb.go | 59 ++++++++++++++---- rpc/user/user.pb | Bin 16591 -> 16705 bytes rpc/user/user.proto | 6 +- services/chore/internal/logic/testLogic.go | 27 ++++---- services/sale/internal/logic/createLogic.go | 59 +++++++++++++++--- services/sale/internal/logic/userIdentity.go | 23 ++++++- services/user/internal/dao/user_client.go | 1 + services/user/internal/dao/user_credential.go | 1 + services/user/internal/logic/authHelper.go | 21 ++++--- .../logic/internalCheckUpdateLogic.go | 11 +++- .../internal/logic/internalCreateLogic.go | 48 +++++++++++--- .../internal/logic/internalUpdateLogic.go | 49 ++++++++++----- .../logic/internalUpdateMobileLogic.go | 21 +++---- services/user/internal/logic/loginLogic.go | 4 +- services/user/validator/user.go | 26 +++++--- 15 files changed, 259 insertions(+), 97 deletions(-) diff --git a/rpc/user/pb/user.pb.go b/rpc/user/pb/user.pb.go index 6894390..bf9b3ad 100644 --- a/rpc/user/pb/user.pb.go +++ b/rpc/user/pb/user.pb.go @@ -289,6 +289,7 @@ type InternalCreateReq struct { CredentialType []string `protobuf:"bytes,7,rep,name=credential_type,json=credentialType,proto3" json:"credential_type,omitempty"` Identifier string `protobuf:"bytes,8,opt,name=identifier,proto3" json:"identifier,omitempty"` Secret string `protobuf:"bytes,9,opt,name=secret,proto3" json:"secret,omitempty"` + BizId int64 `protobuf:"varint,10,opt,name=biz_id,json=bizId,proto3" json:"biz_id,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -386,6 +387,13 @@ func (x *InternalCreateReq) GetSecret() string { return "" } +func (x *InternalCreateReq) GetBizId() int64 { + if x != nil { + return x.BizId + } + return 0 +} + type InternalCreateData struct { state protoimpl.MessageState `protogen:"open.v1"` UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` @@ -924,8 +932,9 @@ func (x *InternalCheckCreateData) GetResult() bool { type InternalCheckUpdateReq struct { state protoimpl.MessageState `protogen:"open.v1"` - UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + BizId int64 `protobuf:"varint,1,opt,name=biz_id,json=bizId,proto3" json:"biz_id,omitempty"` Mobile string `protobuf:"bytes,2,opt,name=mobile,proto3" json:"mobile,omitempty"` + SubjectType string `protobuf:"bytes,3,opt,name=subject_type,json=subjectType,proto3" json:"subject_type,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -960,9 +969,9 @@ func (*InternalCheckUpdateReq) Descriptor() ([]byte, []int) { return file_user_user_proto_rawDescGZIP(), []int{15} } -func (x *InternalCheckUpdateReq) GetUserId() int64 { +func (x *InternalCheckUpdateReq) GetBizId() int64 { if x != nil { - return x.UserId + return x.BizId } return 0 } @@ -974,6 +983,13 @@ func (x *InternalCheckUpdateReq) GetMobile() string { return "" } +func (x *InternalCheckUpdateReq) GetSubjectType() string { + if x != nil { + return x.SubjectType + } + return "" +} + type InternalCheckUpdateData struct { state protoimpl.MessageState `protogen:"open.v1"` Result bool `protobuf:"varint,1,opt,name=result,proto3" json:"result,omitempty"` @@ -1030,6 +1046,8 @@ type InternalUpdateReq struct { CredentialType []string `protobuf:"bytes,8,rep,name=credential_type,json=credentialType,proto3" json:"credential_type,omitempty"` Identifier string `protobuf:"bytes,9,opt,name=identifier,proto3" json:"identifier,omitempty"` Secret string `protobuf:"bytes,10,opt,name=secret,proto3" json:"secret,omitempty"` + BizId int64 `protobuf:"varint,11,opt,name=biz_id,json=bizId,proto3" json:"biz_id,omitempty"` + SubjectType string `protobuf:"bytes,12,opt,name=subject_type,json=subjectType,proto3" json:"subject_type,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -1134,6 +1152,20 @@ func (x *InternalUpdateReq) GetSecret() string { return "" } +func (x *InternalUpdateReq) GetBizId() int64 { + if x != nil { + return x.BizId + } + return 0 +} + +func (x *InternalUpdateReq) GetSubjectType() string { + if x != nil { + return x.SubjectType + } + return "" +} + type InternalUpdateData struct { state protoimpl.MessageState `protogen:"open.v1"` UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` @@ -1254,7 +1286,7 @@ const file_user_user_proto_rawDesc = "" + "\x04size\x18\x03 \x01(\x05R\x04size\"7\n" + "\rUserStatusReq\x12\x0e\n" + "\x02id\x18\x01 \x01(\x03R\x02id\x12\x16\n" + - "\x06status\x18\x02 \x01(\x05R\x06status\"\x8d\x02\n" + + "\x06status\x18\x02 \x01(\x05R\x06status\"\xa4\x02\n" + "\x11InternalCreateReq\x12\x16\n" + "\x06mobile\x18\x01 \x01(\tR\x06mobile\x12\x12\n" + "\x04name\x18\x02 \x01(\tR\x04name\x12\x16\n" + @@ -1267,7 +1299,9 @@ const file_user_user_proto_rawDesc = "" + "\n" + "identifier\x18\b \x01(\tR\n" + "identifier\x12\x16\n" + - "\x06secret\x18\t \x01(\tR\x06secret\"s\n" + + "\x06secret\x18\t \x01(\tR\x06secret\x12\x15\n" + + "\x06biz_id\x18\n" + + " \x01(\x03R\x05bizId\"s\n" + "\x12InternalCreateData\x12\x17\n" + "\auser_id\x18\x01 \x01(\x03R\x06userId\x12\x18\n" + "\acreated\x18\x02 \x01(\bR\acreated\x12\x16\n" + @@ -1300,12 +1334,13 @@ const file_user_user_proto_rawDesc = "" + "\x16InternalCheckCreateReq\x12\x16\n" + "\x06mobile\x18\x01 \x01(\tR\x06mobile\"1\n" + "\x17InternalCheckCreateData\x12\x16\n" + - "\x06result\x18\x01 \x01(\bR\x06result\"I\n" + - "\x16InternalCheckUpdateReq\x12\x17\n" + - "\auser_id\x18\x01 \x01(\x03R\x06userId\x12\x16\n" + - "\x06mobile\x18\x02 \x01(\tR\x06mobile\"1\n" + + "\x06result\x18\x01 \x01(\bR\x06result\"j\n" + + "\x16InternalCheckUpdateReq\x12\x15\n" + + "\x06biz_id\x18\x01 \x01(\x03R\x05bizId\x12\x16\n" + + "\x06mobile\x18\x02 \x01(\tR\x06mobile\x12!\n" + + "\fsubject_type\x18\x03 \x01(\tR\vsubjectType\"1\n" + "\x17InternalCheckUpdateData\x12\x16\n" + - "\x06result\x18\x01 \x01(\bR\x06result\"\xa6\x02\n" + + "\x06result\x18\x01 \x01(\bR\x06result\"\xe0\x02\n" + "\x11InternalUpdateReq\x12\x17\n" + "\auser_id\x18\x01 \x01(\x03R\x06userId\x12\x16\n" + "\x06mobile\x18\x02 \x01(\tR\x06mobile\x12\x12\n" + @@ -1320,7 +1355,9 @@ const file_user_user_proto_rawDesc = "" + "identifier\x18\t \x01(\tR\n" + "identifier\x12\x16\n" + "\x06secret\x18\n" + - " \x01(\tR\x06secret\"Y\n" + + " \x01(\tR\x06secret\x12\x15\n" + + "\x06biz_id\x18\v \x01(\x03R\x05bizId\x12!\n" + + "\fsubject_type\x18\f \x01(\tR\vsubjectType\"Y\n" + "\x12InternalUpdateData\x12\x17\n" + "\auser_id\x18\x01 \x01(\x03R\x06userId\x12\x16\n" + "\x06mobile\x18\x02 \x01(\tR\x06mobile\x12\x12\n" + diff --git a/rpc/user/user.pb b/rpc/user/user.pb index 517645cec0f34d029b04b71ede16dd5f3868502d..b8d6d0ccf869b8de4d0e54a6e9b88e588d83f749 100644 GIT binary patch delta 193 zcmX@#$at`caf6d7XfwB+A8>lvx#@nIgfZz^K6-#0unjrflZ0 zP-kY$nrvV#DS}YJ2v;%rqNS9QkRlgPacNRkYH~?@No7H*1T#>cGl&~17E)O-xx(6% g@xkVG*6NH_NH%f9&GAgZFoXx)kkrjrZGJHW09EigSO5S3 delta 65 zcmV-H0KWghf&tHg0kA?f0gJOkHMRi(jkEeT4gs?tI41)TNeUK8ZggdGZeeUgXk}w- Xlkqz`ld(HA0j9I&J0}6NM?Lxj2X+_s diff --git a/rpc/user/user.proto b/rpc/user/user.proto index bbee50a..e2946fb 100644 --- a/rpc/user/user.proto +++ b/rpc/user/user.proto @@ -41,6 +41,7 @@ message InternalCreateReq { repeated string credential_type = 7; string identifier = 8; string secret = 9; + int64 biz_id = 10; } message InternalCreateData { @@ -96,8 +97,9 @@ message InternalCheckCreateData { } message InternalCheckUpdateReq { - int64 user_id = 1; + int64 biz_id = 1; string mobile = 2; + string subject_type = 3; } message InternalCheckUpdateData { @@ -115,6 +117,8 @@ message InternalUpdateReq { repeated string credential_type = 8; string identifier = 9; string secret = 10; + int64 biz_id = 11; + string subject_type = 12; } message InternalUpdateData { diff --git a/services/chore/internal/logic/testLogic.go b/services/chore/internal/logic/testLogic.go index c2934b5..8d3d25f 100644 --- a/services/chore/internal/logic/testLogic.go +++ b/services/chore/internal/logic/testLogic.go @@ -114,20 +114,21 @@ func (l *TestLogic) Test(in *chore.TestReq) (*chore.Response, error) { // Mobile: in.GetChar(), // }) - // res, err := user.NewUserClient(cli.Conn()).InternalCheckUpdate(l.ctx, &user.InternalCheckUpdateReq{ - // UserId: int64(in.GetId()), - // Mobile: in.GetChar(), - // }) - // fmt.Println(res.GetResult()) - - res, err := user.NewUserClient(cli.Conn()).InternalCreate(l.ctx, &user.InternalCreateReq{ - Mobile: in.GetChar(), - ClientCode: []string{"user_skin", "user_o2"}, - CredentialType: []string{"password", "sms"}, - Identifier: in.GetChar(), - Secret: "123123", + res, err := user.NewUserClient(cli.Conn()).InternalCheckUpdate(l.ctx, &user.InternalCheckUpdateReq{ + BizId: int64(in.GetId()), + SubjectType: "user", + Mobile: in.GetChar(), }) - fmt.Println(res) + fmt.Println(res.GetResult()) + + // res, err := user.NewUserClient(cli.Conn()).InternalCreate(l.ctx, &user.InternalCreateReq{ + // BizId: 10086, + // Mobile: in.GetChar(), + // ClientCode: []string{"user_skin", "user_o2"}, + // CredentialType: []string{"password", "sms"}, + // Identifier: in.GetChar(), + // Secret: "123123", + // }) if err != nil { l.Errorf("XXXXXX: %v", err) return failResponse(utils.ErrorInternalServer), nil diff --git a/services/sale/internal/logic/createLogic.go b/services/sale/internal/logic/createLogic.go index 00b5db3..9c0827b 100644 --- a/services/sale/internal/logic/createLogic.go +++ b/services/sale/internal/logic/createLogic.go @@ -14,6 +14,8 @@ import ( "lone-services/services/sale/validator" "github.com/zeromicro/go-zero/core/logx" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) type CreateLogic struct { @@ -44,24 +46,29 @@ func (l *CreateLogic) Create(in *sale.CreateReq) (*sale.Response, error) { return failResponse(utils.ErrorNoLoginInfo), nil } - identity, idErr := ensureSaleIdentity(l.ctx, l.svcCtx.UserSvcName, req.Mobile, req.Password) - if idErr != nil { - l.Errorf("sale ensure identity: %v", idErr) - if msg, ok := userRPCError(idErr); ok { + if err := checkSaleIdentityCreatable(l.ctx, l.svcCtx.UserSvcName, req.Mobile); err != nil { + l.Errorf("sale check identity: %v", err) + if st, ok := status.FromError(err); ok && st.Code() == codes.AlreadyExists { + return failResponse(utils.ErrorDataIsExist), nil + } + if msg, ok := userRPCError(err); ok { return outResponse(utils.Fail, msg), nil } return failResponse(utils.Fail), nil } - if identity.GetUserId() < utils.NumberOne || identity.GetMobile() == utils.StringEmpty { - return failResponse(utils.Fail), nil + + encryptMobile, encErr := utils.EncryptPhone(req.Mobile) + if encErr != nil { + l.Errorf("sale create encrypt mobile: %v", encErr) + return failResponse(utils.ErrorEncryptAesError), nil } m := model.SaleModel{}.Init() var existing dao.SaleStatusUpdate if err := m.GetOne(modelbase.Params{ - Eq: map[string]string{"user_id": strconv.FormatInt(identity.GetUserId(), utils.NumberTen)}, + Eq: map[string]string{"mobile": encryptMobile}, }, &existing); err != nil { - l.Errorf("sale create check user_id: %v", err) + l.Errorf("sale create check mobile: %v", err) return failResponse(utils.Fail), nil } if existing.Id > utils.NumberZero { @@ -96,9 +103,9 @@ func (l *CreateLogic) Create(in *sale.CreateReq) (*sale.Response, error) { } data := dao.SaleCreate{ - UserId: identity.GetUserId(), + UserId: utils.NumberZero, SaleId: req.SaleId, - Mobile: identity.GetMobile(), + Mobile: encryptMobile, Name: req.Name, IdCardFront: req.IdCardFront, IdCardBack: req.IdCardBack, @@ -124,5 +131,37 @@ func (l *CreateLogic) Create(in *sale.CreateReq) (*sale.Response, error) { return failResponse(utils.Fail), nil } + identity, idErr := ensureSaleIdentity(l.ctx, l.svcCtx.UserSvcName, req.Mobile, req.Password, data.Id) + if idErr != nil { + l.Errorf("sale ensure identity: %v", idErr) + if _, delErr := m.Del(modelbase.Params{ + Eq: map[string]string{"id": strconv.FormatInt(data.Id, utils.NumberTen)}, + }, &dao.SaleCreate{}); delErr != nil { + l.Errorf("sale rollback after identity fail: %v", delErr) + } + if msg, ok := userRPCError(idErr); ok { + return outResponse(utils.Fail, msg), nil + } + return failResponse(utils.Fail), nil + } + if identity.GetUserId() < utils.NumberOne || identity.GetMobile() == utils.StringEmpty { + if _, delErr := m.Del(modelbase.Params{ + Eq: map[string]string{"id": strconv.FormatInt(data.Id, utils.NumberTen)}, + }, &dao.SaleCreate{}); delErr != nil { + l.Errorf("sale rollback after empty identity: %v", delErr) + } + return failResponse(utils.Fail), nil + } + + if _, err := m.Edit(modelbase.Params{ + Eq: map[string]string{"id": strconv.FormatInt(data.Id, utils.NumberTen)}, + }, map[string]interface{}{ + "user_id": identity.GetUserId(), + "mobile": identity.GetMobile(), + }); err != nil { + l.Errorf("sale bind user_id: %v", err) + return failResponse(utils.Fail), nil + } + return okResponse(nil), nil } diff --git a/services/sale/internal/logic/userIdentity.go b/services/sale/internal/logic/userIdentity.go index 0c58bac..6ec5755 100644 --- a/services/sale/internal/logic/userIdentity.go +++ b/services/sale/internal/logic/userIdentity.go @@ -7,12 +7,30 @@ import ( "lone-services/pkg/utils" userpb "lone-services/rpc/user/pb" + "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) const saleClientCode = "sale_beauty" -func ensureSaleIdentity(ctx context.Context, userSvcName, mobile, password string) (*userpb.InternalCreateData, error) { +func checkSaleIdentityCreatable(ctx context.Context, userSvcName, mobile string) error { + cli, err := rpcclient.Get(userSvcName) + if err != nil { + return err + } + res, err := userpb.NewUserClient(cli.Conn()).InternalCheckCreate(ctx, &userpb.InternalCheckCreateReq{ + Mobile: mobile, + }) + if err != nil { + return err + } + if res == nil || !res.GetResult() { + return status.Error(codes.AlreadyExists, utils.ErrorDataIsExist.Msg) + } + return nil +} + +func ensureSaleIdentity(ctx context.Context, userSvcName, mobile, password string, bizId int64) (*userpb.InternalCreateData, error) { cli, err := rpcclient.Get(userSvcName) if err != nil { return nil, err @@ -22,6 +40,7 @@ func ensureSaleIdentity(ctx context.Context, userSvcName, mobile, password strin ClientCode: []string{saleClientCode}, CredentialType: []string{"password"}, Secret: password, + BizId: bizId, }) } @@ -48,7 +67,7 @@ func revokeSaleUserClient(ctx context.Context, userSvcName string, userId int64) } func reopenSaleUserClient(ctx context.Context, userSvcName, mobile string) (*userpb.InternalCreateData, error) { - return ensureSaleIdentity(ctx, userSvcName, mobile, utils.StringEmpty) + return ensureSaleIdentity(ctx, userSvcName, mobile, utils.StringEmpty, utils.NumberZero) } func userRPCError(err error) (string, bool) { diff --git a/services/user/internal/dao/user_client.go b/services/user/internal/dao/user_client.go index fece24b..f7fb902 100644 --- a/services/user/internal/dao/user_client.go +++ b/services/user/internal/dao/user_client.go @@ -6,6 +6,7 @@ type UserClient struct { Id int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"` UserId int64 `gorm:"column:user_id" json:"user_id"` ClientCode string `gorm:"column:client_code" json:"client_code"` + BizId int64 `gorm:"column:biz_id" json:"biz_id"` Status uint8 `gorm:"column:status" json:"status"` OpenedAt utils.CustomTime `gorm:"column:opened_at" json:"opened_at"` } diff --git a/services/user/internal/dao/user_credential.go b/services/user/internal/dao/user_credential.go index 463bff0..1103869 100644 --- a/services/user/internal/dao/user_credential.go +++ b/services/user/internal/dao/user_credential.go @@ -6,6 +6,7 @@ type UserCredential struct { CredentialType string `gorm:"column:credential_type" json:"credential_type"` Identifier string `gorm:"column:identifier" json:"identifier"` Secret string `gorm:"column:secret" json:"secret"` + SubjectType string `gorm:"column:subject_type" json:"subject_type"` ExtraJson string `gorm:"column:extra_json;type:json" json:"extra_json"` Status uint8 `gorm:"column:status" json:"status"` } diff --git a/services/user/internal/logic/authHelper.go b/services/user/internal/logic/authHelper.go index e76fe68..14959ce 100644 --- a/services/user/internal/logic/authHelper.go +++ b/services/user/internal/logic/authHelper.go @@ -51,13 +51,14 @@ func loadEnabledClient(clientCode string) (*dao.Client, error) { return &client, nil } -func findCredential(credentialType, identifier string) (*dao.UserCredential, error) { +func findCredential(credentialType, identifier, subjectType string) (*dao.UserCredential, error) { var cred dao.UserCredential credModel := model.UserCredentialModel{}.Init() if err := credModel.GetOne(modelbase.Params{ Eq: map[string]string{ "credential_type": credentialType, "identifier": identifier, + "subject_type": subjectType, }, }, &cred); err != nil { return nil, err @@ -100,8 +101,8 @@ func loadEnabledUser(userId int64) (*dao.UserRow, error) { return &row, nil } -func resolveOrCreateWechatUser(ctx context.Context, db *gorm.DB, openid, unionid, clientCode string) (int64, error) { - openCred, err := findCredential(dao.CredentialTypeOpenid, openid) +func resolveOrCreateWechatUser(ctx context.Context, db *gorm.DB, openid, unionid, clientCode, subjectType string) (int64, error) { + openCred, err := findCredential(dao.CredentialTypeOpenid, openid, subjectType) if err != nil { return utils.NumberZero, err } @@ -109,7 +110,7 @@ func resolveOrCreateWechatUser(ctx context.Context, db *gorm.DB, openid, unionid if openCred.Status == dao.StatusDisabled { return utils.NumberZero, status.Error(codes.FailedPrecondition, "登录凭证已禁用") } - if err := ensureUserClient(db, openCred.UserId, clientCode); err != nil { + if err := ensureUserClient(db, openCred.UserId, clientCode, utils.NumberZero); err != nil { return utils.NumberZero, err } return openCred.UserId, nil @@ -117,7 +118,7 @@ func resolveOrCreateWechatUser(ctx context.Context, db *gorm.DB, openid, unionid var userId int64 if unionid != utils.StringEmpty { - unionCred, uErr := findCredential(dao.CredentialTypeUnionid, unionid) + unionCred, uErr := findCredential(dao.CredentialTypeUnionid, unionid, subjectType) if uErr != nil { return utils.NumberZero, uErr } @@ -140,10 +141,10 @@ func resolveOrCreateWechatUser(ctx context.Context, db *gorm.DB, openid, unionid userId = add.Id } - if err := createWechatCredentials(tx, userId, openid, unionid); err != nil { + if err := createWechatCredentials(tx, userId, openid, unionid, subjectType); err != nil { return err } - return ensureUserClient(tx, userId, clientCode) + return ensureUserClient(tx, userId, clientCode, utils.NumberZero) }) if txErr != nil { if st, ok := status.FromError(txErr); ok { @@ -154,7 +155,7 @@ func resolveOrCreateWechatUser(ctx context.Context, db *gorm.DB, openid, unionid return userId, nil } -func createWechatCredentials(tx *gorm.DB, userId int64, openid, unionid string) error { +func createWechatCredentials(tx *gorm.DB, userId int64, openid, unionid, subjectType string) error { credModel := model.UserCredentialModel{}.Init() credModel.Base = credModel.Base.WithTX(tx) @@ -163,6 +164,7 @@ func createWechatCredentials(tx *gorm.DB, userId int64, openid, unionid string) Eq: map[string]string{ "credential_type": dao.CredentialTypeOpenid, "identifier": openid, + "subject_type": subjectType, }, }, &existOpen); err != nil { return err @@ -172,6 +174,7 @@ func createWechatCredentials(tx *gorm.DB, userId int64, openid, unionid string) UserId: userId, CredentialType: dao.CredentialTypeOpenid, Identifier: openid, + SubjectType: subjectType, ExtraJson: dao.ExtraJsonEmpty, Status: dao.StatusEnabled, }); err != nil { @@ -190,6 +193,7 @@ func createWechatCredentials(tx *gorm.DB, userId int64, openid, unionid string) Eq: map[string]string{ "credential_type": dao.CredentialTypeUnionid, "identifier": unionid, + "subject_type": subjectType, }, }, &existUnion); err != nil { return err @@ -199,6 +203,7 @@ func createWechatCredentials(tx *gorm.DB, userId int64, openid, unionid string) UserId: userId, CredentialType: dao.CredentialTypeUnionid, Identifier: unionid, + SubjectType: subjectType, ExtraJson: dao.ExtraJsonEmpty, Status: dao.StatusEnabled, }) diff --git a/services/user/internal/logic/internalCheckUpdateLogic.go b/services/user/internal/logic/internalCheckUpdateLogic.go index c0cdf6f..f660de8 100644 --- a/services/user/internal/logic/internalCheckUpdateLogic.go +++ b/services/user/internal/logic/internalCheckUpdateLogic.go @@ -38,10 +38,19 @@ func (l *InternalCheckUpdateLogic) InternalCheckUpdate(in *user.InternalCheckUpd return nil, status.Error(codes.InvalidArgument, msg) } + userId, findErr := findUserIdByBiz(l.svcCtx.DB, req.BizId, req.SubjectType) + if findErr != nil { + l.Errorf("internal check update find by biz: %v", findErr) + return nil, status.Error(codes.Internal, utils.Fail.Msg) + } + if userId < utils.NumberOne { + return nil, status.Error(codes.NotFound, utils.ErrorNotFund.Msg) + } + userModel := model.UserModel{}.Init() var row dao.UserRow if err := userModel.GetOne(modelbase.Params{ - Eq: map[string]string{"id": strconv.FormatInt(req.UserId, utils.NumberTen)}, + Eq: map[string]string{"id": strconv.FormatInt(userId, utils.NumberTen)}, }, &row); err != nil { l.Errorf("internal check update get user: %v", err) return nil, status.Error(codes.Internal, utils.Fail.Msg) diff --git a/services/user/internal/logic/internalCreateLogic.go b/services/user/internal/logic/internalCreateLogic.go index 3f9e7a9..e3096d4 100644 --- a/services/user/internal/logic/internalCreateLogic.go +++ b/services/user/internal/logic/internalCreateLogic.go @@ -45,6 +45,8 @@ func (l *InternalCreateLogic) InternalCreate(in *user.InternalCreateReq) (*user. } clientModel := model.ClientModel{}.Init() + subjectTypes := make([]string, 0, len(clientCodes)) + seenSubject := make(map[string]struct{}, len(clientCodes)) for _, code := range clientCodes { var client dao.Client if err := clientModel.GetOne(modelbase.Params{ @@ -59,6 +61,13 @@ func (l *InternalCreateLogic) InternalCreate(in *user.InternalCreateReq) (*user. if client.Id < utils.NumberOne { return nil, status.Error(codes.InvalidArgument, "端配置不存在或已禁用: "+code) } + if client.SubjectType == utils.StringEmpty { + return nil, status.Error(codes.InvalidArgument, "端主体类型未配置: "+code) + } + if _, ok := seenSubject[client.SubjectType]; !ok { + seenSubject[client.SubjectType] = struct{}{} + subjectTypes = append(subjectTypes, client.SubjectType) + } } encryptMobile, encErr := utils.EncryptPhone(req.Mobile) @@ -114,14 +123,16 @@ func (l *InternalCreateLogic) InternalCreate(in *user.InternalCreateReq) (*user. created = true } - for _, credType := range credentialTypes { - if err := ensureCredential(tx, userId, credType, req.Identifier, req.Secret, encryptMobile); err != nil { - return err + for _, subjectType := range subjectTypes { + for _, credType := range credentialTypes { + if err := ensureCredential(tx, userId, credType, req.Identifier, req.Secret, encryptMobile, subjectType); err != nil { + return err + } } } for _, code := range clientCodes { - if err := ensureUserClient(tx, userId, code); err != nil { + if err := ensureUserClient(tx, userId, code, req.BizId); err != nil { return err } } @@ -143,11 +154,18 @@ func (l *InternalCreateLogic) InternalCreate(in *user.InternalCreateReq) (*user. }, nil } -func ensureCredential(tx *gorm.DB, userId int64, credentialType, identifier, secret, encryptMobile string) error { +func ensureCredential(tx *gorm.DB, userId int64, credentialType, identifier, secret, encryptMobile, subjectType string) error { + if subjectType == utils.StringEmpty { + return status.Error(codes.InvalidArgument, "主体类型不能为空") + } if identifier == utils.StringEmpty { identifier = encryptMobile - } else if credentialType != dao.CredentialTypeOpenid { - identifier, _ = utils.EncryptPhone(identifier) + } else if credentialType != dao.CredentialTypeOpenid && credentialType != dao.CredentialTypeUnionid { + encrypted, encErr := utils.EncryptPhone(identifier) + if encErr != nil { + return status.Error(codes.Internal, utils.ErrorEncryptAesError.Msg) + } + identifier = encrypted } hashedSecret := utils.StringEmpty @@ -167,6 +185,7 @@ func ensureCredential(tx *gorm.DB, userId int64, credentialType, identifier, sec Eq: map[string]string{ "credential_type": credentialType, "identifier": identifier, + "subject_type": subjectType, }, }, &exist); err != nil { return err @@ -193,12 +212,13 @@ func ensureCredential(tx *gorm.DB, userId int64, credentialType, identifier, sec CredentialType: credentialType, Identifier: identifier, Secret: hashedSecret, + SubjectType: subjectType, ExtraJson: dao.ExtraJsonEmpty, Status: dao.StatusEnabled, }) } -func ensureUserClient(tx *gorm.DB, userId int64, clientCode string) error { +func ensureUserClient(tx *gorm.DB, userId int64, clientCode string, bizId int64) error { clientModel := model.UserClientModel{}.Init() clientModel.Base = clientModel.Base.WithTX(tx) @@ -212,18 +232,26 @@ func ensureUserClient(tx *gorm.DB, userId int64, clientCode string) error { return err } if exist.Id > utils.NumberZero { - if exist.Status == dao.StatusEnabled { + updates := map[string]interface{}{} + if exist.Status != dao.StatusEnabled { + updates["status"] = dao.StatusEnabled + } + if bizId > utils.NumberZero && exist.BizId != bizId { + updates["biz_id"] = bizId + } + if len(updates) == 0 { return nil } _, err := clientModel.Edit(modelbase.Params{ Eq: map[string]string{"id": strconv.FormatInt(exist.Id, utils.NumberTen)}, - }, map[string]interface{}{"status": dao.StatusEnabled}) + }, updates) return err } return clientModel.Create(&dao.UserClient{ UserId: userId, ClientCode: clientCode, + BizId: bizId, Status: dao.StatusEnabled, OpenedAt: utils.Now(), }) diff --git a/services/user/internal/logic/internalUpdateLogic.go b/services/user/internal/logic/internalUpdateLogic.go index 70cb9fa..1f42a86 100644 --- a/services/user/internal/logic/internalUpdateLogic.go +++ b/services/user/internal/logic/internalUpdateLogic.go @@ -2,6 +2,7 @@ package logic import ( "context" + "fmt" "strconv" "lone-services/pkg/modelbase" @@ -39,10 +40,19 @@ func (l *InternalUpdateLogic) InternalUpdate(in *user.InternalUpdateReq) (*user. return nil, status.Error(codes.InvalidArgument, msg) } + userId, findErr := findUserIdByBiz(l.svcCtx.DB, req.BizId, req.SubjectType) + if findErr != nil { + l.Errorf("internal update find by biz: %v", findErr) + return nil, status.Error(codes.Internal, utils.Fail.Msg) + } + if userId < utils.NumberOne { + return nil, status.Error(codes.NotFound, utils.ErrorNotFund.Msg) + } + userModel := model.UserModel{}.Init() var row dao.UserRow if err := userModel.GetOne(modelbase.Params{ - Eq: map[string]string{"id": strconv.FormatInt(req.UserId, utils.NumberTen)}, + Eq: map[string]string{"id": strconv.FormatInt(userId, utils.NumberTen)}, }, &row); err != nil { l.Errorf("internal update get user: %v", err) return nil, status.Error(codes.Internal, utils.Fail.Msg) @@ -89,6 +99,9 @@ func (l *InternalUpdateLogic) InternalUpdate(in *user.InternalUpdateReq) (*user. if client.Id < utils.NumberOne { return nil, status.Error(codes.InvalidArgument, "端配置不存在或已禁用: "+code) } + if client.SubjectType != req.SubjectType { + return nil, status.Error(codes.InvalidArgument, "端主体类型与业务主体不一致: "+code) + } } updates := map[string]interface{}{} @@ -130,33 +143,25 @@ func (l *InternalUpdateLogic) InternalUpdate(in *user.InternalUpdateReq) (*user. if encryptMobile != oldMobile { credModel := model.UserCredentialModel{}.Init() credModel.Base = credModel.Base.WithTX(tx) - var cred dao.UserCredential - if err := credModel.GetOne(modelbase.Params{ + if _, err := credModel.Edit(modelbase.Params{ Eq: map[string]string{ - "user_id": strconv.FormatInt(row.Id, utils.NumberTen), - "credential_type": dao.CredentialTypePassword, - "identifier": oldMobile, + "user_id": strconv.FormatInt(row.Id, utils.NumberTen), + "identifier": oldMobile, + "subject_type": req.SubjectType, }, - }, &cred); err != nil { + }, map[string]interface{}{"identifier": encryptMobile}); err != nil { return err } - if cred.Id > utils.NumberZero { - if _, err := credModel.Edit(modelbase.Params{ - Eq: map[string]string{"id": strconv.FormatInt(cred.Id, utils.NumberTen)}, - }, map[string]interface{}{"identifier": encryptMobile}); err != nil { - return err - } - } } for _, credType := range credentialTypes { - if err := ensureCredential(tx, row.Id, credType, req.Identifier, req.Secret, encryptMobile); err != nil { + if err := ensureCredential(tx, row.Id, credType, req.Identifier, req.Secret, encryptMobile, req.SubjectType); err != nil { return err } } for _, code := range clientCodes { - if err := ensureUserClient(tx, row.Id, code); err != nil { + if err := ensureUserClient(tx, row.Id, code, req.BizId); err != nil { return err } } @@ -180,3 +185,15 @@ func (l *InternalUpdateLogic) InternalUpdate(in *user.InternalUpdateReq) (*user. Name: name, }, nil } + +func findUserIdByBiz(db *gorm.DB, bizId int64, subjectType string) (int64, error) { + prefix := modelbase.Prefix() + var userId int64 + err := db.Table(fmt.Sprintf("%suser_client AS uc", prefix)). + Select("uc.user_id"). + Joins(fmt.Sprintf("INNER JOIN %sclient AS c ON c.code = uc.client_code", prefix)). + Where("uc.biz_id = ? AND c.subject_type = ? AND uc.status = ?", bizId, subjectType, dao.StatusEnabled). + Limit(utils.NumberOne). + Scan(&userId).Error + return userId, err +} diff --git a/services/user/internal/logic/internalUpdateMobileLogic.go b/services/user/internal/logic/internalUpdateMobileLogic.go index 7901fe2..5a0bd5f 100644 --- a/services/user/internal/logic/internalUpdateMobileLogic.go +++ b/services/user/internal/logic/internalUpdateMobileLogic.go @@ -83,25 +83,18 @@ func (l *InternalUpdateMobileLogic) InternalUpdateMobile(in *user.InternalUpdate credModel := model.UserCredentialModel{}.Init() credModel.Base = credModel.Base.WithTX(tx) - var cred dao.UserCredential - if err := credModel.GetOne(modelbase.Params{ - Eq: map[string]string{ - "user_id": strconv.FormatInt(row.Id, utils.NumberTen), - "credential_type": dao.CredentialTypePassword, - "identifier": oldMobile, - }, - }, &cred); err != nil { - return err - } - if cred.Id < utils.NumberOne { - return nil - } _, err := credModel.Edit(modelbase.Params{ - Eq: map[string]string{"id": strconv.FormatInt(cred.Id, utils.NumberTen)}, + Eq: map[string]string{ + "user_id": strconv.FormatInt(row.Id, utils.NumberTen), + "identifier": oldMobile, + }, }, map[string]interface{}{"identifier": newEncrypt}) return err }) if txErr != nil { + if st, ok := status.FromError(txErr); ok { + return nil, st.Err() + } l.Errorf("internal update mobile tx: %v", txErr) return nil, status.Error(codes.Internal, utils.Fail.Msg) } diff --git a/services/user/internal/logic/loginLogic.go b/services/user/internal/logic/loginLogic.go index f349890..46c5c1e 100644 --- a/services/user/internal/logic/loginLogic.go +++ b/services/user/internal/logic/loginLogic.go @@ -71,7 +71,7 @@ func (l *LoginLogic) loginByOpenid(req validator.LoginValidator) (*user.Response return outResponse(utils.Fail, "微信登录失败"), nil } - userId, resolveErr := resolveOrCreateWechatUser(l.ctx, l.svcCtx.DB, session.OpenID, session.UnionID, req.ClientCode) + userId, resolveErr := resolveOrCreateWechatUser(l.ctx, l.svcCtx.DB, session.OpenID, session.UnionID, req.ClientCode, client.SubjectType) if resolveErr != nil { l.Errorf("login resolve wechat user: %v", resolveErr) if st, ok := status.FromError(resolveErr); ok { @@ -113,7 +113,7 @@ func (l *LoginLogic) loginByPassword(req validator.LoginValidator) (*user.Respon return failResponse(utils.ErrorEncryptAesError), nil } - cred, credErr := findCredential(dao.CredentialTypePassword, encryptMobile) + cred, credErr := findCredential(dao.CredentialTypePassword, encryptMobile, client.SubjectType) if credErr != nil { l.Errorf("login find credential: %v", credErr) return failResponse(utils.Fail), nil diff --git a/services/user/validator/user.go b/services/user/validator/user.go index bcffc3e..835e1f7 100644 --- a/services/user/validator/user.go +++ b/services/user/validator/user.go @@ -61,6 +61,7 @@ type InternalCreateValidator struct { CredentialType []string `validate:"omitempty,dive,oneof=password sms"` Identifier string `validate:"omitempty,max=128"` Secret string `validate:"omitempty,max=255"` + BizId int64 `validate:"omitempty,gte=0"` } func (p InternalCreateValidator) GetMessage() validate.ValidatorMessages { @@ -125,21 +126,24 @@ func (p InternalCheckCreateValidator) GetMessage() validate.ValidatorMessages { } type InternalCheckUpdateValidator struct { - UserId int64 `validate:"required,gt=0"` - Mobile string `validate:"required,max=20"` + BizId int64 `validate:"required,gt=0"` + Mobile string `validate:"required,max=20"` + SubjectType string `validate:"required,oneof=sale store user"` } func (p InternalCheckUpdateValidator) GetMessage() validate.ValidatorMessages { return validate.ValidatorMessages{ - "UserId.required": "用户ID不能为空", - "UserId.gt": "用户ID必须大于0", - "Mobile.required": "手机号不能为空", - "Mobile.max": "手机号过长", + "BizId.required": "业务用户ID不能为空", + "BizId.gt": "业务用户ID必须大于0", + "Mobile.required": "手机号不能为空", + "Mobile.max": "手机号过长", + "SubjectType.required": "主体类型不能为空", + "SubjectType.oneof": "主体类型不正确", } } type InternalUpdateValidator struct { - UserId int64 `validate:"required,gt=0"` + UserId int64 `validate:"omitempty,gte=0"` Mobile string `validate:"required,max=20"` Name string `validate:"omitempty,max=64"` Avatar string `validate:"omitempty,max=255"` @@ -149,15 +153,19 @@ type InternalUpdateValidator struct { CredentialType []string `validate:"omitempty"` Identifier string `validate:"omitempty,max=128"` Secret string `validate:"omitempty,max=255"` + BizId int64 `validate:"required,gt=0"` + SubjectType string `validate:"required,oneof=sale store user"` } func (p InternalUpdateValidator) GetMessage() validate.ValidatorMessages { return validate.ValidatorMessages{ - "UserId.required": "用户ID不能为空", - "UserId.gt": "用户ID必须大于0", "Mobile.required": "手机号不能为空", "Mobile.max": "手机号过长", "ClientCode.max": "端编码过长", "CredentialType.oneof": "凭证类型不正确", + "BizId.required": "业务用户ID不能为空", + "BizId.gt": "业务用户ID必须大于0", + "SubjectType.required": "主体类型不能为空", + "SubjectType.oneof": "主体类型不正确", } }