diff --git a/rpc/user/pb/user.pb.go b/rpc/user/pb/user.pb.go index 1fc020a..7debed4 100644 --- a/rpc/user/pb/user.pb.go +++ b/rpc/user/pb/user.pb.go @@ -1466,6 +1466,58 @@ func (*InfoReq) Descriptor() ([]byte, []int) { return file_user_user_proto_rawDescGZIP(), []int{22} } +type PasswordReq struct { + state protoimpl.MessageState `protogen:"open.v1"` + OldPassword string `protobuf:"bytes,1,opt,name=old_password,json=oldPassword,proto3" json:"old_password,omitempty"` + Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PasswordReq) Reset() { + *x = PasswordReq{} + mi := &file_user_user_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PasswordReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PasswordReq) ProtoMessage() {} + +func (x *PasswordReq) ProtoReflect() protoreflect.Message { + mi := &file_user_user_proto_msgTypes[23] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PasswordReq.ProtoReflect.Descriptor instead. +func (*PasswordReq) Descriptor() ([]byte, []int) { + return file_user_user_proto_rawDescGZIP(), []int{23} +} + +func (x *PasswordReq) GetOldPassword() string { + if x != nil { + return x.OldPassword + } + return "" +} + +func (x *PasswordReq) GetPassword() string { + if x != nil { + return x.Password + } + return "" +} + type ClientReq struct { state protoimpl.MessageState `protogen:"open.v1"` Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` @@ -1477,7 +1529,7 @@ type ClientReq struct { func (x *ClientReq) Reset() { *x = ClientReq{} - mi := &file_user_user_proto_msgTypes[23] + mi := &file_user_user_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1489,7 +1541,7 @@ func (x *ClientReq) String() string { func (*ClientReq) ProtoMessage() {} func (x *ClientReq) ProtoReflect() protoreflect.Message { - mi := &file_user_user_proto_msgTypes[23] + mi := &file_user_user_proto_msgTypes[24] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1502,7 +1554,7 @@ func (x *ClientReq) ProtoReflect() protoreflect.Message { // Deprecated: Use ClientReq.ProtoReflect.Descriptor instead. func (*ClientReq) Descriptor() ([]byte, []int) { - return file_user_user_proto_rawDescGZIP(), []int{23} + return file_user_user_proto_rawDescGZIP(), []int{24} } func (x *ClientReq) GetName() string { @@ -1643,14 +1695,18 @@ const file_user_user_proto_rawDesc = "" + "\x0fcredential_type\x18\t \x01(\tR\x0ecredentialType\"\"\n" + "\fGetOpenidReq\x12\x12\n" + "\x04code\x18\x01 \x01(\tR\x04code\"\t\n" + - "\aInfoReq\"V\n" + + "\aInfoReq\"L\n" + + "\vPasswordReq\x12!\n" + + "\fold_password\x18\x01 \x01(\tR\voldPassword\x12\x1a\n" + + "\bpassword\x18\x02 \x01(\tR\bpassword\"V\n" + "\tClientReq\x12\x12\n" + "\x04name\x18\x01 \x01(\tR\x04name\x12\x12\n" + "\x04type\x18\x02 \x01(\tR\x04type\x12!\n" + - "\fsubject_type\x18\x03 \x01(\rR\vsubjectType2\xe0\b\n" + + "\fsubject_type\x18\x03 \x01(\rR\vsubjectType2\xb1\t\n" + "\x04User\x12A\n" + "\x05Login\x12\x0e.user.LoginReq\x1a\x0e.user.Response\"\x18\x82\xd3\xe4\x93\x02\x12:\x01*\"\r/api/v3/login\x12C\n" + - "\x04Info\x12\r.user.InfoReq\x1a\x0e.user.Response\"\x1c\x82\xd3\xe4\x93\x02\x16:\x01*\x12\x11/api/v3/user/info\x12N\n" + + "\x04Info\x12\r.user.InfoReq\x1a\x0e.user.Response\"\x1c\x82\xd3\xe4\x93\x02\x16:\x01*\x12\x11/api/v3/user/info\x12O\n" + + "\bPassword\x12\x11.user.PasswordReq\x1a\x0e.user.Response\" \x82\xd3\xe4\x93\x02\x1a:\x01*\x1a\x15/api/v3/user/password\x12N\n" + "\tGetOpenid\x12\x12.user.GetOpenidReq\x1a\x0e.user.Response\"\x1d\x82\xd3\xe4\x93\x02\x17:\x01*\"\x12/api/v3/getuseroid\x12K\n" + "\x06Client\x12\x0f.user.ClientReq\x1a\x0e.user.Response\" \x82\xd3\xe4\x93\x02\x1a:\x01*\x12\x15/admin/v3/user/client\x12P\n" + "\tUserItems\x12\x12.user.UserItemsReq\x1a\x0e.user.Response\"\x1f\x82\xd3\xe4\x93\x02\x19:\x01*\x12\x14/admin/v3/user/items\x12S\n" + @@ -1677,7 +1733,7 @@ func file_user_user_proto_rawDescGZIP() []byte { return file_user_user_proto_rawDescData } -var file_user_user_proto_msgTypes = make([]protoimpl.MessageInfo, 24) +var file_user_user_proto_msgTypes = make([]protoimpl.MessageInfo, 25) var file_user_user_proto_goTypes = []any{ (*Response)(nil), // 0: user.Response (*LoginReq)(nil), // 1: user.LoginReq @@ -1702,40 +1758,43 @@ var file_user_user_proto_goTypes = []any{ (*InternalGetUserInfoData)(nil), // 20: user.InternalGetUserInfoData (*GetOpenidReq)(nil), // 21: user.GetOpenidReq (*InfoReq)(nil), // 22: user.InfoReq - (*ClientReq)(nil), // 23: user.ClientReq + (*PasswordReq)(nil), // 23: user.PasswordReq + (*ClientReq)(nil), // 24: user.ClientReq } var file_user_user_proto_depIdxs = []int32{ 7, // 0: user.InternalUsersByIdsData.items:type_name -> user.UserBriefItem 1, // 1: user.User.Login:input_type -> user.LoginReq 22, // 2: user.User.Info:input_type -> user.InfoReq - 21, // 3: user.User.GetOpenid:input_type -> user.GetOpenidReq - 23, // 4: user.User.Client:input_type -> user.ClientReq - 2, // 5: user.User.UserItems:input_type -> user.UserItemsReq - 3, // 6: user.User.UserStatus:input_type -> user.UserStatusReq - 4, // 7: user.User.InternalCreate:input_type -> user.InternalCreateReq - 13, // 8: user.User.InternalCheckCreate:input_type -> user.InternalCheckCreateReq - 15, // 9: user.User.InternalCheckUpdate:input_type -> user.InternalCheckUpdateReq - 17, // 10: user.User.InternalUpdate:input_type -> user.InternalUpdateReq - 6, // 11: user.User.InternalUsersByIds:input_type -> user.InternalUsersByIdsReq - 9, // 12: user.User.InternalUpdateMobile:input_type -> user.InternalUpdateMobileReq - 11, // 13: user.User.InternalRevokeBizClient:input_type -> user.InternalRevokeBizClientReq - 19, // 14: user.User.InternalGetUserInfo:input_type -> user.InternalGetUserInfoReq - 0, // 15: user.User.Login:output_type -> user.Response - 0, // 16: user.User.Info:output_type -> user.Response - 0, // 17: user.User.GetOpenid:output_type -> user.Response - 0, // 18: user.User.Client:output_type -> user.Response - 0, // 19: user.User.UserItems:output_type -> user.Response - 0, // 20: user.User.UserStatus:output_type -> user.Response - 5, // 21: user.User.InternalCreate:output_type -> user.InternalCreateData - 14, // 22: user.User.InternalCheckCreate:output_type -> user.InternalCheckCreateData - 16, // 23: user.User.InternalCheckUpdate:output_type -> user.InternalCheckUpdateData - 18, // 24: user.User.InternalUpdate:output_type -> user.InternalUpdateData - 8, // 25: user.User.InternalUsersByIds:output_type -> user.InternalUsersByIdsData - 10, // 26: user.User.InternalUpdateMobile:output_type -> user.InternalUpdateMobileData - 12, // 27: user.User.InternalRevokeBizClient:output_type -> user.InternalRevokeBizClientData - 20, // 28: user.User.InternalGetUserInfo:output_type -> user.InternalGetUserInfoData - 15, // [15:29] is the sub-list for method output_type - 1, // [1:15] is the sub-list for method input_type + 23, // 3: user.User.Password:input_type -> user.PasswordReq + 21, // 4: user.User.GetOpenid:input_type -> user.GetOpenidReq + 24, // 5: user.User.Client:input_type -> user.ClientReq + 2, // 6: user.User.UserItems:input_type -> user.UserItemsReq + 3, // 7: user.User.UserStatus:input_type -> user.UserStatusReq + 4, // 8: user.User.InternalCreate:input_type -> user.InternalCreateReq + 13, // 9: user.User.InternalCheckCreate:input_type -> user.InternalCheckCreateReq + 15, // 10: user.User.InternalCheckUpdate:input_type -> user.InternalCheckUpdateReq + 17, // 11: user.User.InternalUpdate:input_type -> user.InternalUpdateReq + 6, // 12: user.User.InternalUsersByIds:input_type -> user.InternalUsersByIdsReq + 9, // 13: user.User.InternalUpdateMobile:input_type -> user.InternalUpdateMobileReq + 11, // 14: user.User.InternalRevokeBizClient:input_type -> user.InternalRevokeBizClientReq + 19, // 15: user.User.InternalGetUserInfo:input_type -> user.InternalGetUserInfoReq + 0, // 16: user.User.Login:output_type -> user.Response + 0, // 17: user.User.Info:output_type -> user.Response + 0, // 18: user.User.Password:output_type -> user.Response + 0, // 19: user.User.GetOpenid:output_type -> user.Response + 0, // 20: user.User.Client:output_type -> user.Response + 0, // 21: user.User.UserItems:output_type -> user.Response + 0, // 22: user.User.UserStatus:output_type -> user.Response + 5, // 23: user.User.InternalCreate:output_type -> user.InternalCreateData + 14, // 24: user.User.InternalCheckCreate:output_type -> user.InternalCheckCreateData + 16, // 25: user.User.InternalCheckUpdate:output_type -> user.InternalCheckUpdateData + 18, // 26: user.User.InternalUpdate:output_type -> user.InternalUpdateData + 8, // 27: user.User.InternalUsersByIds:output_type -> user.InternalUsersByIdsData + 10, // 28: user.User.InternalUpdateMobile:output_type -> user.InternalUpdateMobileData + 12, // 29: user.User.InternalRevokeBizClient:output_type -> user.InternalRevokeBizClientData + 20, // 30: user.User.InternalGetUserInfo:output_type -> user.InternalGetUserInfoData + 16, // [16:31] is the sub-list for method output_type + 1, // [1:16] is the sub-list for method input_type 1, // [1:1] is the sub-list for extension type_name 1, // [1:1] is the sub-list for extension extendee 0, // [0:1] is the sub-list for field type_name @@ -1752,7 +1811,7 @@ func file_user_user_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_user_user_proto_rawDesc), len(file_user_user_proto_rawDesc)), NumEnums: 0, - NumMessages: 24, + NumMessages: 25, NumExtensions: 0, NumServices: 1, }, diff --git a/rpc/user/pb/user_grpc.pb.go b/rpc/user/pb/user_grpc.pb.go index c469bab..e25bc02 100644 --- a/rpc/user/pb/user_grpc.pb.go +++ b/rpc/user/pb/user_grpc.pb.go @@ -21,6 +21,7 @@ const _ = grpc.SupportPackageIsVersion9 const ( User_Login_FullMethodName = "/user.User/Login" User_Info_FullMethodName = "/user.User/Info" + User_Password_FullMethodName = "/user.User/Password" User_GetOpenid_FullMethodName = "/user.User/GetOpenid" User_Client_FullMethodName = "/user.User/Client" User_UserItems_FullMethodName = "/user.User/UserItems" @@ -41,6 +42,7 @@ const ( type UserClient interface { Login(ctx context.Context, in *LoginReq, opts ...grpc.CallOption) (*Response, error) Info(ctx context.Context, in *InfoReq, opts ...grpc.CallOption) (*Response, error) + Password(ctx context.Context, in *PasswordReq, opts ...grpc.CallOption) (*Response, error) GetOpenid(ctx context.Context, in *GetOpenidReq, opts ...grpc.CallOption) (*Response, error) Client(ctx context.Context, in *ClientReq, opts ...grpc.CallOption) (*Response, error) UserItems(ctx context.Context, in *UserItemsReq, opts ...grpc.CallOption) (*Response, error) @@ -83,6 +85,16 @@ func (c *userClient) Info(ctx context.Context, in *InfoReq, opts ...grpc.CallOpt return out, nil } +func (c *userClient) Password(ctx context.Context, in *PasswordReq, opts ...grpc.CallOption) (*Response, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Response) + err := c.cc.Invoke(ctx, User_Password_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *userClient) GetOpenid(ctx context.Context, in *GetOpenidReq, opts ...grpc.CallOption) (*Response, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(Response) @@ -209,6 +221,7 @@ func (c *userClient) InternalGetUserInfo(ctx context.Context, in *InternalGetUse type UserServer interface { Login(context.Context, *LoginReq) (*Response, error) Info(context.Context, *InfoReq) (*Response, error) + Password(context.Context, *PasswordReq) (*Response, error) GetOpenid(context.Context, *GetOpenidReq) (*Response, error) Client(context.Context, *ClientReq) (*Response, error) UserItems(context.Context, *UserItemsReq) (*Response, error) @@ -237,6 +250,9 @@ func (UnimplementedUserServer) Login(context.Context, *LoginReq) (*Response, err func (UnimplementedUserServer) Info(context.Context, *InfoReq) (*Response, error) { return nil, status.Error(codes.Unimplemented, "method Info not implemented") } +func (UnimplementedUserServer) Password(context.Context, *PasswordReq) (*Response, error) { + return nil, status.Error(codes.Unimplemented, "method Password not implemented") +} func (UnimplementedUserServer) GetOpenid(context.Context, *GetOpenidReq) (*Response, error) { return nil, status.Error(codes.Unimplemented, "method GetOpenid not implemented") } @@ -330,6 +346,24 @@ func _User_Info_Handler(srv interface{}, ctx context.Context, dec func(interface return interceptor(ctx, in, info, handler) } +func _User_Password_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PasswordReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(UserServer).Password(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: User_Password_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(UserServer).Password(ctx, req.(*PasswordReq)) + } + return interceptor(ctx, in, info, handler) +} + func _User_GetOpenid_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(GetOpenidReq) if err := dec(in); err != nil { @@ -561,6 +595,10 @@ var User_ServiceDesc = grpc.ServiceDesc{ MethodName: "Info", Handler: _User_Info_Handler, }, + { + MethodName: "Password", + Handler: _User_Password_Handler, + }, { MethodName: "GetOpenid", Handler: _User_GetOpenid_Handler, diff --git a/rpc/user/user.pb b/rpc/user/user.pb index fea0cb9..e9bdd62 100644 Binary files a/rpc/user/user.pb and b/rpc/user/user.pb differ diff --git a/rpc/user/user.proto b/rpc/user/user.proto index b7fadd8..f0cc92a 100644 --- a/rpc/user/user.proto +++ b/rpc/user/user.proto @@ -150,6 +150,11 @@ message GetOpenidReq { message InfoReq {} +message PasswordReq { + string old_password = 1; + string password = 2; +} + message ClientReq { string name = 1; string type = 2; @@ -169,6 +174,12 @@ service User { body: "*" }; } + rpc Password(PasswordReq) returns (Response) { + option (google.api.http) = { + put: "/api/v3/user/password" + body: "*" + }; + } rpc GetOpenid(GetOpenidReq) returns (Response) { option (google.api.http) = { post: "/api/v3/getuseroid" diff --git a/services/user/internal/logic/passwordLogic.go b/services/user/internal/logic/passwordLogic.go new file mode 100644 index 0000000..b26641f --- /dev/null +++ b/services/user/internal/logic/passwordLogic.go @@ -0,0 +1,122 @@ +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" +) + +type PasswordLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewPasswordLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PasswordLogic { + return &PasswordLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +func (l *PasswordLogic) Password(in *user.PasswordReq) (*user.Response, error) { + var req validator.PasswordValidator + if msg := validate.ValidateFromProto(in, &req); msg != utils.StringEmpty { + return outResponse(utils.ErrorParams, msg), nil + } + + loginUser := utils.GetUserFromCtx(l.ctx) + if loginUser.ID < utils.NumberOne { + return failResponse(utils.ErrorNoLoginInfo), nil + } + + subjectType, subjectErr := l.resolveSubjectType(loginUser) + if subjectErr != nil { + l.Errorf("password resolve subject: %v", subjectErr) + return failResponse(utils.Fail), nil + } + if subjectType == utils.StringEmpty { + return outResponse(utils.ErrorParams, "无法识别用户主体类型"), nil + } + + row, userErr := loadEnabledUser(loginUser.ID) + if userErr != nil { + l.Errorf("password load user: %v", userErr) + return failResponse(utils.ErrorNotFund), nil + } + if row.Mobile == utils.StringEmpty { + return outResponse(utils.ErrorParams, "用户未绑定手机号,无法修改密码"), nil + } + + cred, credErr := findCredential(dao.CredentialTypePassword, row.Mobile, subjectType) + if credErr != nil { + l.Errorf("password find credential: %v", credErr) + return failResponse(utils.Fail), nil + } + if cred == nil || cred.UserId != loginUser.ID { + return outResponse(utils.ErrorNotFund, "密码凭证不存在"), nil + } + if cred.Status == dao.StatusDisabled { + return outResponse(utils.Fail, "登录凭证已禁用"), nil + } + if !utils.EqualsPassword(req.OldPassword, cred.Secret) { + return failResponse(utils.ErrorPwdError), nil + } + if req.OldPassword == req.Password { + return outResponse(utils.ErrorParams, "新密码不能与原密码相同"), nil + } + + hashed, hashErr := utils.EncryptPassword(req.Password) + if hashErr != nil { + l.Errorf("password encrypt: %v", hashErr) + return failResponse(utils.ErrorEncryptAesError), nil + } + + credModel := model.UserCredentialModel{}.Init() + _, editErr := credModel.Edit(modelbase.Params{ + Eq: map[string]string{"id": strconv.FormatInt(cred.Id, utils.NumberTen)}, + }, map[string]interface{}{ + "secret": hashed, + "status": dao.StatusEnabled, + }) + if editErr != nil { + l.Errorf("password update: %v", editErr) + return failResponse(utils.Fail), nil + } + + return okResponse(nil), nil +} + +func (l *PasswordLogic) resolveSubjectType(loginUser utils.UserInfo) (string, error) { + if loginUser.ClientCode != utils.StringEmpty { + client, err := loadEnabledClient(loginUser.ClientCode) + if err != nil { + return utils.StringEmpty, err + } + if client.SubjectType != utils.StringEmpty { + return client.SubjectType, nil + } + } + + switch loginUser.Type { + case dao.TypeSale: + return dao.SubjectTypeSale, nil + case dao.TypeStore: + return dao.SubjectTypeStore, nil + case dao.TypeUser: + return dao.SubjectTypeUser, nil + default: + return utils.StringEmpty, nil + } +} diff --git a/services/user/internal/server/userServer.go b/services/user/internal/server/userServer.go index 8dfddde..e676eec 100644 --- a/services/user/internal/server/userServer.go +++ b/services/user/internal/server/userServer.go @@ -33,6 +33,11 @@ func (s *UserServer) Info(ctx context.Context, in *user.InfoReq) (*user.Response return l.Info(in) } +func (s *UserServer) Password(ctx context.Context, in *user.PasswordReq) (*user.Response, error) { + l := logic.NewPasswordLogic(ctx, s.svcCtx) + return l.Password(in) +} + func (s *UserServer) GetOpenid(ctx context.Context, in *user.GetOpenidReq) (*user.Response, error) { l := logic.NewGetOpenidLogic(ctx, s.svcCtx) return l.GetOpenid(in) diff --git a/services/user/userClient/user.go b/services/user/userClient/user.go index 91c6a0c..d52bc04 100644 --- a/services/user/userClient/user.go +++ b/services/user/userClient/user.go @@ -34,6 +34,7 @@ type ( InternalUsersByIdsData = user.InternalUsersByIdsData InternalUsersByIdsReq = user.InternalUsersByIdsReq LoginReq = user.LoginReq + PasswordReq = user.PasswordReq Response = user.Response UserBriefItem = user.UserBriefItem UserItemsReq = user.UserItemsReq @@ -42,6 +43,7 @@ type ( User interface { Login(ctx context.Context, in *LoginReq, opts ...grpc.CallOption) (*Response, error) Info(ctx context.Context, in *InfoReq, opts ...grpc.CallOption) (*Response, error) + Password(ctx context.Context, in *PasswordReq, opts ...grpc.CallOption) (*Response, error) GetOpenid(ctx context.Context, in *GetOpenidReq, opts ...grpc.CallOption) (*Response, error) Client(ctx context.Context, in *ClientReq, opts ...grpc.CallOption) (*Response, error) UserItems(ctx context.Context, in *UserItemsReq, opts ...grpc.CallOption) (*Response, error) @@ -77,6 +79,11 @@ func (m *defaultUser) Info(ctx context.Context, in *InfoReq, opts ...grpc.CallOp return client.Info(ctx, in, opts...) } +func (m *defaultUser) Password(ctx context.Context, in *PasswordReq, opts ...grpc.CallOption) (*Response, error) { + client := user.NewUserClient(m.cli.Conn()) + return client.Password(ctx, in, opts...) +} + func (m *defaultUser) GetOpenid(ctx context.Context, in *GetOpenidReq, opts ...grpc.CallOption) (*Response, error) { client := user.NewUserClient(m.cli.Conn()) return client.GetOpenid(ctx, in, opts...) diff --git a/services/user/validator/user.go b/services/user/validator/user.go index 11bea4b..b1aed2b 100644 --- a/services/user/validator/user.go +++ b/services/user/validator/user.go @@ -24,6 +24,21 @@ func (p LoginValidator) GetMessage() validate.ValidatorMessages { } } +type PasswordValidator struct { + OldPassword string `validate:"required,max=64"` + Password string `validate:"required,min=6,max=64"` +} + +func (p PasswordValidator) GetMessage() validate.ValidatorMessages { + return validate.ValidatorMessages{ + "OldPassword.required": "原密码不能为空", + "OldPassword.max": "原密码过长", + "Password.required": "新密码不能为空", + "Password.min": "新密码长度不能小于6位", + "Password.max": "新密码过长", + } +} + type GetOpenidValidator struct { Code string `validate:"required,max=128"` }