From 6d3c8fbc6316e0c63d23549e2ae61ee520577453 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=80=A7=E9=A9=8A?= Date: Fri, 2 Aug 2024 02:20:15 +0000 Subject: [PATCH] feat/member (#1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 建立 Member 基礎功能 接下來要做的事情還有 1. golint 2. 寫單元測試 3. 寫 readme 4. 撰寫產生mock 的指令 5. 撰寫build 指令 Co-authored-by: daniel.w Reviewed-on: https://code.30cm.net/Wanderland/ark-member/pulls/1 --- generate/protobuf/member.proto | 4 +- go.mod | 4 + internal/config/config.go | 5 +- internal/domain/const.go | 4 +- internal/lib/error/easy_func.go | 5 +- internal/lib/error/easy_func_test.go | 46 +++-- internal/lib/error/errors_test.go | 7 +- internal/lib/middleware/with_context.go | 5 +- internal/lib/required/validate.go | 45 +++- internal/lib/required/validate_option.go | 12 -- internal/logic/bind_account_logic.go | 16 +- internal/logic/bind_account_logic_test.go | 179 ++++++++++++++++ internal/logic/bind_user_info_logic.go | 69 ++++++- internal/logic/bind_user_info_logic_test.go | 164 +++++++++++++++ internal/logic/create_user_account_logic.go | 25 ++- .../logic/create_user_account_logic_test.go | 166 +++++++++++++++ internal/logic/generate_refresh_code_logic.go | 103 +++++++++- .../logic/generate_refresh_code_logic_test.go | 51 +++++ internal/logic/get_uid_by_account_logic.go | 30 ++- internal/logic/get_user_account_info_logic.go | 8 +- internal/logic/get_user_info_logic.go | 29 ++- internal/logic/list_member_logic.go | 142 ++++++++++++- internal/logic/update_status_logic.go | 29 ++- internal/logic/update_user_info_logic.go | 16 +- internal/logic/update_user_token_logic.go | 35 +++- internal/logic/verify_refresh_code_logic.go | 43 +++- internal/mock/lib/validate.go | 72 +++++++ internal/mock/model/account_model.go | 129 ++++++++++++ internal/mock/model/account_model_gen.go | 115 +++++++++++ internal/mock/model/account_to_uid_model.go | 115 +++++++++++ .../mock/model/account_to_uid_model_gen.go | 115 +++++++++++ internal/mock/model/machine_node_model.go | 115 +++++++++++ internal/mock/model/machine_node_model_gen.go | 100 +++++++++ internal/mock/model/user_table_model.go | 189 +++++++++++++++++ internal/mock/model/user_table_model_gen.go | 115 +++++++++++ internal/mock/svc/machine_node.go | 68 ++++++ internal/model/account_model.go | 20 ++ internal/model/account_to_uid_model.go | 1 + internal/model/machine_node_model.go | 8 +- internal/model/user_table_model.go | 194 ++++++++++++++++++ internal/model/user_table_model_gen.go | 11 +- internal/svc/machine_node.go | 49 +++-- internal/svc/service_context.go | 20 +- member.go | 2 +- readme.md | 2 + 45 files changed, 2552 insertions(+), 130 deletions(-) create mode 100644 internal/logic/bind_account_logic_test.go create mode 100644 internal/logic/bind_user_info_logic_test.go create mode 100644 internal/logic/create_user_account_logic_test.go create mode 100644 internal/logic/generate_refresh_code_logic_test.go create mode 100644 internal/mock/lib/validate.go create mode 100644 internal/mock/model/account_model.go create mode 100644 internal/mock/model/account_model_gen.go create mode 100644 internal/mock/model/account_to_uid_model.go create mode 100644 internal/mock/model/account_to_uid_model_gen.go create mode 100644 internal/mock/model/machine_node_model.go create mode 100644 internal/mock/model/machine_node_model_gen.go create mode 100644 internal/mock/model/user_table_model.go create mode 100644 internal/mock/model/user_table_model_gen.go create mode 100644 internal/mock/svc/machine_node.go diff --git a/generate/protobuf/member.proto b/generate/protobuf/member.proto index 9e8f18d..a70280f 100644 --- a/generate/protobuf/member.proto +++ b/generate/protobuf/member.proto @@ -95,6 +95,8 @@ message UpdateUserInfoReq { optional int64 birthday = 6; optional VerifyType verify_type = 7; optional AlarmType alarm_type = 8; + optional string role_id = 9; + optional MemberStatus status = 10; } message GetUIDByAccountReq { @@ -136,7 +138,7 @@ message VerifyRefreshCodeReq { } message UpdateStatusReq { - string account = 1; + string uid = 1; MemberStatus status = 2; } diff --git a/go.mod b/go.mod index 82f437b..c9d4de8 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module member go 1.22.3 require ( + github.com/alicebob/miniredis/v2 v2.33.0 github.com/bwmarrin/snowflake v0.3.0 github.com/go-playground/validator/v10 v10.22.0 github.com/go-sql-driver/mysql v1.8.1 @@ -10,6 +11,7 @@ require ( github.com/stretchr/testify v1.9.0 github.com/zeromicro/go-zero v1.6.6 go.uber.org/goleak v1.2.1 + go.uber.org/mock v0.4.0 golang.org/x/crypto v0.24.0 google.golang.org/grpc v1.65.0 google.golang.org/protobuf v1.34.2 @@ -17,6 +19,7 @@ require ( require ( filippo.io/edwards25519 v1.1.0 // indirect + github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect @@ -60,6 +63,7 @@ require ( github.com/prometheus/procfs v0.12.0 // indirect github.com/redis/go-redis/v9 v9.5.3 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect + github.com/yuin/gopher-lua v1.1.1 // indirect go.etcd.io/etcd/api/v3 v3.5.14 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.14 // indirect go.etcd.io/etcd/client/v3 v3.5.14 // indirect diff --git a/internal/config/config.go b/internal/config/config.go index c1927ff..25bb788 100755 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -2,6 +2,7 @@ package config import ( "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/redis" "github.com/zeromicro/go-zero/zrpc" ) @@ -11,9 +12,9 @@ type Config struct { DB struct { DsnString string } - Cache cache.CacheConf - + Cache cache.CacheConf Bcrypt struct { Cost int } + RedisCluster redis.RedisConf } diff --git a/internal/domain/const.go b/internal/domain/const.go index c5725b7..b67307b 100644 --- a/internal/domain/const.go +++ b/internal/domain/const.go @@ -1,5 +1,7 @@ package domain const ( - Scope = 10 + DefaultPageSize = 100 + DefaultPageIndex = 0 + Scope = 10 ) diff --git a/internal/lib/error/easy_func.go b/internal/lib/error/easy_func.go index a0f802b..f85d4db 100644 --- a/internal/lib/error/easy_func.go +++ b/internal/lib/error/easy_func.go @@ -3,12 +3,13 @@ package error import ( "errors" "fmt" + "member/internal/lib/error/code" + "strings" + "github.com/zeromicro/go-zero/core/logx" _ "github.com/zeromicro/go-zero/core/logx" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - "member/internal/lib/error/code" - "strings" ) func newErr(scope, detail uint32, msg string) *Err { diff --git a/internal/lib/error/easy_func_test.go b/internal/lib/error/easy_func_test.go index f92e680..5ff951c 100644 --- a/internal/lib/error/easy_func_test.go +++ b/internal/lib/error/easy_func_test.go @@ -4,15 +4,16 @@ import ( "context" "errors" "fmt" + "member/internal/lib/error/code" + "reflect" + "strconv" + "testing" + "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "github.com/zeromicro/go-zero/core/logx" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - "member/internal/lib/error/code" - "reflect" - "strconv" - "testing" ) func TestFromGRPCError_GivenStatusWithCodeAndMessage_ShouldReturnErr(t *testing.T) { @@ -398,7 +399,7 @@ func TestXBCInternal_WithStrings_ShouldHasCatResource_DetailCodeXBCInternal(t *t }() // act - e := XBCInternal("field A", "Error description") + e := ArkInternal("field A", "Error description") // assert assert.Equal(t, code.CatArk, e.Category()) @@ -816,7 +817,10 @@ func TestStructErr_WithInternalErr_ShouldIsFuncReportCorrectly(t *testing.T) { // act with error chain: InvalidFormat -> layer 2 err -> layer 1 err e := InvalidFormat("field A", "Error description") - e.Wrap(layer2Err) + err := e.Wrap(layer2Err) + if err != nil { + t.Fatalf("Failed to wrap error: %v", err) + } // assert assert.Equal(t, code.CatInput, e.Category()) @@ -839,7 +843,10 @@ func TestStructErr_WithInternalErr_ShouldErrorOutputChainErrMessage(t *testing.T layer1Err := fmt.Errorf("layer 1 error") // act with error chain: InvalidFormat -> layer 1 err e := InvalidFormat("field A", "Error description") - e.Wrap(layer1Err) + err := e.Wrap(layer1Err) + if err != nil { + t.Fatalf("Failed to wrap error: %v", err) + } // assert assert.Equal(t, "invalid format: field A Error description: layer 1 error", e.Error()) @@ -864,7 +871,10 @@ func TestStructErr_WithInternalErr_ShouldAsFuncReportCorrectly(t *testing.T) { // act with error chain: InvalidFormat -> layer 2 err -> testErr e := InvalidFormat("field A", "Error description") - e.Wrap(layer2Err) + err := e.Wrap(layer2Err) + if err != nil { + t.Fatalf("Failed to wrap error: %v", err) + } // assert assert.Equal(t, code.CatInput, e.Category()) @@ -905,7 +915,10 @@ func Benchmark_ErrorsIs_TwoLayerError(b *testing.B) { // act with error chain: InvalidFormat(layer 2) -> testErr(layer 1) layer2Err := InvalidFormat("field A", "Error description") - layer2Err.Wrap(layer1Err) + err := layer2Err.Wrap(layer1Err) + if err != nil { + b.Fatalf("Failed to wrap error: %v", err) + } b.ReportAllocs() b.ResetTimer() @@ -920,7 +933,10 @@ func Benchmark_ErrorsIs_FourLayerError(b *testing.B) { layer3Err := fmt.Errorf("layer 3: %w", layer2Err) // act with error chain: InvalidFormat(layer 4) -> Error(layer 3) -> Error(layer 2) -> testErr(layer 1) layer4Err := InvalidFormat("field A", "Error description") - layer4Err.Wrap(layer3Err) + err := layer4Err.Wrap(layer3Err) + if err != nil { + b.Fatalf("Failed to wrap error: %v", err) + } b.ReportAllocs() b.ResetTimer() @@ -946,7 +962,10 @@ func Benchmark_ErrorsAs_TwoLayerError(b *testing.B) { // act with error chain: InvalidFormat(layer 2) -> testErr(layer 1) layer2Err := InvalidFormat("field A", "Error description") - layer2Err.Wrap(layer1Err) + err := layer2Err.Wrap(layer1Err) + if err != nil { + b.Fatalf("Failed to wrap error: %v", err) + } b.ReportAllocs() b.ResetTimer() @@ -962,7 +981,10 @@ func Benchmark_ErrorsAs_FourLayerError(b *testing.B) { layer3Err := fmt.Errorf("layer 3: %w", layer2Err) // act with error chain: InvalidFormat(layer 4) -> Error(layer 3) -> Error(layer 2) -> testErr(layer 1) layer4Err := InvalidFormat("field A", "Error description") - layer4Err.Wrap(layer3Err) + err := layer4Err.Wrap(layer3Err) + if err != nil { + b.Fatalf("Failed to wrap error: %v", err) + } b.ReportAllocs() b.ResetTimer() diff --git a/internal/lib/error/errors_test.go b/internal/lib/error/errors_test.go index 33c1625..a0f5325 100644 --- a/internal/lib/error/errors_test.go +++ b/internal/lib/error/errors_test.go @@ -3,12 +3,13 @@ package error import ( "errors" "fmt" - "github.com/stretchr/testify/assert" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" "member/internal/lib/error/code" "net/http" "testing" + + "github.com/stretchr/testify/assert" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) func TestCode_GivenNilReceiver_CodeReturnOK_CodeStrReturns00000(t *testing.T) { diff --git a/internal/lib/middleware/with_context.go b/internal/lib/middleware/with_context.go index 65f21b1..66ba484 100644 --- a/internal/lib/middleware/with_context.go +++ b/internal/lib/middleware/with_context.go @@ -3,10 +3,11 @@ package middleware import ( "context" "errors" - "github.com/zeromicro/go-zero/core/logx" - "google.golang.org/grpc" ers "member/internal/lib/error" "time" + + "github.com/zeromicro/go-zero/core/logx" + "google.golang.org/grpc" ) const defaultTimeout = 30 * time.Second diff --git a/internal/lib/required/validate.go b/internal/lib/required/validate.go index f21031c..6fe9a11 100644 --- a/internal/lib/required/validate.go +++ b/internal/lib/required/validate.go @@ -1,10 +1,25 @@ package required -import "github.com/go-playground/validator/v10" +import ( + "fmt" + + "github.com/zeromicro/go-zero/core/logx" + + "github.com/go-playground/validator/v10" +) + +type Validate interface { + ValidateAll(obj any) error + BindToValidator(opts ...Option) error +} + +type Validator struct { + V *validator.Validate +} // ValidateAll TODO 要移到common 包 -func ValidateAll(validate *validator.Validate, obj any) error { - err := validate.Struct(obj) +func (v *Validator) ValidateAll(obj any) error { + err := v.V.Struct(obj) if err != nil { return err } @@ -12,12 +27,24 @@ func ValidateAll(validate *validator.Validate, obj any) error { return nil } -func MustValidator(option ...Option) *validator.Validate { - // TODO Validator 要抽出來 - v := validator.New() - err := BindToValidator(v, option...) - if err != nil { - // log +func (v *Validator) BindToValidator(opts ...Option) error { + for _, item := range opts { + err := v.V.RegisterValidation(item.ValidatorName, item.ValidatorFunc) + if err != nil { + return fmt.Errorf("failed to register validator : %w", err) + } + } + + return nil +} + +func MustValidator(option ...Option) Validate { + v := &Validator{ + V: validator.New(), + } + + if err := v.BindToValidator(option...); err != nil { + logx.Error("failed to bind validator") } return v diff --git a/internal/lib/required/validate_option.go b/internal/lib/required/validate_option.go index 24851ab..8a896cb 100644 --- a/internal/lib/required/validate_option.go +++ b/internal/lib/required/validate_option.go @@ -1,7 +1,6 @@ package required import ( - "fmt" "regexp" "github.com/go-playground/validator/v10" @@ -12,17 +11,6 @@ type Option struct { ValidatorFunc func(fl validator.FieldLevel) bool } -func BindToValidator(v *validator.Validate, opts ...Option) error { - for _, item := range opts { - err := v.RegisterValidation(item.ValidatorName, item.ValidatorFunc) - if err != nil { - return fmt.Errorf("failed to register validator : %w", err) - } - } - - return nil -} - // WithAccount 創建一個新的 Option 結構,包含自定義的驗證函數,用於驗證 email 和台灣的手機號碼格式 func WithAccount(tagName string) Option { return Option{ diff --git a/internal/logic/bind_account_logic.go b/internal/logic/bind_account_logic.go index 9eaff7e..5d800c2 100644 --- a/internal/logic/bind_account_logic.go +++ b/internal/logic/bind_account_logic.go @@ -5,7 +5,6 @@ import ( "fmt" "member/internal/domain" ers "member/internal/lib/error" - "member/internal/lib/required" "member/internal/model" "strconv" @@ -37,29 +36,26 @@ type bindLoginUserReq struct { // BindAccount 綁定帳號 -> account bind to UID func (l *BindAccountLogic) BindAccount(in *member.BindingUserReq) (*member.Response, error) { // 驗證資料 - err := required.ValidateAll(l.svcCtx.Validate, &bindLoginUserReq{ + if err := l.svcCtx.Validate.ValidateAll(&bindLoginUserReq{ Account: in.GetLoginId(), - }) - if err != nil { + }); err != nil { return nil, ers.InvalidFormat(err.Error()) } uid := in.GetUid() - // 有UID 綁看看,沒帶UID 近來,確認沒重複就直接綁一個給他 + // 有 UID 綁看看,沒帶UID 近來,確認沒重複就直接綁一個給他 if in.GetUid() == "" { uid = strconv.FormatInt(int64(l.svcCtx.SnackFlowGen.Generate()), 10) } // 先確定有這個Account - _, err = l.svcCtx.AccountModel.FindOneByAccount(l.ctx, in.GetLoginId()) - if err != nil { + if _, err := l.svcCtx.AccountModel.FindOneByAccount(l.ctx, in.GetLoginId()); err != nil { return nil, ers.ResourceNotFound(fmt.Sprintf("failed to get account : %s ", in.GetLoginId())) } - _, err = l.svcCtx.AccountToUidModel.Insert(l.ctx, &model.AccountToUid{ + if _, err := l.svcCtx.AccountToUidModel.Insert(l.ctx, &model.AccountToUid{ Account: in.LoginId, Uid: uid, - }) - if err != nil { + }); err != nil { return nil, ers.DBError(err.Error()) } diff --git a/internal/logic/bind_account_logic_test.go b/internal/logic/bind_account_logic_test.go new file mode 100644 index 0000000..c7bbccf --- /dev/null +++ b/internal/logic/bind_account_logic_test.go @@ -0,0 +1,179 @@ +package logic + +import ( + "context" + "errors" + "fmt" + "member/gen_result/pb/member" + "member/internal/domain" + libMock "member/internal/mock/lib" + modelMock "member/internal/mock/model" + svcMock "member/internal/mock/svc" + "member/internal/model" + "member/internal/svc" + "testing" + + "github.com/alicebob/miniredis/v2" + "github.com/bwmarrin/snowflake" + "github.com/stretchr/testify/assert" + "github.com/zeromicro/go-zero/core/stores/redis" + "go.uber.org/mock/gomock" +) + +func TestBindAccountLogic_BindAccount(t *testing.T) { + // mock + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockAccountModel := modelMock.NewMockAccountModel(ctrl) + mockAccountToUidModel := modelMock.NewMockAccountToUidModel(ctrl) + mockSnackFlow := svcMock.NewMockSnackFlow(ctrl) + mockValidate := libMock.NewMockValidate(ctrl) + + r1, err := miniredis.Run() + assert.NoError(t, err) + defer r1.Close() + + newRedis, err := redis.NewRedis(redis.RedisConf{ + Host: r1.Addr(), + Type: redis.ClusterType, + Pass: "", + }) + assert.NoError(t, err) + + sc := svc.ServiceContext{ + AccountModel: mockAccountModel, + AccountToUidModel: mockAccountToUidModel, + SnackFlowGen: mockSnackFlow, + Redis: *newRedis, + Validate: mockValidate, + } + + l := NewBindAccountLogic(context.Background(), &sc) + + tests := []struct { + name string + input *member.BindingUserReq + setupMocks func() + expectError bool + expected *member.Response + }{ + { + name: "ok", + input: &member.BindingUserReq{ + LoginId: "cat1@30cm.net", + Uid: "12345", + }, + setupMocks: func() { + // mock validate returns + mockValidate.EXPECT(). + ValidateAll(gomock.Any()).Return(nil) + mockAccountModel.EXPECT(). + FindOneByAccount(gomock.Any(), "cat1@30cm.net"). + Return(&model.Account{Account: "cat1@30cm.net"}, nil) + + mockAccountToUidModel.EXPECT(). + Insert(gomock.Any(), gomock.Any()). + Return(nil, nil) + }, + expectError: false, + expected: &member.Response{ + Status: &member.BaseResp{ + Code: domain.CodeOk.ToString(), + Message: "success", + Error: "", + }, + }, + }, + { + name: "valid account without UID", + input: &member.BindingUserReq{ + LoginId: "cat1@30cm.net", + Uid: "", + }, + setupMocks: func() { + // mock validate returns + mockValidate.EXPECT(). + ValidateAll(gomock.Any()).Return(nil) + mockAccountModel.EXPECT(). + FindOneByAccount(gomock.Any(), "cat1@30cm.net"). + Return(&model.Account{Account: "cat1@30cm.net"}, nil) + mockSnackFlow.EXPECT(). + Generate(). + Return(snowflake.ID(202408013345678)) + mockAccountToUidModel.EXPECT(). + Insert(gomock.Any(), &model.AccountToUid{Account: "cat1@30cm.net", Uid: "202408013345678"}). + Return(nil, nil) + }, + expectError: false, + expected: &member.Response{ + Status: &member.BaseResp{ + Code: domain.CodeOk.ToString(), + Message: "success", + Error: "", + }, + }, + }, + { + name: "account not found", + input: &member.BindingUserReq{ + LoginId: "cat2@30cm.net", + Uid: "12345", + }, + setupMocks: func() { + // mock validate returns + mockValidate.EXPECT(). + ValidateAll(gomock.Any()).Return(nil) + mockAccountModel.EXPECT(). + FindOneByAccount(gomock.Any(), "cat2@30cm.net"). + Return(nil, errors.New("account not found")) + }, + expectError: true, + }, + { + name: "insert account to UID failed", + input: &member.BindingUserReq{ + LoginId: "cat2@30cm.net", + Uid: "202408013345679", + }, + setupMocks: func() { + // mock validate returns + mockValidate.EXPECT(). + ValidateAll(gomock.Any()).Return(nil) + mockAccountModel.EXPECT(). + FindOneByAccount(gomock.Any(), "cat2@30cm.net"). + Return(&model.Account{Account: "cat2@30cm.net"}, nil) + mockAccountToUidModel.EXPECT(). + Insert(gomock.Any(), &model.AccountToUid{Account: "cat2@30cm.net", Uid: "202408013345679"}). + Return(nil, errors.New("insert failed")) + }, + expectError: true, + }, + { + name: "failed to validate param", + input: &member.BindingUserReq{ + LoginId: "cat3", + Uid: "202408013345679", + }, + setupMocks: func() { + // mock validate returns + mockValidate.EXPECT(). + ValidateAll(gomock.Any()).Return(fmt.Errorf("invalid format: failed to get correct formate loginID ")) + }, + expectError: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.setupMocks() + + resp, err := l.BindAccount(tt.input) + if tt.expectError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, tt.expected, resp) + } + }) + } +} diff --git a/internal/logic/bind_user_info_logic.go b/internal/logic/bind_user_info_logic.go index ac5f39d..ff2f32b 100644 --- a/internal/logic/bind_user_info_logic.go +++ b/internal/logic/bind_user_info_logic.go @@ -2,6 +2,13 @@ package logic import ( "context" + "errors" + "member/internal/domain" + ers "member/internal/lib/error" + "member/internal/model" + "time" + + "github.com/go-sql-driver/mysql" "member/gen_result/pb/member" "member/internal/svc" @@ -23,9 +30,67 @@ func NewBindUserInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Bind } } +type createUserInfo struct { + Uid string `validate:"required"` + VerifyType int32 `validate:"required,oneof=0 1 2 3"` + AlarmType int32 `validate:"required,oneof=0 1 2"` + Status int32 `validate:"required,oneof=1 2 3 4 5 6"` + RoleId string `validate:"required"` + Language string `validate:"required"` + Currency string `validate:"required"` + NickName string + Gender int8 + Birthday int64 +} + // BindUserInfo 初次,綁定 User Info func (l *BindUserInfoLogic) BindUserInfo(in *member.CreateUserInfoReq) (*member.Response, error) { - // todo: add your logic here and delete this line + // 驗證資料 + if err := l.svcCtx.Validate.ValidateAll(&createUserInfo{ + Uid: in.GetUid(), + VerifyType: int32(in.GetVerifyType()), + AlarmType: int32(in.GetAlarmType()), + Status: int32(in.GetStatus()), + RoleId: in.GetRoleId(), + Language: in.GetLanguage(), + Currency: in.GetCurrency(), + NickName: in.GetNickName(), + Gender: int8(in.GetGender()), + Birthday: in.GetBirthday(), + }); err != nil { + return nil, ers.InvalidFormat(err.Error()) + } - return &member.Response{}, nil + now := time.Now().UTC().Unix() + if _, err := l.svcCtx.UserModel.Insert(l.ctx, &model.UserTable{ + Uid: in.GetUid(), + VerifyType: int64(in.GetVerifyType()), + AlarmType: int64(in.GetAlarmType()), + Status: int64(in.GetStatus()), + RoleId: in.GetRoleId(), + Language: in.GetLanguage(), + Currency: in.GetCurrency(), + NickName: in.GetNickName(), + Gender: int64(in.GetGender()), + Birthday: in.GetBirthday(), + CreateTime: now, + UpdateTime: now, + }); err != nil { + // 新增進去 + var mysqlErr *mysql.MySQLError + if errors.As(err, &mysqlErr) && mysqlErr.Number == 1062 { + // 處理重複條目錯誤 + return nil, ers.DBDuplicate(in.GetUid()) + } + + return nil, ers.DBError(err.Error()) + } + + return &member.Response{ + Status: &member.BaseResp{ + Code: domain.CodeOk.ToString(), + Message: "success", + Error: "", + }, + }, nil } diff --git a/internal/logic/bind_user_info_logic_test.go b/internal/logic/bind_user_info_logic_test.go new file mode 100644 index 0000000..d768149 --- /dev/null +++ b/internal/logic/bind_user_info_logic_test.go @@ -0,0 +1,164 @@ +package logic + +import ( + "context" + "fmt" + "member/gen_result/pb/member" + "member/internal/domain" + libMock "member/internal/mock/lib" + modelMock "member/internal/mock/model" + svcMock "member/internal/mock/svc" + "member/internal/svc" + "testing" + + "github.com/alicebob/miniredis/v2" + "github.com/go-sql-driver/mysql" + "github.com/stretchr/testify/assert" + "github.com/zeromicro/go-zero/core/stores/redis" + "go.uber.org/mock/gomock" + "google.golang.org/protobuf/proto" +) + +func TestBindUserInfoLogic_BindUserInfo(t *testing.T) { + // mock + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockUserModel := modelMock.NewMockUserTableModel(ctrl) + + mockSnackFlow := svcMock.NewMockSnackFlow(ctrl) + mockValidate := libMock.NewMockValidate(ctrl) + + r1, err := miniredis.Run() + assert.NoError(t, err) + defer r1.Close() + + newRedis, err := redis.NewRedis(redis.RedisConf{ + Host: r1.Addr(), + Type: redis.ClusterType, + Pass: "", + }) + assert.NoError(t, err) + + sc := svc.ServiceContext{ + UserModel: mockUserModel, + SnackFlowGen: mockSnackFlow, + Redis: *newRedis, + Validate: mockValidate, + } + + l := NewBindUserInfoLogic(context.Background(), &sc) + + tests := []struct { + name string + input *member.CreateUserInfoReq + setupMocks func() + expectError bool + expected *member.Response + }{ + { + name: "ok", + input: &member.CreateUserInfoReq{ + Uid: "2024101598765", + VerifyType: 1, + AlarmType: 2, + Status: 3, + RoleId: "cat_01", + Language: "en", + Currency: "USDT", + NickName: proto.String("Test User"), + Gender: proto.Uint32(1), + Birthday: proto.Int64(1722327098), + }, + setupMocks: func() { + mockValidate.EXPECT(). + ValidateAll(gomock.Any()). + Return(nil) + mockUserModel.EXPECT(). + Insert(gomock.Any(), gomock.Any()). + Return(nil, nil) + }, + expectError: false, + expected: &member.Response{ + Status: &member.BaseResp{ + Code: domain.CodeOk.ToString(), + Message: "success", + Error: "", + }, + }, + }, + { + name: "invalid user info", + input: &member.CreateUserInfoReq{ + Uid: "", + }, + setupMocks: func() { + mockValidate.EXPECT(). + ValidateAll(gomock.Any()). + Return(fmt.Errorf("validation error")) + }, + expectError: true, + }, + { + name: "duplicate entry", + input: &member.CreateUserInfoReq{ + Uid: "test_uid", + VerifyType: 1, + AlarmType: 2, + Status: 3, + RoleId: "test_role", + Language: "en", + Currency: "USD", + NickName: proto.String("Test User"), + Gender: proto.Uint32(1), + Birthday: proto.Int64(1622517800), + }, + setupMocks: func() { + mockValidate.EXPECT(). + ValidateAll(gomock.Any()). + Return(nil) + mockUserModel.EXPECT(). + Insert(gomock.Any(), gomock.Any()). + Return(nil, &mysql.MySQLError{Number: 1062, Message: "Duplicate entry"}) + }, + expectError: true, + }, + { + name: "database error", + input: &member.CreateUserInfoReq{ + Uid: "test_uid", + VerifyType: 1, + AlarmType: 2, + Status: 3, + RoleId: "test_role", + Language: "en", + Currency: "USD", + NickName: proto.String("Test User"), + Gender: proto.Uint32(1), + Birthday: proto.Int64(1622517800), + }, + setupMocks: func() { + mockValidate.EXPECT(). + ValidateAll(gomock.Any()). + Return(nil) + mockUserModel.EXPECT(). + Insert(gomock.Any(), gomock.Any()). + Return(nil, fmt.Errorf("database error")) + }, + expectError: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.setupMocks() + resp, err := l.BindUserInfo(tt.input) + if tt.expectError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, tt.expected, resp) + } + }) + } +} diff --git a/internal/logic/create_user_account_logic.go b/internal/logic/create_user_account_logic.go index 0b91070..e62c590 100644 --- a/internal/logic/create_user_account_logic.go +++ b/internal/logic/create_user_account_logic.go @@ -4,15 +4,16 @@ import ( "context" "errors" "fmt" - "github.com/go-sql-driver/mysql" - "github.com/zeromicro/go-zero/core/logx" "member/gen_result/pb/member" + "member/internal/domain" ers "member/internal/lib/error" - "member/internal/lib/required" "member/internal/model" "member/internal/svc" "member/internal/utils" "time" + + "github.com/go-sql-driver/mysql" + "github.com/zeromicro/go-zero/core/logx" ) type CreateUserAccountLogic struct { @@ -35,19 +36,21 @@ type createLoginUserReq struct { Token string `json:"token" validate:"required"` } +// HasPasswordFunc 這樣方便測試 +var HasPasswordFunc = utils.HashPassword + // CreateUserAccount 建立帳號與密碼 -> 可登入,但可不可以做其他事情看業務流程,也可以只註冊就好 func (l *CreateUserAccountLogic) CreateUserAccount(in *member.CreateLoginUserReq) (*member.Response, error) { // 驗證資料 - err := required.ValidateAll(l.svcCtx.Validate, &createLoginUserReq{ + if err := l.svcCtx.Validate.ValidateAll(&createLoginUserReq{ LoginId: in.GetLoginId(), Platform: in.GetPlatform(), Token: in.GetToken(), - }) - if err != nil { + }); err != nil { return nil, ers.InvalidFormat(err.Error()) } - token, err := utils.HashPassword(in.GetToken(), l.svcCtx.Config.Bcrypt.Cost) + token, err := HasPasswordFunc(in.GetToken(), l.svcCtx.Config.Bcrypt.Cost) if err != nil { return nil, ers.ArkInternal(fmt.Sprintf("failed to encrypt err: %v", err.Error())) } @@ -72,5 +75,11 @@ func (l *CreateUserAccountLogic) CreateUserAccount(in *member.CreateLoginUserReq return nil, ers.DBError(err.Error()) } - return nil, nil + return &member.Response{ + Status: &member.BaseResp{ + Code: domain.CodeOk.ToString(), + Message: "success", + Error: "", + }, + }, nil } diff --git a/internal/logic/create_user_account_logic_test.go b/internal/logic/create_user_account_logic_test.go new file mode 100644 index 0000000..6b68bb5 --- /dev/null +++ b/internal/logic/create_user_account_logic_test.go @@ -0,0 +1,166 @@ +package logic + +import ( + "context" + "fmt" + "member/gen_result/pb/member" + "member/internal/domain" + libMock "member/internal/mock/lib" + modelMock "member/internal/mock/model" + svcMock "member/internal/mock/svc" + "member/internal/svc" + "testing" + + "github.com/alicebob/miniredis/v2" + "github.com/go-sql-driver/mysql" + "github.com/stretchr/testify/assert" + "github.com/zeromicro/go-zero/core/stores/redis" + "go.uber.org/mock/gomock" +) + +func TestCreateUserAccountLogic_CreateUserAccount(t *testing.T) { + // mock + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + modelAccountModel := modelMock.NewMockAccountModel(ctrl) + + mockSnackFlow := svcMock.NewMockSnackFlow(ctrl) + mockValidate := libMock.NewMockValidate(ctrl) + + r1, err := miniredis.Run() + assert.NoError(t, err) + defer r1.Close() + + newRedis, err := redis.NewRedis(redis.RedisConf{ + Host: r1.Addr(), + Type: redis.ClusterType, + Pass: "", + }) + assert.NoError(t, err) + + sc := svc.ServiceContext{ + AccountModel: modelAccountModel, + SnackFlowGen: mockSnackFlow, + Redis: *newRedis, + Validate: mockValidate, + } + + l := NewCreateUserAccountLogic(context.Background(), &sc) + + tests := []struct { + name string + input *member.CreateLoginUserReq + setupMocks func() + expectError bool + expected *member.Response + }{ + { + name: "ok", + input: &member.CreateLoginUserReq{ + LoginId: "test_user", + Platform: 1, + Token: "password123", + }, + setupMocks: func() { + mockValidate.EXPECT(). + ValidateAll(gomock.Any()). + Return(nil) + modelAccountModel.EXPECT(). + Insert(gomock.Any(), gomock.Any()). + Return(nil, nil) + }, + expectError: false, + expected: &member.Response{ + Status: &member.BaseResp{ + Code: domain.CodeOk.ToString(), + Message: "success", + Error: "", + }, + }, + }, + { + name: "validation failure", + input: &member.CreateLoginUserReq{ + LoginId: "test_user", + Platform: 1, + Token: "password123", + }, + setupMocks: func() { + mockValidate.EXPECT(). + ValidateAll(gomock.Any()). + Return(fmt.Errorf("validation error")) + }, + expectError: true, + }, + { + name: "password hash failure", + input: &member.CreateLoginUserReq{ + LoginId: "test_user", + Platform: 1, + Token: "password123", + }, + setupMocks: func() { + mockValidate.EXPECT(). + ValidateAll(gomock.Any()). + Return(nil) + HasPasswordFunc = func(password string, cost int) (string, error) { + return "", fmt.Errorf("hash error") + } + }, + expectError: true, + }, + { + name: "duplicate entry error", + input: &member.CreateLoginUserReq{ + LoginId: "test_user", + Platform: 1, + Token: "password123", + }, + setupMocks: func() { + mockValidate.EXPECT(). + ValidateAll(gomock.Any()). + Return(nil) + HasPasswordFunc = func(password string, cost int) (string, error) { + return "hashedpassword", nil + } + modelAccountModel.EXPECT(). + Insert(gomock.Any(), gomock.Any()). + Return(nil, &mysql.MySQLError{Number: 1062, Message: "Duplicate entry"}) + }, + expectError: true, + }, + { + name: "database error", + input: &member.CreateLoginUserReq{ + LoginId: "test_user", + Platform: 1, + Token: "password123", + }, + setupMocks: func() { + mockValidate.EXPECT(). + ValidateAll(gomock.Any()). + Return(nil) + HasPasswordFunc = func(password string, cost int) (string, error) { + return "hashedpassword", nil + } + modelAccountModel.EXPECT(). + Insert(gomock.Any(), gomock.Any()). + Return(nil, fmt.Errorf("database error")) + }, + expectError: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.setupMocks() + resp, err := l.CreateUserAccount(tt.input) + if tt.expectError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, tt.expected, resp) + } + }) + } +} diff --git a/internal/logic/generate_refresh_code_logic.go b/internal/logic/generate_refresh_code_logic.go index 2d263a2..dae6307 100644 --- a/internal/logic/generate_refresh_code_logic.go +++ b/internal/logic/generate_refresh_code_logic.go @@ -2,9 +2,14 @@ package logic import ( "context" - + "crypto/rand" + "fmt" + "math/big" "member/gen_result/pb/member" + "member/internal/domain" + ers "member/internal/lib/error" "member/internal/svc" + "strconv" "github.com/zeromicro/go-zero/core/logx" ) @@ -23,9 +28,101 @@ func NewGenerateRefreshCodeLogic(ctx context.Context, svcCtx *svc.ServiceContext } } +type generateRefreshCodeReq struct { + Account string `json:"account" validate:"account"` + // CodeType 1 email 2 phone + CodeType int32 `json:"code_type" validate:"required,oneof=1 2 3"` +} + +var codeMap = map[int32]string{ + 1: "email", + 2: "phone", +} + +func getCodeNameByCode(code int32) (string, bool) { + res, ok := codeMap[code] + if !ok { + return "", false + } + + return res, true +} + +func generateVerifyCode(digits int) (string, error) { + if digits <= 0 { + // 預設為六位數 + digits = 6 + } + + // 計算最大值 (10^digits - 1) + exp := new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(digits)), nil) + // 生成隨機數 + randomNumber, err := rand.Int(rand.Reader, exp) + if err != nil { + return "", err + } + + // 將隨機數轉換為 string + verifyCode := strconv.Itoa(int(randomNumber.Int64())) + // 如果隨機數的位數少於指定的位數,則補 0 + if len(verifyCode) < digits { + verifyCode = fmt.Sprintf("%0*d", digits, randomNumber) + } + + return verifyCode, nil +} + // GenerateRefreshCode 這個帳號驗證碼(十分鐘),通用的 func (l *GenerateRefreshCodeLogic) GenerateRefreshCode(in *member.GenerateRefreshCodeReq) (*member.GenerateRefreshCodeResp, error) { - // todo: add your logic here and delete this line + // 驗證資料 + if err := l.svcCtx.Validate.ValidateAll(&generateRefreshCodeReq{ + Account: in.GetAccount(), + CodeType: in.GetCodeType(), + }); err != nil { + return nil, ers.InvalidFormat(err.Error()) + } - return &member.GenerateRefreshCodeResp{}, nil + checkType, status := getCodeNameByCode(in.GetCodeType()) + if !status { + return nil, ers.InvalidFormat(fmt.Errorf("failed to get correct code type").Error()) + } + rk := fmt.Sprintf("verify:%s:%s", checkType, in.GetAccount()) + // 拿過就不要再拿了 + get, err := l.svcCtx.Redis.Get(rk) + if err != nil { + return nil, ers.DBError("failed to connect to redis", err.Error()) + } + if get != "" { + return &member.GenerateRefreshCodeResp{ + Status: &member.BaseResp{ + Code: domain.CodeOk.ToString(), + Message: "success", + Error: "", + }, + Data: &member.VerifyCode{ + VerifyCode: get, + }, + }, nil + } + + code, err := generateVerifyCode(6) + if !status { + return nil, ers.ArkInternal(err.Error()) + } + + err = l.svcCtx.Redis.Setex(rk, code, 600) + if err != nil { + return nil, ers.ArkInternal(err.Error()) + } + + return &member.GenerateRefreshCodeResp{ + Status: &member.BaseResp{ + Code: domain.CodeOk.ToString(), + Message: "success", + Error: "", + }, + Data: &member.VerifyCode{ + VerifyCode: code, + }, + }, nil } diff --git a/internal/logic/generate_refresh_code_logic_test.go b/internal/logic/generate_refresh_code_logic_test.go new file mode 100644 index 0000000..ea71cf2 --- /dev/null +++ b/internal/logic/generate_refresh_code_logic_test.go @@ -0,0 +1,51 @@ +package logic + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_getCodeNameByCode(t *testing.T) { + type args struct { + code int32 + } + tests := []struct { + name string + args args + want string + want1 bool + }{ + { + name: "email", + args: args{ + code: 1, + }, + want: "email", + want1: true, + }, + { + name: "phone", + args: args{ + code: 2, + }, + want: "phone", + want1: true, + }, + { + name: "none", + args: args{ + code: 3, + }, + want: "", + want1: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, got1 := getCodeNameByCode(tt.args.code) + assert.Equalf(t, tt.want, got, "getCodeNameByCode(%v)", tt.args.code) + assert.Equalf(t, tt.want1, got1, "getCodeNameByCode(%v)", tt.args.code) + }) + } +} diff --git a/internal/logic/get_uid_by_account_logic.go b/internal/logic/get_uid_by_account_logic.go index 68eab23..c0112a0 100644 --- a/internal/logic/get_uid_by_account_logic.go +++ b/internal/logic/get_uid_by_account_logic.go @@ -2,8 +2,9 @@ package logic import ( "context" - "member/gen_result/pb/member" + "member/internal/domain" + ers "member/internal/lib/error" "member/internal/svc" "github.com/zeromicro/go-zero/core/logx" @@ -23,9 +24,32 @@ func NewGetUidByAccountLogic(ctx context.Context, svcCtx *svc.ServiceContext) *G } } +type getUidByAccountReq struct { + Account string `json:"account" validate:"account"` +} + // GetUidByAccount 用帳號換取 UID func (l *GetUidByAccountLogic) GetUidByAccount(in *member.GetUIDByAccountReq) (*member.GetUidByAccountResp, error) { - // todo: add your logic here and delete this line + // 驗證資料 + if err := l.svcCtx.Validate.ValidateAll(&getUidByAccountReq{ + Account: in.GetAccount(), + }); err != nil { + return nil, ers.InvalidFormat(err.Error()) + } - return &member.GetUidByAccountResp{}, nil + account, err := l.svcCtx.AccountToUidModel.FindOneByAccount(l.ctx, in.GetAccount()) + if err != nil { + return nil, err + } + + return &member.GetUidByAccountResp{ + Status: &member.BaseResp{ + Code: domain.CodeOk.ToString(), + Message: "success", + Error: "", + }, + Data: &member.UID{ + Uid: account.Uid, + }, + }, nil } diff --git a/internal/logic/get_user_account_info_logic.go b/internal/logic/get_user_account_info_logic.go index 660db18..19204da 100644 --- a/internal/logic/get_user_account_info_logic.go +++ b/internal/logic/get_user_account_info_logic.go @@ -5,7 +5,6 @@ import ( "member/gen_result/pb/member" "member/internal/domain" ers "member/internal/lib/error" - "member/internal/lib/required" "member/internal/svc" "github.com/zeromicro/go-zero/core/logx" @@ -31,11 +30,10 @@ type getUserAccountReq struct { // GetUserAccountInfo 取得帳號密碼資料 func (l *GetUserAccountInfoLogic) GetUserAccountInfo(in *member.GetUIDByAccountReq) (*member.GetAccountInfoResp, error) { - // 驗證輸入資料 - err := required.ValidateAll(l.svcCtx.Validate, &getUserAccountReq{ + // 驗證資料 + if err := l.svcCtx.Validate.ValidateAll(getUserAccountReq{ LoginId: in.GetAccount(), - }) - if err != nil { + }); err != nil { return nil, ers.InvalidFormat(err.Error()) } diff --git a/internal/logic/get_user_info_logic.go b/internal/logic/get_user_info_logic.go index 0f56cfc..dd850ea 100644 --- a/internal/logic/get_user_info_logic.go +++ b/internal/logic/get_user_info_logic.go @@ -2,8 +2,9 @@ package logic import ( "context" - "member/gen_result/pb/member" + ers "member/internal/lib/error" + "member/internal/model" "member/internal/svc" "github.com/zeromicro/go-zero/core/logx" @@ -23,9 +24,29 @@ func NewGetUserInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUs } } -// UpdateStatus 取得會員資訊 +// GetUserInfo 取得會員資訊 func (l *GetUserInfoLogic) GetUserInfo(in *member.GetUserInfoReq) (*member.GetUserInfoResp, error) { - // todo: add your logic here and delete this line + var entity *model.UserTable + var err error - return &member.GetUserInfoResp{}, nil + if in.GetUid() != "" { + entity, err = l.svcCtx.UserModel.FindOneByUid(l.ctx, in.GetUid()) + if err != nil { + return nil, ers.DBError(err.Error()) + } + } else { + if in.GetNickName() != "" { + entity, err = l.svcCtx.UserModel.FindOneByNickName(l.ctx, in.GetNickName()) + if err != nil { + return nil, ers.DBError(err.Error()) + } + + } + } + + if entity != nil { + return &member.GetUserInfoResp{}, nil + } + + return nil, ers.ResourceNotFound("filed to get user info") } diff --git a/internal/logic/list_member_logic.go b/internal/logic/list_member_logic.go index 9cf98c3..5a0902b 100644 --- a/internal/logic/list_member_logic.go +++ b/internal/logic/list_member_logic.go @@ -2,9 +2,13 @@ package logic import ( "context" - + "fmt" "member/gen_result/pb/member" + "member/internal/domain" + ers "member/internal/lib/error" + "member/internal/model" "member/internal/svc" + "strconv" "github.com/zeromicro/go-zero/core/logx" ) @@ -23,9 +27,141 @@ func NewListMemberLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListMe } } +func parse(in *member.ListUserInfoReq) (model.UserQueryParams, error) { + var filter model.UserQueryParams + + // 設置 PageSize + filter.PageSize = getValidPageSize(in.PageSize) + + // 設置 PageIndex + filter.PageIndex = getValidPageIndex(in.PageIndex) + + // 設置 RoleId + if in.RoleId != nil { + filter.RoleId = in.RoleId + } + + // 設置 VerifyType + svt := fmt.Sprintf("%d", in.GetVerifyType().Number()) + vt, err := getInt32FromStringPointer(&svt) + if err != nil { + return model.UserQueryParams{}, err + } + if vt != nil { + filter.VerifyType = vt + } + + // 設置 AlarmType + sat := fmt.Sprintf("%d", in.GetAlarmType().Number()) + at, err := getInt32FromStringPointer(&sat) + if err != nil { + return model.UserQueryParams{}, err + } + + if at != nil { + filter.AlarmType = at + } + + // 設置 Status + sst := fmt.Sprintf("%d", in.GetStatus().Number()) + st, err := getInt32FromStringPointer(&sst) + if err != nil { + return model.UserQueryParams{}, err + } + if st != nil { + filter.Status = st + } + + // 設置 CreateStartTime + if in.CreateStartTime != nil { + ct := in.GetCreateStartTime() + filter.CreateStartTime = &ct + } + + // 設置 CreateEndTime + if in.CreateEndTime != nil { + et := in.GetCreateEndTime() + filter.CreateEndTime = &et + } + + return filter, nil +} + +func getValidPageSize(pageSize int64) int64 { + if pageSize <= 0 { + return domain.DefaultPageSize + } + return pageSize +} + +func getValidPageIndex(pageIndex int64) int64 { + if pageIndex <= 0 { + return domain.DefaultPageIndex + } + return pageIndex +} + +func getInt32FromStringPointer(strPtr *string) (*int32, error) { + if strPtr == nil { + return nil, nil + } + value, err := strconv.Atoi(*strPtr) + if err != nil { + return nil, err + } + int32Value := int32(value) + if int32Value == 0 { + return nil, nil + } + return &int32Value, nil +} + // ListMember 取得會員列表 func (l *ListMemberLogic) ListMember(in *member.ListUserInfoReq) (*member.ListUserInfoResp, error) { - // todo: add your logic here and delete this line + params, err := parse(in) + if err != nil { + return nil, ers.InvalidFormat("failed to get correct param", err.Error()) + } - return &member.ListUserInfoResp{}, nil + members, err := l.svcCtx.UserModel.ListMembers(l.ctx, ¶ms) + if err != nil { + return nil, ers.DBError(err.Error()) + } + + count, err := l.svcCtx.UserModel.Count(l.ctx) + if err != nil { + return nil, ers.DBError(err.Error()) + } + + var data = make([]*member.UserInfo, 0, len(members)) + + for _, item := range members { + g := uint32(item.Gender) + data = append(data, &member.UserInfo{ + Uid: item.Uid, + VerifyType: member.VerifyType(item.VerifyType), + AlarmType: member.AlarmType(item.AlarmType), + Status: member.MemberStatus(item.Status), + RoleId: item.RoleId, + Language: item.Language, + Currency: item.Currency, + NickName: &item.NickName, + Gender: &g, + Birthday: &item.Birthday, + }) + } + + return &member.ListUserInfoResp{ + Status: &member.BaseResp{ + Code: domain.CodeOk.ToString(), + Message: "success", + Error: "", + }, + Data: data, + Page: &member.Pager{ + Total: count, + Size: in.PageSize, + Index: in.PageIndex, + }, + }, nil } diff --git a/internal/logic/update_status_logic.go b/internal/logic/update_status_logic.go index c71d5c2..0ddc69e 100644 --- a/internal/logic/update_status_logic.go +++ b/internal/logic/update_status_logic.go @@ -2,8 +2,9 @@ package logic import ( "context" - "member/gen_result/pb/member" + "member/internal/domain" + ers "member/internal/lib/error" "member/internal/svc" "github.com/zeromicro/go-zero/core/logx" @@ -23,9 +24,31 @@ func NewUpdateStatusLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Upda } } +type updateStatusReq struct { + UID string `json:"uid" validate:"required"` + Status int32 `json:"status" validate:"required,oneof=1 2 3 4 5 6"` +} + // UpdateStatus 修改狀態 func (l *UpdateStatusLogic) UpdateStatus(in *member.UpdateStatusReq) (*member.Response, error) { - // todo: add your logic here and delete this line + // 驗證資料 + if err := l.svcCtx.Validate.ValidateAll(&updateStatusReq{ + UID: in.GetUid(), + Status: int32(in.GetStatus()), + }); err != nil { + return nil, ers.InvalidFormat(err.Error()) + } - return &member.Response{}, nil + err := l.svcCtx.UserModel.UpdateStatus(l.ctx, in.GetUid(), int32(in.GetStatus())) + if err != nil { + return nil, ers.DBError(err.Error()) + } + + return &member.Response{ + Status: &member.BaseResp{ + Code: domain.CodeOk.ToString(), + Message: "success", + Error: "", + }, + }, nil } diff --git a/internal/logic/update_user_info_logic.go b/internal/logic/update_user_info_logic.go index 9d93691..f85238a 100644 --- a/internal/logic/update_user_info_logic.go +++ b/internal/logic/update_user_info_logic.go @@ -2,8 +2,9 @@ package logic import ( "context" - "member/gen_result/pb/member" + "member/internal/domain" + ers "member/internal/lib/error" "member/internal/svc" "github.com/zeromicro/go-zero/core/logx" @@ -25,7 +26,16 @@ func NewUpdateUserInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Up // UpdateUserInfo 更新 User Info func (l *UpdateUserInfoLogic) UpdateUserInfo(in *member.UpdateUserInfoReq) (*member.Response, error) { - // todo: add your logic here and delete this line + err := l.svcCtx.UserModel.UpdateSome(l.ctx, in) + if err != nil { + return nil, ers.DBError(err.Error()) + } - return &member.Response{}, nil + return &member.Response{ + Status: &member.BaseResp{ + Code: domain.CodeOk.ToString(), + Message: "success", + Error: "", + }, + }, nil } diff --git a/internal/logic/update_user_token_logic.go b/internal/logic/update_user_token_logic.go index d6c6635..264eb48 100644 --- a/internal/logic/update_user_token_logic.go +++ b/internal/logic/update_user_token_logic.go @@ -2,6 +2,10 @@ package logic import ( "context" + "fmt" + "member/internal/domain" + ers "member/internal/lib/error" + "member/internal/utils" "member/gen_result/pb/member" "member/internal/svc" @@ -23,9 +27,36 @@ func NewUpdateUserTokenLogic(ctx context.Context, svcCtx *svc.ServiceContext) *U } } +type updateUserTokenReq struct { + LoginId string `json:"login_id" validate:"account"` + Token string `json:"token" validate:"required"` +} + // UpdateUserToken 更新密碼 func (l *UpdateUserTokenLogic) UpdateUserToken(in *member.UpdateTokenReq) (*member.Response, error) { - // todo: add your logic here and delete this line + // 驗證資料 + if err := l.svcCtx.Validate.ValidateAll(&updateUserTokenReq{ + LoginId: in.GetAccount(), + Token: in.GetToken(), + }); err != nil { + return nil, ers.InvalidFormat(err.Error()) + } - return &member.Response{}, nil + token, err := utils.HashPassword(in.GetToken(), l.svcCtx.Config.Bcrypt.Cost) + if err != nil { + return nil, ers.ArkInternal(fmt.Sprintf("failed to encrypt err: %v", err.Error())) + } + + err = l.svcCtx.AccountModel.UpdateTokenByLoginID(l.ctx, in.GetAccount(), token) + if err != nil { + return nil, ers.DBError(err.Error()) + } + + return &member.Response{ + Status: &member.BaseResp{ + Code: domain.CodeOk.ToString(), + Message: "success", + Error: "", + }, + }, nil } diff --git a/internal/logic/verify_refresh_code_logic.go b/internal/logic/verify_refresh_code_logic.go index a316a82..8c62574 100644 --- a/internal/logic/verify_refresh_code_logic.go +++ b/internal/logic/verify_refresh_code_logic.go @@ -2,8 +2,10 @@ package logic import ( "context" - + "fmt" "member/gen_result/pb/member" + "member/internal/domain" + ers "member/internal/lib/error" "member/internal/svc" "github.com/zeromicro/go-zero/core/logx" @@ -25,7 +27,42 @@ func NewVerifyRefreshCodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) // VerifyRefreshCode 驗證忘記密碼 token func (l *VerifyRefreshCodeLogic) VerifyRefreshCode(in *member.VerifyRefreshCodeReq) (*member.Response, error) { - // todo: add your logic here and delete this line + // 驗證資料 + if err := l.svcCtx.Validate.ValidateAll(&generateRefreshCodeReq{ + Account: in.GetAccount(), + CodeType: in.GetCodeType(), + }); err != nil { + return nil, ers.InvalidFormat(err.Error()) + } - return &member.Response{}, nil + checkType, status := getCodeNameByCode(in.GetCodeType()) + if !status { + return nil, ers.InvalidFormat(fmt.Errorf("failed to get correct code type").Error()) + } + rk := fmt.Sprintf("verify:%s:%s", checkType, in.GetAccount()) + get, err := l.svcCtx.Redis.Get(rk) + if err != nil { + return nil, ers.DBError("failed to connect to redis", err.Error()) + } + + if get == "" { + return nil, ers.DBError("failed to get data from redis") + } + + if get != fmt.Sprintf("%d", in.CodeType) { + return nil, ers.ArkInternal("Illegible Verify Code") + } + + _, err = l.svcCtx.Redis.Del(rk) + if err != nil { + return nil, ers.DBError("failed to del redis key", rk) + } + + return &member.Response{ + Status: &member.BaseResp{ + Code: domain.CodeOk.ToString(), + Message: "success", + Error: "", + }, + }, nil } diff --git a/internal/mock/lib/validate.go b/internal/mock/lib/validate.go new file mode 100644 index 0000000..bee4621 --- /dev/null +++ b/internal/mock/lib/validate.go @@ -0,0 +1,72 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./validate.go +// +// Generated by this command: +// +// mockgen -source=./validate.go -destination=../../mock/lib/validate.go -package=lib +// + +// Package lib is a generated GoMock package. +package lib + +import ( + required "member/internal/lib/required" + reflect "reflect" + + gomock "go.uber.org/mock/gomock" +) + +// MockValidate is a mock of Validate interface. +type MockValidate struct { + ctrl *gomock.Controller + recorder *MockValidateMockRecorder +} + +// MockValidateMockRecorder is the mock recorder for MockValidate. +type MockValidateMockRecorder struct { + mock *MockValidate +} + +// NewMockValidate creates a new mock instance. +func NewMockValidate(ctrl *gomock.Controller) *MockValidate { + mock := &MockValidate{ctrl: ctrl} + mock.recorder = &MockValidateMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockValidate) EXPECT() *MockValidateMockRecorder { + return m.recorder +} + +// BindToValidator mocks base method. +func (m *MockValidate) BindToValidator(opts ...required.Option) error { + m.ctrl.T.Helper() + varargs := []any{} + for _, a := range opts { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "BindToValidator", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// BindToValidator indicates an expected call of BindToValidator. +func (mr *MockValidateMockRecorder) BindToValidator(opts ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BindToValidator", reflect.TypeOf((*MockValidate)(nil).BindToValidator), opts...) +} + +// ValidateAll mocks base method. +func (m *MockValidate) ValidateAll(obj any) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ValidateAll", obj) + ret0, _ := ret[0].(error) + return ret0 +} + +// ValidateAll indicates an expected call of ValidateAll. +func (mr *MockValidateMockRecorder) ValidateAll(obj any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateAll", reflect.TypeOf((*MockValidate)(nil).ValidateAll), obj) +} diff --git a/internal/mock/model/account_model.go b/internal/mock/model/account_model.go new file mode 100644 index 0000000..162ef56 --- /dev/null +++ b/internal/mock/model/account_model.go @@ -0,0 +1,129 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./account_model.go +// +// Generated by this command: +// +// mockgen -source=./account_model.go -destination=../mock/model/account_model.go -package=model +// + +// Package model is a generated GoMock package. +package model + +import ( + context "context" + sql "database/sql" + model "member/internal/model" + reflect "reflect" + + gomock "go.uber.org/mock/gomock" +) + +// MockAccountModel is a mock of AccountModel interface. +type MockAccountModel struct { + ctrl *gomock.Controller + recorder *MockAccountModelMockRecorder +} + +// MockAccountModelMockRecorder is the mock recorder for MockAccountModel. +type MockAccountModelMockRecorder struct { + mock *MockAccountModel +} + +// NewMockAccountModel creates a new mock instance. +func NewMockAccountModel(ctrl *gomock.Controller) *MockAccountModel { + mock := &MockAccountModel{ctrl: ctrl} + mock.recorder = &MockAccountModelMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockAccountModel) EXPECT() *MockAccountModelMockRecorder { + return m.recorder +} + +// Delete mocks base method. +func (m *MockAccountModel) Delete(ctx context.Context, id int64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, id) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockAccountModelMockRecorder) Delete(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockAccountModel)(nil).Delete), ctx, id) +} + +// FindOne mocks base method. +func (m *MockAccountModel) FindOne(ctx context.Context, id int64) (*model.Account, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOne", ctx, id) + ret0, _ := ret[0].(*model.Account) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOne indicates an expected call of FindOne. +func (mr *MockAccountModelMockRecorder) FindOne(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockAccountModel)(nil).FindOne), ctx, id) +} + +// FindOneByAccount mocks base method. +func (m *MockAccountModel) FindOneByAccount(ctx context.Context, account string) (*model.Account, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOneByAccount", ctx, account) + ret0, _ := ret[0].(*model.Account) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOneByAccount indicates an expected call of FindOneByAccount. +func (mr *MockAccountModelMockRecorder) FindOneByAccount(ctx, account any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOneByAccount", reflect.TypeOf((*MockAccountModel)(nil).FindOneByAccount), ctx, account) +} + +// Insert mocks base method. +func (m *MockAccountModel) Insert(ctx context.Context, data *model.Account) (sql.Result, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", ctx, data) + ret0, _ := ret[0].(sql.Result) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Insert indicates an expected call of Insert. +func (mr *MockAccountModelMockRecorder) Insert(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockAccountModel)(nil).Insert), ctx, data) +} + +// Update mocks base method. +func (m *MockAccountModel) Update(ctx context.Context, data *model.Account) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, data) + ret0, _ := ret[0].(error) + return ret0 +} + +// Update indicates an expected call of Update. +func (mr *MockAccountModelMockRecorder) Update(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockAccountModel)(nil).Update), ctx, data) +} + +// UpdateTokenByLoginID mocks base method. +func (m *MockAccountModel) UpdateTokenByLoginID(ctx context.Context, account, token string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateTokenByLoginID", ctx, account, token) + ret0, _ := ret[0].(error) + return ret0 +} + +// UpdateTokenByLoginID indicates an expected call of UpdateTokenByLoginID. +func (mr *MockAccountModelMockRecorder) UpdateTokenByLoginID(ctx, account, token any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateTokenByLoginID", reflect.TypeOf((*MockAccountModel)(nil).UpdateTokenByLoginID), ctx, account, token) +} diff --git a/internal/mock/model/account_model_gen.go b/internal/mock/model/account_model_gen.go new file mode 100644 index 0000000..300ddb2 --- /dev/null +++ b/internal/mock/model/account_model_gen.go @@ -0,0 +1,115 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./account_model_gen.go +// +// Generated by this command: +// +// mockgen -source=./account_model_gen.go -destination=../mock/model/account_model_gen.go -package=model +// + +// Package model is a generated GoMock package. +package model + +import ( + context "context" + sql "database/sql" + model "member/internal/model" + reflect "reflect" + + gomock "go.uber.org/mock/gomock" +) + +// MockaccountModel is a mock of accountModel interface. +type MockaccountModel struct { + ctrl *gomock.Controller + recorder *MockaccountModelMockRecorder +} + +// MockaccountModelMockRecorder is the mock recorder for MockaccountModel. +type MockaccountModelMockRecorder struct { + mock *MockaccountModel +} + +// NewMockaccountModel creates a new mock instance. +func NewMockaccountModel(ctrl *gomock.Controller) *MockaccountModel { + mock := &MockaccountModel{ctrl: ctrl} + mock.recorder = &MockaccountModelMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockaccountModel) EXPECT() *MockaccountModelMockRecorder { + return m.recorder +} + +// Delete mocks base method. +func (m *MockaccountModel) Delete(ctx context.Context, id int64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, id) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockaccountModelMockRecorder) Delete(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockaccountModel)(nil).Delete), ctx, id) +} + +// FindOne mocks base method. +func (m *MockaccountModel) FindOne(ctx context.Context, id int64) (*model.Account, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOne", ctx, id) + ret0, _ := ret[0].(*model.Account) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOne indicates an expected call of FindOne. +func (mr *MockaccountModelMockRecorder) FindOne(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockaccountModel)(nil).FindOne), ctx, id) +} + +// FindOneByAccount mocks base method. +func (m *MockaccountModel) FindOneByAccount(ctx context.Context, account string) (*model.Account, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOneByAccount", ctx, account) + ret0, _ := ret[0].(*model.Account) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOneByAccount indicates an expected call of FindOneByAccount. +func (mr *MockaccountModelMockRecorder) FindOneByAccount(ctx, account any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOneByAccount", reflect.TypeOf((*MockaccountModel)(nil).FindOneByAccount), ctx, account) +} + +// Insert mocks base method. +func (m *MockaccountModel) Insert(ctx context.Context, data *model.Account) (sql.Result, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", ctx, data) + ret0, _ := ret[0].(sql.Result) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Insert indicates an expected call of Insert. +func (mr *MockaccountModelMockRecorder) Insert(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockaccountModel)(nil).Insert), ctx, data) +} + +// Update mocks base method. +func (m *MockaccountModel) Update(ctx context.Context, data *model.Account) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, data) + ret0, _ := ret[0].(error) + return ret0 +} + +// Update indicates an expected call of Update. +func (mr *MockaccountModelMockRecorder) Update(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockaccountModel)(nil).Update), ctx, data) +} diff --git a/internal/mock/model/account_to_uid_model.go b/internal/mock/model/account_to_uid_model.go new file mode 100644 index 0000000..8354a9e --- /dev/null +++ b/internal/mock/model/account_to_uid_model.go @@ -0,0 +1,115 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./account_to_uid_model.go +// +// Generated by this command: +// +// mockgen -source=./account_to_uid_model.go -destination=../mock/model/account_to_uid_model.go -package=model +// + +// Package model is a generated GoMock package. +package model + +import ( + context "context" + sql "database/sql" + model "member/internal/model" + reflect "reflect" + + gomock "go.uber.org/mock/gomock" +) + +// MockAccountToUidModel is a mock of AccountToUidModel interface. +type MockAccountToUidModel struct { + ctrl *gomock.Controller + recorder *MockAccountToUidModelMockRecorder +} + +// MockAccountToUidModelMockRecorder is the mock recorder for MockAccountToUidModel. +type MockAccountToUidModelMockRecorder struct { + mock *MockAccountToUidModel +} + +// NewMockAccountToUidModel creates a new mock instance. +func NewMockAccountToUidModel(ctrl *gomock.Controller) *MockAccountToUidModel { + mock := &MockAccountToUidModel{ctrl: ctrl} + mock.recorder = &MockAccountToUidModelMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockAccountToUidModel) EXPECT() *MockAccountToUidModelMockRecorder { + return m.recorder +} + +// Delete mocks base method. +func (m *MockAccountToUidModel) Delete(ctx context.Context, id int64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, id) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockAccountToUidModelMockRecorder) Delete(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockAccountToUidModel)(nil).Delete), ctx, id) +} + +// FindOne mocks base method. +func (m *MockAccountToUidModel) FindOne(ctx context.Context, id int64) (*model.AccountToUid, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOne", ctx, id) + ret0, _ := ret[0].(*model.AccountToUid) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOne indicates an expected call of FindOne. +func (mr *MockAccountToUidModelMockRecorder) FindOne(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockAccountToUidModel)(nil).FindOne), ctx, id) +} + +// FindOneByAccount mocks base method. +func (m *MockAccountToUidModel) FindOneByAccount(ctx context.Context, account string) (*model.AccountToUid, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOneByAccount", ctx, account) + ret0, _ := ret[0].(*model.AccountToUid) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOneByAccount indicates an expected call of FindOneByAccount. +func (mr *MockAccountToUidModelMockRecorder) FindOneByAccount(ctx, account any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOneByAccount", reflect.TypeOf((*MockAccountToUidModel)(nil).FindOneByAccount), ctx, account) +} + +// Insert mocks base method. +func (m *MockAccountToUidModel) Insert(ctx context.Context, data *model.AccountToUid) (sql.Result, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", ctx, data) + ret0, _ := ret[0].(sql.Result) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Insert indicates an expected call of Insert. +func (mr *MockAccountToUidModelMockRecorder) Insert(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockAccountToUidModel)(nil).Insert), ctx, data) +} + +// Update mocks base method. +func (m *MockAccountToUidModel) Update(ctx context.Context, data *model.AccountToUid) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, data) + ret0, _ := ret[0].(error) + return ret0 +} + +// Update indicates an expected call of Update. +func (mr *MockAccountToUidModelMockRecorder) Update(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockAccountToUidModel)(nil).Update), ctx, data) +} diff --git a/internal/mock/model/account_to_uid_model_gen.go b/internal/mock/model/account_to_uid_model_gen.go new file mode 100644 index 0000000..4837c6b --- /dev/null +++ b/internal/mock/model/account_to_uid_model_gen.go @@ -0,0 +1,115 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./account_to_uid_model_gen.go +// +// Generated by this command: +// +// mockgen -source=./account_to_uid_model_gen.go -destination=../mock/model/account_to_uid_model_gen.go -package=model +// + +// Package model is a generated GoMock package. +package model + +import ( + context "context" + sql "database/sql" + model "member/internal/model" + reflect "reflect" + + gomock "go.uber.org/mock/gomock" +) + +// MockaccountToUidModel is a mock of accountToUidModel interface. +type MockaccountToUidModel struct { + ctrl *gomock.Controller + recorder *MockaccountToUidModelMockRecorder +} + +// MockaccountToUidModelMockRecorder is the mock recorder for MockaccountToUidModel. +type MockaccountToUidModelMockRecorder struct { + mock *MockaccountToUidModel +} + +// NewMockaccountToUidModel creates a new mock instance. +func NewMockaccountToUidModel(ctrl *gomock.Controller) *MockaccountToUidModel { + mock := &MockaccountToUidModel{ctrl: ctrl} + mock.recorder = &MockaccountToUidModelMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockaccountToUidModel) EXPECT() *MockaccountToUidModelMockRecorder { + return m.recorder +} + +// Delete mocks base method. +func (m *MockaccountToUidModel) Delete(ctx context.Context, id int64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, id) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockaccountToUidModelMockRecorder) Delete(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockaccountToUidModel)(nil).Delete), ctx, id) +} + +// FindOne mocks base method. +func (m *MockaccountToUidModel) FindOne(ctx context.Context, id int64) (*model.AccountToUid, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOne", ctx, id) + ret0, _ := ret[0].(*model.AccountToUid) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOne indicates an expected call of FindOne. +func (mr *MockaccountToUidModelMockRecorder) FindOne(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockaccountToUidModel)(nil).FindOne), ctx, id) +} + +// FindOneByAccount mocks base method. +func (m *MockaccountToUidModel) FindOneByAccount(ctx context.Context, account string) (*model.AccountToUid, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOneByAccount", ctx, account) + ret0, _ := ret[0].(*model.AccountToUid) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOneByAccount indicates an expected call of FindOneByAccount. +func (mr *MockaccountToUidModelMockRecorder) FindOneByAccount(ctx, account any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOneByAccount", reflect.TypeOf((*MockaccountToUidModel)(nil).FindOneByAccount), ctx, account) +} + +// Insert mocks base method. +func (m *MockaccountToUidModel) Insert(ctx context.Context, data *model.AccountToUid) (sql.Result, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", ctx, data) + ret0, _ := ret[0].(sql.Result) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Insert indicates an expected call of Insert. +func (mr *MockaccountToUidModelMockRecorder) Insert(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockaccountToUidModel)(nil).Insert), ctx, data) +} + +// Update mocks base method. +func (m *MockaccountToUidModel) Update(ctx context.Context, data *model.AccountToUid) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, data) + ret0, _ := ret[0].(error) + return ret0 +} + +// Update indicates an expected call of Update. +func (mr *MockaccountToUidModelMockRecorder) Update(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockaccountToUidModel)(nil).Update), ctx, data) +} diff --git a/internal/mock/model/machine_node_model.go b/internal/mock/model/machine_node_model.go new file mode 100644 index 0000000..f580744 --- /dev/null +++ b/internal/mock/model/machine_node_model.go @@ -0,0 +1,115 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./machine_node_model.go +// +// Generated by this command: +// +// mockgen -source=./machine_node_model.go -destination=../mock/model/machine_node_model.go -package=model +// + +// Package model is a generated GoMock package. +package model + +import ( + context "context" + sql "database/sql" + model "member/internal/model" + reflect "reflect" + + gomock "go.uber.org/mock/gomock" +) + +// MockMachineNodeModel is a mock of MachineNodeModel interface. +type MockMachineNodeModel struct { + ctrl *gomock.Controller + recorder *MockMachineNodeModelMockRecorder +} + +// MockMachineNodeModelMockRecorder is the mock recorder for MockMachineNodeModel. +type MockMachineNodeModelMockRecorder struct { + mock *MockMachineNodeModel +} + +// NewMockMachineNodeModel creates a new mock instance. +func NewMockMachineNodeModel(ctrl *gomock.Controller) *MockMachineNodeModel { + mock := &MockMachineNodeModel{ctrl: ctrl} + mock.recorder = &MockMachineNodeModelMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockMachineNodeModel) EXPECT() *MockMachineNodeModelMockRecorder { + return m.recorder +} + +// Delete mocks base method. +func (m *MockMachineNodeModel) Delete(ctx context.Context, id int64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, id) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockMachineNodeModelMockRecorder) Delete(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockMachineNodeModel)(nil).Delete), ctx, id) +} + +// FindOne mocks base method. +func (m *MockMachineNodeModel) FindOne(ctx context.Context, id int64) (*model.MachineNode, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOne", ctx, id) + ret0, _ := ret[0].(*model.MachineNode) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOne indicates an expected call of FindOne. +func (mr *MockMachineNodeModelMockRecorder) FindOne(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockMachineNodeModel)(nil).FindOne), ctx, id) +} + +// FindOneByHostName mocks base method. +func (m *MockMachineNodeModel) FindOneByHostName(ctx context.Context, hostName string) (*model.MachineNode, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOneByHostName", ctx, hostName) + ret0, _ := ret[0].(*model.MachineNode) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOneByHostName indicates an expected call of FindOneByHostName. +func (mr *MockMachineNodeModelMockRecorder) FindOneByHostName(ctx, hostName any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOneByHostName", reflect.TypeOf((*MockMachineNodeModel)(nil).FindOneByHostName), ctx, hostName) +} + +// Insert mocks base method. +func (m *MockMachineNodeModel) Insert(ctx context.Context, data *model.MachineNode) (sql.Result, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", ctx, data) + ret0, _ := ret[0].(sql.Result) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Insert indicates an expected call of Insert. +func (mr *MockMachineNodeModelMockRecorder) Insert(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockMachineNodeModel)(nil).Insert), ctx, data) +} + +// Update mocks base method. +func (m *MockMachineNodeModel) Update(ctx context.Context, data *model.MachineNode) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, data) + ret0, _ := ret[0].(error) + return ret0 +} + +// Update indicates an expected call of Update. +func (mr *MockMachineNodeModelMockRecorder) Update(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockMachineNodeModel)(nil).Update), ctx, data) +} diff --git a/internal/mock/model/machine_node_model_gen.go b/internal/mock/model/machine_node_model_gen.go new file mode 100644 index 0000000..1d3f855 --- /dev/null +++ b/internal/mock/model/machine_node_model_gen.go @@ -0,0 +1,100 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./machine_node_model_gen.go +// +// Generated by this command: +// +// mockgen -source=./machine_node_model_gen.go -destination=../mock/model/machine_node_model_gen.go -package=model +// + +// Package model is a generated GoMock package. +package model + +import ( + context "context" + sql "database/sql" + model "member/internal/model" + reflect "reflect" + + gomock "go.uber.org/mock/gomock" +) + +// MockmachineNodeModel is a mock of machineNodeModel interface. +type MockmachineNodeModel struct { + ctrl *gomock.Controller + recorder *MockmachineNodeModelMockRecorder +} + +// MockmachineNodeModelMockRecorder is the mock recorder for MockmachineNodeModel. +type MockmachineNodeModelMockRecorder struct { + mock *MockmachineNodeModel +} + +// NewMockmachineNodeModel creates a new mock instance. +func NewMockmachineNodeModel(ctrl *gomock.Controller) *MockmachineNodeModel { + mock := &MockmachineNodeModel{ctrl: ctrl} + mock.recorder = &MockmachineNodeModelMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockmachineNodeModel) EXPECT() *MockmachineNodeModelMockRecorder { + return m.recorder +} + +// Delete mocks base method. +func (m *MockmachineNodeModel) Delete(ctx context.Context, id int64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, id) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockmachineNodeModelMockRecorder) Delete(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockmachineNodeModel)(nil).Delete), ctx, id) +} + +// FindOne mocks base method. +func (m *MockmachineNodeModel) FindOne(ctx context.Context, id int64) (*model.MachineNode, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOne", ctx, id) + ret0, _ := ret[0].(*model.MachineNode) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOne indicates an expected call of FindOne. +func (mr *MockmachineNodeModelMockRecorder) FindOne(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockmachineNodeModel)(nil).FindOne), ctx, id) +} + +// Insert mocks base method. +func (m *MockmachineNodeModel) Insert(ctx context.Context, data *model.MachineNode) (sql.Result, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", ctx, data) + ret0, _ := ret[0].(sql.Result) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Insert indicates an expected call of Insert. +func (mr *MockmachineNodeModelMockRecorder) Insert(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockmachineNodeModel)(nil).Insert), ctx, data) +} + +// Update mocks base method. +func (m *MockmachineNodeModel) Update(ctx context.Context, data *model.MachineNode) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, data) + ret0, _ := ret[0].(error) + return ret0 +} + +// Update indicates an expected call of Update. +func (mr *MockmachineNodeModelMockRecorder) Update(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockmachineNodeModel)(nil).Update), ctx, data) +} diff --git a/internal/mock/model/user_table_model.go b/internal/mock/model/user_table_model.go new file mode 100644 index 0000000..b4eee9a --- /dev/null +++ b/internal/mock/model/user_table_model.go @@ -0,0 +1,189 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./user_table_model.go +// +// Generated by this command: +// +// mockgen -source=./user_table_model.go -destination=../mock/model/user_table_model.go -package=model +// + +// Package model is a generated GoMock package. +package model + +import ( + context "context" + sql "database/sql" + member "member/gen_result/pb/member" + model "member/internal/model" + reflect "reflect" + + gomock "go.uber.org/mock/gomock" +) + +// MockUserTableModel is a mock of UserTableModel interface. +type MockUserTableModel struct { + ctrl *gomock.Controller + recorder *MockUserTableModelMockRecorder +} + +// MockUserTableModelMockRecorder is the mock recorder for MockUserTableModel. +type MockUserTableModelMockRecorder struct { + mock *MockUserTableModel +} + +// NewMockUserTableModel creates a new mock instance. +func NewMockUserTableModel(ctrl *gomock.Controller) *MockUserTableModel { + mock := &MockUserTableModel{ctrl: ctrl} + mock.recorder = &MockUserTableModelMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockUserTableModel) EXPECT() *MockUserTableModelMockRecorder { + return m.recorder +} + +// Count mocks base method. +func (m *MockUserTableModel) Count(ctx context.Context) (int64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Count", ctx) + ret0, _ := ret[0].(int64) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Count indicates an expected call of Count. +func (mr *MockUserTableModelMockRecorder) Count(ctx any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Count", reflect.TypeOf((*MockUserTableModel)(nil).Count), ctx) +} + +// Delete mocks base method. +func (m *MockUserTableModel) Delete(ctx context.Context, id int64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, id) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockUserTableModelMockRecorder) Delete(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockUserTableModel)(nil).Delete), ctx, id) +} + +// FindOne mocks base method. +func (m *MockUserTableModel) FindOne(ctx context.Context, id int64) (*model.UserTable, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOne", ctx, id) + ret0, _ := ret[0].(*model.UserTable) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOne indicates an expected call of FindOne. +func (mr *MockUserTableModelMockRecorder) FindOne(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockUserTableModel)(nil).FindOne), ctx, id) +} + +// FindOneByNickName mocks base method. +func (m *MockUserTableModel) FindOneByNickName(ctx context.Context, uid string) (*model.UserTable, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOneByNickName", ctx, uid) + ret0, _ := ret[0].(*model.UserTable) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOneByNickName indicates an expected call of FindOneByNickName. +func (mr *MockUserTableModelMockRecorder) FindOneByNickName(ctx, uid any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOneByNickName", reflect.TypeOf((*MockUserTableModel)(nil).FindOneByNickName), ctx, uid) +} + +// FindOneByUid mocks base method. +func (m *MockUserTableModel) FindOneByUid(ctx context.Context, uid string) (*model.UserTable, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOneByUid", ctx, uid) + ret0, _ := ret[0].(*model.UserTable) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOneByUid indicates an expected call of FindOneByUid. +func (mr *MockUserTableModelMockRecorder) FindOneByUid(ctx, uid any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOneByUid", reflect.TypeOf((*MockUserTableModel)(nil).FindOneByUid), ctx, uid) +} + +// Insert mocks base method. +func (m *MockUserTableModel) Insert(ctx context.Context, data *model.UserTable) (sql.Result, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", ctx, data) + ret0, _ := ret[0].(sql.Result) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Insert indicates an expected call of Insert. +func (mr *MockUserTableModelMockRecorder) Insert(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockUserTableModel)(nil).Insert), ctx, data) +} + +// ListMembers mocks base method. +func (m *MockUserTableModel) ListMembers(ctx context.Context, params *model.UserQueryParams) ([]*model.UserTable, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ListMembers", ctx, params) + ret0, _ := ret[0].([]*model.UserTable) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ListMembers indicates an expected call of ListMembers. +func (mr *MockUserTableModelMockRecorder) ListMembers(ctx, params any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListMembers", reflect.TypeOf((*MockUserTableModel)(nil).ListMembers), ctx, params) +} + +// Update mocks base method. +func (m *MockUserTableModel) Update(ctx context.Context, data *model.UserTable) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, data) + ret0, _ := ret[0].(error) + return ret0 +} + +// Update indicates an expected call of Update. +func (mr *MockUserTableModelMockRecorder) Update(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockUserTableModel)(nil).Update), ctx, data) +} + +// UpdateSome mocks base method. +func (m *MockUserTableModel) UpdateSome(ctx context.Context, newData *member.UpdateUserInfoReq) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateSome", ctx, newData) + ret0, _ := ret[0].(error) + return ret0 +} + +// UpdateSome indicates an expected call of UpdateSome. +func (mr *MockUserTableModelMockRecorder) UpdateSome(ctx, newData any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateSome", reflect.TypeOf((*MockUserTableModel)(nil).UpdateSome), ctx, newData) +} + +// UpdateStatus mocks base method. +func (m *MockUserTableModel) UpdateStatus(ctx context.Context, uid string, status int32) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateStatus", ctx, uid, status) + ret0, _ := ret[0].(error) + return ret0 +} + +// UpdateStatus indicates an expected call of UpdateStatus. +func (mr *MockUserTableModelMockRecorder) UpdateStatus(ctx, uid, status any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateStatus", reflect.TypeOf((*MockUserTableModel)(nil).UpdateStatus), ctx, uid, status) +} diff --git a/internal/mock/model/user_table_model_gen.go b/internal/mock/model/user_table_model_gen.go new file mode 100644 index 0000000..b2be8cd --- /dev/null +++ b/internal/mock/model/user_table_model_gen.go @@ -0,0 +1,115 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./user_table_model_gen.go +// +// Generated by this command: +// +// mockgen -source=./user_table_model_gen.go -destination=../mock/model/user_table_model_gen.go -package=model +// + +// Package model is a generated GoMock package. +package model + +import ( + context "context" + sql "database/sql" + model "member/internal/model" + reflect "reflect" + + gomock "go.uber.org/mock/gomock" +) + +// MockuserTableModel is a mock of userTableModel interface. +type MockuserTableModel struct { + ctrl *gomock.Controller + recorder *MockuserTableModelMockRecorder +} + +// MockuserTableModelMockRecorder is the mock recorder for MockuserTableModel. +type MockuserTableModelMockRecorder struct { + mock *MockuserTableModel +} + +// NewMockuserTableModel creates a new mock instance. +func NewMockuserTableModel(ctrl *gomock.Controller) *MockuserTableModel { + mock := &MockuserTableModel{ctrl: ctrl} + mock.recorder = &MockuserTableModelMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockuserTableModel) EXPECT() *MockuserTableModelMockRecorder { + return m.recorder +} + +// Delete mocks base method. +func (m *MockuserTableModel) Delete(ctx context.Context, id int64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, id) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockuserTableModelMockRecorder) Delete(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockuserTableModel)(nil).Delete), ctx, id) +} + +// FindOne mocks base method. +func (m *MockuserTableModel) FindOne(ctx context.Context, id int64) (*model.UserTable, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOne", ctx, id) + ret0, _ := ret[0].(*model.UserTable) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOne indicates an expected call of FindOne. +func (mr *MockuserTableModelMockRecorder) FindOne(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockuserTableModel)(nil).FindOne), ctx, id) +} + +// FindOneByUid mocks base method. +func (m *MockuserTableModel) FindOneByUid(ctx context.Context, uid string) (*model.UserTable, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindOneByUid", ctx, uid) + ret0, _ := ret[0].(*model.UserTable) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindOneByUid indicates an expected call of FindOneByUid. +func (mr *MockuserTableModelMockRecorder) FindOneByUid(ctx, uid any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOneByUid", reflect.TypeOf((*MockuserTableModel)(nil).FindOneByUid), ctx, uid) +} + +// Insert mocks base method. +func (m *MockuserTableModel) Insert(ctx context.Context, data *model.UserTable) (sql.Result, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", ctx, data) + ret0, _ := ret[0].(sql.Result) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Insert indicates an expected call of Insert. +func (mr *MockuserTableModelMockRecorder) Insert(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockuserTableModel)(nil).Insert), ctx, data) +} + +// Update mocks base method. +func (m *MockuserTableModel) Update(ctx context.Context, data *model.UserTable) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, data) + ret0, _ := ret[0].(error) + return ret0 +} + +// Update indicates an expected call of Update. +func (mr *MockuserTableModelMockRecorder) Update(ctx, data any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockuserTableModel)(nil).Update), ctx, data) +} diff --git a/internal/mock/svc/machine_node.go b/internal/mock/svc/machine_node.go new file mode 100644 index 0000000..4d5dad4 --- /dev/null +++ b/internal/mock/svc/machine_node.go @@ -0,0 +1,68 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./machine_node.go +// +// Generated by this command: +// +// mockgen -source=./machine_node.go -destination=../mock/svc/machine_node.go -package=svc +// + +// Package svc is a generated GoMock package. +package svc + +import ( + reflect "reflect" + + snowflake "github.com/bwmarrin/snowflake" + gomock "go.uber.org/mock/gomock" +) + +// MockSnackFlow is a mock of SnackFlow interface. +type MockSnackFlow struct { + ctrl *gomock.Controller + recorder *MockSnackFlowMockRecorder +} + +// MockSnackFlowMockRecorder is the mock recorder for MockSnackFlow. +type MockSnackFlowMockRecorder struct { + mock *MockSnackFlow +} + +// NewMockSnackFlow creates a new mock instance. +func NewMockSnackFlow(ctrl *gomock.Controller) *MockSnackFlow { + mock := &MockSnackFlow{ctrl: ctrl} + mock.recorder = &MockSnackFlowMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockSnackFlow) EXPECT() *MockSnackFlowMockRecorder { + return m.recorder +} + +// Generate mocks base method. +func (m *MockSnackFlow) Generate() snowflake.ID { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Generate") + ret0, _ := ret[0].(snowflake.ID) + return ret0 +} + +// Generate indicates an expected call of Generate. +func (mr *MockSnackFlowMockRecorder) Generate() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generate", reflect.TypeOf((*MockSnackFlow)(nil).Generate)) +} + +// GetSnackFlowNode mocks base method. +func (m *MockSnackFlow) GetSnackFlowNode() *snowflake.Node { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSnackFlowNode") + ret0, _ := ret[0].(*snowflake.Node) + return ret0 +} + +// GetSnackFlowNode indicates an expected call of GetSnackFlowNode. +func (mr *MockSnackFlowMockRecorder) GetSnackFlowNode() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSnackFlowNode", reflect.TypeOf((*MockSnackFlow)(nil).GetSnackFlowNode)) +} diff --git a/internal/model/account_model.go b/internal/model/account_model.go index 958d6dc..bd27aa7 100755 --- a/internal/model/account_model.go +++ b/internal/model/account_model.go @@ -1,6 +1,10 @@ package model import ( + "context" + "database/sql" + "fmt" + "github.com/zeromicro/go-zero/core/stores/cache" "github.com/zeromicro/go-zero/core/stores/sqlx" ) @@ -12,6 +16,7 @@ type ( // and implement the added methods in customAccountModel. AccountModel interface { accountModel + UpdateTokenByLoginID(ctx context.Context, account string, token string) error } customAccountModel struct { @@ -19,6 +24,21 @@ type ( } ) +func (m *defaultAccountModel) UpdateTokenByLoginID(ctx context.Context, account string, token string) error { + data, err := m.FindOneByAccount(ctx, account) + if err != nil { + return err + } + + accountAccountKey := fmt.Sprintf("%s%v", cacheAccountAccountPrefix, data.Account) + accountIdKey := fmt.Sprintf("%s%v", cacheAccountIdPrefix, data.Id) + _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("update %s set `token` = ? where `id` = ?", m.table) + return conn.ExecCtx(ctx, query, token, data.Id) + }, accountAccountKey, accountIdKey) + return err +} + // NewAccountModel returns a model for the database table. func NewAccountModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) AccountModel { return &customAccountModel{ diff --git a/internal/model/account_to_uid_model.go b/internal/model/account_to_uid_model.go index 694526e..72dfa07 100755 --- a/internal/model/account_to_uid_model.go +++ b/internal/model/account_to_uid_model.go @@ -8,6 +8,7 @@ import ( var _ AccountToUidModel = (*customAccountToUidModel)(nil) var ( + // nolint:unused cacheAccountPrefix = "cache:accountToUid:account:" ) diff --git a/internal/model/machine_node_model.go b/internal/model/machine_node_model.go index 86b044e..9620ebd 100755 --- a/internal/model/machine_node_model.go +++ b/internal/model/machine_node_model.go @@ -2,7 +2,9 @@ package model import ( "context" + "errors" "fmt" + "github.com/zeromicro/go-zero/core/stores/cache" "github.com/zeromicro/go-zero/core/stores/sqlc" "github.com/zeromicro/go-zero/core/stores/sqlx" @@ -37,10 +39,10 @@ func (m *defaultMachineNodeModel) FindOneByHostName(ctx context.Context, hostNam query := fmt.Sprintf("select %s from %s where `host_name` = ? limit 1", machineNodeRows, m.table) return conn.QueryRowCtx(ctx, v, query, hostName) }) - switch err { - case nil: + switch { + case err == nil: return &resp, nil - case sqlc.ErrNotFound: + case errors.Is(err, sqlc.ErrNotFound): return nil, ErrNotFound default: return nil, err diff --git a/internal/model/user_table_model.go b/internal/model/user_table_model.go index 13f2b1d..2ee4efc 100755 --- a/internal/model/user_table_model.go +++ b/internal/model/user_table_model.go @@ -1,7 +1,15 @@ package model import ( + "context" + "database/sql" + "fmt" + "member/gen_result/pb/member" + "strings" + "time" + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlc" "github.com/zeromicro/go-zero/core/stores/sqlx" ) @@ -12,11 +20,27 @@ type ( // and implement the added methods in customUserTableModel. UserTableModel interface { userTableModel + FindOneByNickName(ctx context.Context, uid string) (*UserTable, error) + ListMembers(ctx context.Context, params *UserQueryParams) ([]*UserTable, error) + Count(ctx context.Context) (int64, error) + UpdateStatus(ctx context.Context, uid string, status int32) error + UpdateSome(ctx context.Context, newData *member.UpdateUserInfoReq) error } customUserTableModel struct { *defaultUserTableModel } + + UserQueryParams struct { + RoleId *string + VerifyType *int32 + AlarmType *int32 + Status *int32 + CreateStartTime *int64 + CreateEndTime *int64 + PageSize int64 + PageIndex int64 + } ) // NewUserTableModel returns a model for the database table. @@ -25,3 +49,173 @@ func NewUserTableModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Optio defaultUserTableModel: newUserTableModel(conn, c, opts...), } } + +func (m *defaultUserTableModel) FindOneByNickName(ctx context.Context, nickName string) (*UserTable, error) { + userTableUidKey := fmt.Sprintf("%s%v", cacheUserTableUidPrefix, nickName) + var resp UserTable + err := m.QueryRowIndexCtx(ctx, &resp, userTableUidKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v any) (i any, e error) { + query := fmt.Sprintf("select %s from %s where `nick_name` = ? limit 1", userTableRows, m.table) + if err := conn.QueryRowCtx(ctx, &resp, query, nickName); err != nil { + return nil, err + } + return resp.Id, nil + }, m.queryPrimary) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultUserTableModel) ListMembers(ctx context.Context, params *UserQueryParams) ([]*UserTable, error) { + query := fmt.Sprintf("select %s from %s", userTableRows, m.table) + var args = make([]any, 0, 10) + var conditions []string + + if params.RoleId != nil { + conditions = append(conditions, "role_id = ?") + args = append(args, *params.RoleId) + } + + if params.VerifyType != nil { + conditions = append(conditions, "verify_type = ?") + args = append(args, *params.VerifyType) + } + + if params.AlarmType != nil { + conditions = append(conditions, "alarm_type = ?") + args = append(args, *params.AlarmType) + } + + if params.Status != nil { + conditions = append(conditions, "status = ?") + args = append(args, *params.Status) + } + + if params.CreateStartTime != nil { + conditions = append(conditions, "create_time >= ?") + args = append(args, *params.CreateStartTime) + } + + if params.CreateEndTime != nil { + conditions = append(conditions, "create_time <= ?") + args = append(args, *params.CreateEndTime) + } + + // 加入條件到查詢語句中 + if len(conditions) > 0 { + query += " WHERE " + strings.Join(conditions, " AND ") + } + + // 分頁處理 + offset := (params.PageIndex - 1) * params.PageSize + query += " LIMIT ? OFFSET ?" + args = append(args, params.PageSize, offset) + + var users []*UserTable + fmt.Println("query:", query) + fmt.Println("args:", args) + err := m.QueryRowsNoCacheCtx(ctx, &users, query, args...) + if err != nil { + return nil, err + } + + return users, nil +} + +func (m *defaultUserTableModel) Count(ctx context.Context) (int64, error) { + var count int64 + query := fmt.Sprintf("select count(*) from %s", m.table) + err := m.QueryRowNoCacheCtx(ctx, &count, query) + if err != nil { + return 0, err + } + return count, nil +} + +func (m *defaultUserTableModel) UpdateStatus(ctx context.Context, uid string, status int32) error { + data, err := m.FindOneByUid(ctx, uid) + if err != nil { + return err + } + + userTableIdKey := fmt.Sprintf("%s%v", cacheUserTableIdPrefix, data.Id) + userTableUidKey := fmt.Sprintf("%s%v", cacheUserTableUidPrefix, data.Uid) + _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("update %s set `status` = ? where `id` = ?", m.table) + return conn.ExecCtx(ctx, query, status, data.Id) + }, userTableIdKey, userTableUidKey) + return err +} + +func (m *defaultUserTableModel) UpdateSome(ctx context.Context, newData *member.UpdateUserInfoReq) error { + data, err := m.FindOneByUid(ctx, newData.Uid) + if err != nil { + return err + } + + // 初始化缓存键 + userTableIdKey := fmt.Sprintf("%s%v", cacheUserTableIdPrefix, data.Id) + userTableUidKey := fmt.Sprintf("%s%v", cacheUserTableUidPrefix, data.Uid) + + query := fmt.Sprintf("update %s set ", m.table) + var args []interface{} + var updates []string + + if newData.VerifyType != nil { + updates = append(updates, "verify_type = ?") + args = append(args, *newData.VerifyType) + } + if newData.AlarmType != nil { + updates = append(updates, "alarm_type = ?") + args = append(args, *newData.AlarmType) + } + if newData.Status != nil { + updates = append(updates, "status = ?") + args = append(args, *newData.Status) + } + if newData.RoleId != nil { + updates = append(updates, "role_id = ?") + args = append(args, *newData.RoleId) + } + if newData.Language != nil { + updates = append(updates, "language = ?") + args = append(args, *newData.Language) + } + if newData.Currency != nil { + updates = append(updates, "currency = ?") + args = append(args, *newData.Currency) + } + if newData.NickName != nil { + updates = append(updates, "nick_name = ?") + args = append(args, *newData.NickName) + } + if newData.Gender != nil { + updates = append(updates, "gender = ?") + args = append(args, *newData.Gender) + } + if newData.Birthday != nil { + updates = append(updates, "birthday = ?") + args = append(args, *newData.Birthday) + } + + if len(updates) == 0 { + return nil + } + + update := time.Now().UTC().Unix() + updates = append(updates, "update_time = ?") + args = append(args, &update) + + query += strings.Join(updates, ", ") + " where `id` = ?" + args = append(args, data.Id) + + _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + return conn.ExecCtx(ctx, query, args...) + }, userTableIdKey, userTableUidKey) + + return err +} diff --git a/internal/model/user_table_model_gen.go b/internal/model/user_table_model_gen.go index 7ee1f9b..647c416 100755 --- a/internal/model/user_table_model_gen.go +++ b/internal/model/user_table_model_gen.go @@ -18,14 +18,15 @@ import ( var ( userTableFieldNames = builder.RawFieldNames(&UserTable{}) userTableRows = strings.Join(userTableFieldNames, ",") - userTableRowsExpectAutoSet = strings.Join(stringx.Remove(userTableFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",") - userTableRowsWithPlaceHolder = strings.Join(stringx.Remove(userTableFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?" + userTableRowsExpectAutoSet = strings.Join(stringx.Remove(userTableFieldNames, "`id`"), ",") + userTableRowsWithPlaceHolder = strings.Join(stringx.Remove(userTableFieldNames, "`id`"), "=?,") + "=?" cacheUserTableIdPrefix = "cache:userTable:id:" cacheUserTableUidPrefix = "cache:userTable:uid:" ) type ( + // go:generate mockgen -source=./user_table_model_gen.go -destination=../../mock/model/user_table_model_gen.go -package=model userTableModel interface { Insert(ctx context.Context, data *UserTable) (sql.Result, error) FindOne(ctx context.Context, id int64) (*UserTable, error) @@ -126,8 +127,8 @@ func (m *defaultUserTableModel) Insert(ctx context.Context, data *UserTable) (sq userTableIdKey := fmt.Sprintf("%s%v", cacheUserTableIdPrefix, data.Id) userTableUidKey := fmt.Sprintf("%s%v", cacheUserTableUidPrefix, data.Uid) ret, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { - query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, userTableRowsExpectAutoSet) - return conn.ExecCtx(ctx, query, data.VerifyType, data.AlarmType, data.Status, data.Uid, data.RoleId, data.Language, data.Currency, data.NickName, data.Gender, data.Birthday) + query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, userTableRowsExpectAutoSet) + return conn.ExecCtx(ctx, query, data.VerifyType, data.AlarmType, data.Status, data.Uid, data.RoleId, data.Language, data.Currency, data.NickName, data.Gender, data.Birthday, data.CreateTime, data.UpdateTime) }, userTableIdKey, userTableUidKey) return ret, err } @@ -142,7 +143,7 @@ func (m *defaultUserTableModel) Update(ctx context.Context, newData *UserTable) userTableUidKey := fmt.Sprintf("%s%v", cacheUserTableUidPrefix, data.Uid) _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, userTableRowsWithPlaceHolder) - return conn.ExecCtx(ctx, query, newData.VerifyType, newData.AlarmType, newData.Status, newData.Uid, newData.RoleId, newData.Language, newData.Currency, newData.NickName, newData.Gender, newData.Birthday, newData.Id) + return conn.ExecCtx(ctx, query, newData.VerifyType, newData.AlarmType, newData.Status, newData.Uid, newData.RoleId, newData.Language, newData.Currency, newData.NickName, newData.Gender, newData.Birthday, newData.CreateTime, newData.UpdateTime, newData.Id) }, userTableIdKey, userTableUidKey) return err } diff --git a/internal/svc/machine_node.go b/internal/svc/machine_node.go index a044bd7..8e2e098 100644 --- a/internal/svc/machine_node.go +++ b/internal/svc/machine_node.go @@ -2,25 +2,36 @@ package svc import ( "context" - "github.com/bwmarrin/snowflake" - sf "member/internal/lib/snackflow" "member/internal/model" "os" "time" + + "github.com/bwmarrin/snowflake" ) -type machineNode struct { - MachineNodeID int64 `json:"machine_node_id"` +type SnackFlow interface { + GetSnackFlowNode() *snowflake.Node + Generate() snowflake.ID } -type MachineNodeCreateParams struct { - HostName string +type SnackFlowNode struct { + *snowflake.Node } -func NewMachineNode(node model.MachineNodeModel) int64 { +func NewSnackFlow(node model.MachineNodeModel) (SnackFlow, error) { + nodeID := newMachineNodeID(node) + ringNodeID := getMachineNodeID(nodeID) + s, err := snowflake.NewNode(ringNodeID) + if err != nil { + return nil, err + } + return &SnackFlowNode{Node: s}, nil +} + +func newMachineNodeID(node model.MachineNodeModel) int64 { ctx := context.Background() nodeName := os.Getenv("POD_NAME") - if os.Getenv("POD_NAME") == "" { + if nodeName == "" { nodeName = "default_node" } @@ -37,30 +48,24 @@ func NewMachineNode(node model.MachineNodeModel) int64 { if err != nil { return 1 } - return id } return machine.Id } -func GetMachineNodeID(machineNodeID int64) int64 { - // Snowflake 公式,工作機器 ID 佔用 10bit,最多容納 1024節點, +func getMachineNodeID(machineNodeID int64) int64 { + // Snowflake 公式,工作機器 ID 佔用 10bit,最多容納 1024 節點, // 故用 % 1024 取餘數做 ring const nodeMax = 1024 return machineNodeID % nodeMax } -func newSnackFlowNode(node model.MachineNodeModel) (*snowflake.Node, error) { - - nodeID := NewMachineNode(node) - ringNodeID := GetMachineNodeID(nodeID) - s := sf.New(sf.WithMachineNodeID(ringNodeID)) - n, err := s.NewNode() - if err != nil { - return nil, err - } - - return n, nil +func (n *SnackFlowNode) GetSnackFlowNode() *snowflake.Node { + return n.Node +} + +func (n *SnackFlowNode) Generate() snowflake.ID { + return n.Node.Generate() } diff --git a/internal/svc/service_context.go b/internal/svc/service_context.go index db92094..f7cf761 100644 --- a/internal/svc/service_context.go +++ b/internal/svc/service_context.go @@ -1,25 +1,27 @@ package svc import ( - "github.com/bwmarrin/snowflake" "member/internal/config" "member/internal/domain" "member/internal/lib/required" "member/internal/model" - "github.com/go-playground/validator/v10" - "github.com/zeromicro/go-zero/core/stores/sqlx" + "github.com/zeromicro/go-zero/core/stores/redis" + ers "member/internal/lib/error" + + "github.com/zeromicro/go-zero/core/stores/sqlx" ) type ServiceContext struct { Config config.Config - Validate *validator.Validate + Redis redis.Redis + Validate required.Validate AccountModel model.AccountModel UserModel model.UserTableModel AccountToUidModel model.AccountToUidModel - SnackFlowGen *snowflake.Node + SnackFlowGen SnackFlow } func NewServiceContext(c config.Config) *ServiceContext { @@ -27,13 +29,19 @@ func NewServiceContext(c config.Config) *ServiceContext { // 設置 ers.Scope = domain.Scope - n, err := newSnackFlowNode(model.NewMachineNodeModel(sqlConn, c.Cache)) + n, err := NewSnackFlow(model.NewMachineNodeModel(sqlConn, c.Cache)) + if err != nil { + panic(err) + } + + newRedis, err := redis.NewRedis(c.RedisCluster, redis.Cluster()) if err != nil { panic(err) } return &ServiceContext{ Config: c, + Redis: *newRedis, Validate: required.MustValidator(required.WithAccount("account")), UserModel: model.NewUserTableModel(sqlConn, c.Cache), AccountToUidModel: model.NewAccountToUidModel(sqlConn, c.Cache), diff --git a/member.go b/member.go index e83bd6d..b858381 100644 --- a/member.go +++ b/member.go @@ -35,7 +35,7 @@ func main() { }) defer s.Stop() - // 加入勿中間件 + // 加入中間件 s.AddUnaryInterceptors(middleware.TimeoutMiddleware) fmt.Printf("Starting rpc server at %s...\n", c.ListenOn) diff --git a/readme.md b/readme.md index cd9f892..c425dbc 100644 --- a/readme.md +++ b/readme.md @@ -5,6 +5,8 @@ goctl go get -d github.com/envoyproxy/protoc-gen-validate +mockgen -source=./validate.go -destination=../../mock/lib/validate.go -package=lib + ```