From c89aa9f14cb4aa8b643d37fdab99704ad9f85d78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=80=A7=E9=A9=8A?= Date: Sat, 8 Feb 2025 02:23:54 +0000 Subject: [PATCH] feature/rename_package (#1) Reviewed-on: https://code.30cm.net/digimon/app-cloudep-member-server/pulls/1 --- .golangci.yaml | 2 +- build/Dockerfile | 3 +- build/id_ed25519 | 0 docker-compose.yml | 23 +- etc/member.example.yaml | 26 ++- generate/protobuf/member.proto | 115 +++++---- go.mod | 2 +- internal/config/config.go | 7 +- internal/logic/account/bind_account_logic.go | 52 ++--- .../logic/account/bind_user_info_logic.go | 49 ++-- .../logic/account/bind_verify_email_logic.go | 23 +- .../logic/account/bind_verify_phone_logic.go | 23 +- .../logic/account/check_refresh_code_logic.go | 36 ++- .../account/create_user_account_logic.go | 50 +++- .../account/generate_refresh_code_logic.go | 36 ++- .../account/get_u_i_d_by_account_logic.go | 29 ++- .../account/get_user_account_info_logic.go | 32 ++- internal/logic/account/get_user_info_logic.go | 33 ++- .../line_code_to_access_token_logic.go | 15 +- .../line_get_profile_by_access_token_logic.go | 18 +- internal/logic/account/list_member_logic.go | 77 +++++- internal/logic/account/update_status_logic.go | 22 +- .../logic/account/update_user_info_logic.go | 44 +++- .../logic/account/update_user_token_logic.go | 16 +- .../verify_google_auth_result_logic.go | 30 ++- .../verify_platform_auth_result_logic.go | 18 +- .../account/verify_refresh_code_logic.go | 31 ++- internal/server/account/account_server.go | 12 +- internal/svc/service_context.go | 75 +++--- member.go | 8 +- pkg/domain/entity/account.go | 2 +- pkg/domain/entity/account_uid_table.go | 2 +- pkg/domain/entity/user.go | 2 +- pkg/domain/repository/account.go | 7 +- pkg/domain/repository/account_uid.go | 3 +- pkg/domain/repository/auto_id.go | 3 +- pkg/domain/repository/user.go | 5 +- pkg/domain/usecase/account.go | 3 +- pkg/mock/repository/account.go | 11 +- pkg/mock/repository/account_uid.go | 2 +- pkg/mock/repository/auto_id.go | 2 +- pkg/mock/repository/user.go | 4 +- pkg/repository/account.go | 17 +- pkg/repository/account_test.go | 15 +- pkg/repository/account_uid.go | 11 +- pkg/repository/account_uid_test.go | 9 +- pkg/repository/auto_id.go | 9 +- pkg/repository/auto_id_test.go | 9 +- pkg/repository/user.go | 11 +- pkg/repository/user_test.go | 11 +- pkg/repository/verify_code.go | 4 +- pkg/repository/verify_code_test.go | 3 +- pkg/usecase/account.go | 6 +- pkg/usecase/binding.go | 7 +- pkg/usecase/binding_test.go | 9 +- pkg/usecase/generate.go | 5 +- pkg/usecase/generate_test.go | 5 +- pkg/usecase/member.go | 31 ++- pkg/usecase/member_test.go | 29 +-- pkg/usecase/verify.go | 7 +- pkg/usecase/verify_google.go | 5 +- pkg/usecase/verify_google_test.go | 12 +- pkg/usecase/verify_line.go | 5 +- pkg/usecase/verify_test.go | 9 +- readme.md | 220 ++++++++++++++++++ 65 files changed, 1047 insertions(+), 355 deletions(-) delete mode 100644 build/id_ed25519 diff --git a/.golangci.yaml b/.golangci.yaml index 36f79f3..b6b98e7 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -104,7 +104,7 @@ issues: - contextcheck exclude-dirs: - - internal/logic + - gen_result/ exclude-files: - .*_test.go diff --git a/build/Dockerfile b/build/Dockerfile index 076303a..d720d4e 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -16,7 +16,8 @@ COPY . . RUN apt-get update && \ - apt-get install -y git + apt-get install -y git && \ + mkdir /root/.ssh # Make the root foler for our ssh RUN --mount=type=secret,id=ssh_key,dst=/root/.ssh/id_rsa \ diff --git a/build/id_ed25519 b/build/id_ed25519 deleted file mode 100644 index e69de29..0000000 diff --git a/docker-compose.yml b/docker-compose.yml index 7dcf0c3..f2bf8a8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -27,10 +27,6 @@ services: environment: MONGO_INITDB_ROOT_USERNAME: root MONGO_INITDB_ROOT_PASSWORD: example - networks: - - app-network - volumes: - - mongo-data:/data/db etcd: image: quay.io/coreos/etcd:v3.5.5 @@ -45,27 +41,10 @@ services: ports: - "2379:2379" - "2380:2380" - networks: - - app-network - volumes: - - etcd-data:/etcd-data redis: image: redis:7.0 container_name: redis restart: always ports: - - "6379:6379" - networks: - - app-network - volumes: - - redis-data:/data - -networks: - app-network: - driver: bridge - -volumes: - mongo-data: - etcd-data: - redis-data: \ No newline at end of file + - "6379:6379" \ No newline at end of file diff --git a/etc/member.example.yaml b/etc/member.example.yaml index f4fc756..a6a1915 100644 --- a/etc/member.example.yaml +++ b/etc/member.example.yaml @@ -2,7 +2,7 @@ Name: member.rpc ListenOn: 0.0.0.0:8080 Etcd: Hosts: - - 127.0.0.1:2379 + - 127.0.0.1:2379 Key: member.rpc Cache: @@ -11,12 +11,18 @@ Cache: CacheExpireTime: 1s CacheWithNotFoundExpiry: 1s +Redis: + Host: 127.0.0.1:6379 + Type: node + Tls: false + Key: "" + Mongo: Schema: mongodb - Host: 127.0.0.1 - User: "admin" - Password: "123" - Port: "27017" + Host: "127.0.0.1:27017" + User: "root" + Password: "example" + Port: "" Database: digimon_member ReplicaName: "rs0" MaxStaleness: 30m @@ -32,12 +38,12 @@ Bcrypt: Cost: 10 GoogleAuth: - ClientID: - AuthURL: + ClientID: xxx.apps.googleusercontent.com + AuthURL: x LineAuth: - ClientID : - ClientSecret : - RedirectURI : + ClientID : "200000000" + ClientSecret : xxxxx + RedirectURI : http://localhost:8080/line.html Host: 127.0.0.1 \ No newline at end of file diff --git a/generate/protobuf/member.proto b/generate/protobuf/member.proto index 9d39c8a..884a47c 100644 --- a/generate/protobuf/member.proto +++ b/generate/protobuf/member.proto @@ -9,12 +9,6 @@ message OKResp {} message NoneReq {} // ================ enum ================ -enum VerifyType { - VERIFY_NONE = 0; // 初始(異常) - VERIFY_OK = 1; - VERIFY_NOT = 2; // 尚未 -} - enum AlarmType { ALARM_NONE = 0; // 初始(異常) ALARM_NOT = 1; // 未告警 @@ -61,19 +55,18 @@ message BindingUserResp { message CreateUserInfoReq { string uid = 1; - VerifyType verify_type = 2; - AlarmType alarm_type = 3; - MemberStatus status = 4; - string language = 5; - string currency = 6; - optional string avatar= 7; - optional string nick_name = 8; - optional string full_name = 9; - optional int64 gender = 10; - optional int64 birthdate = 11; - optional string phone_number = 12; - optional string email = 13; - optional string address = 14; + AlarmType alarm_type = 2; + MemberStatus status = 3; + string language = 4; + string currency = 5; + optional string avatar= 6; + optional string nick_name = 7; + optional string full_name = 8; + optional int64 gender = 9; + optional int64 birthdate = 10; + optional string phone_number = 11; + optional string email = 12; + optional string address = 13; } message GetAccountInfoResp { @@ -87,15 +80,12 @@ message UpdateUserInfoReq { optional string currency = 3; optional string nick_name = 4; optional string avatar = 5; - optional VerifyType verify_type = 6; - optional AlarmType alarm_type = 7; - optional MemberStatus status = 8; - optional string full_name = 9; - optional int64 gender = 10; - optional int64 birthdate = 11; - optional string phone_number = 12; - optional string email = 13; - optional string address = 14; + optional AlarmType alarm_type = 6; + optional MemberStatus status = 7; + optional string full_name = 8; + optional int64 gender = 9; + optional int64 birthdate = 10; + optional string address = 11; } message GetUIDByAccountReq { @@ -144,15 +134,20 @@ message GetUserInfoReq { message UserInfo { string uid = 1; - VerifyType verify_type = 2; - AlarmType alarm_type = 3; - MemberStatus status = 4; - string language = 5; - string currency = 6; - string avatar = 7; - int64 create_time=8; - int64 update_time=9; - optional string nick_name = 10; + optional string avatar_url = 2; + optional string full_name = 3; + optional string nick_name = 4; + optional int64 gender_code = 5; + optional int64 birthday = 6; + optional string phone =7; + optional string email=8; + optional string address=9; + AlarmType alarm_type = 10; + MemberStatus status = 11; + string language = 12; + string currency = 13; + int64 create_time=14; + int64 update_time=15; } message GetUserInfoResp { @@ -160,13 +155,12 @@ message GetUserInfoResp { } message ListUserInfoReq { - optional VerifyType verify_type = 1; - optional AlarmType alarm_type = 2; - optional MemberStatus status = 3; - optional int64 create_start_time = 4; - optional int64 create_end_time = 5; - int64 page_size =6; - int64 page_index=7; + optional AlarmType alarm_type = 1; + optional MemberStatus status = 2; + optional int64 create_start_time = 3; + optional int64 create_end_time = 4; + int64 page_size =5; + int64 page_index=6; } message ListUserInfoResp { @@ -183,6 +177,19 @@ message VerifyAuthResultResp { bool status = 1; } +message VerifyGoogleAuthResultResp { + bool status = 1; + optional string iss =2; // 發行者 (issuer) 通常為 "https://accounts.google.com" + optional string sub =3; // 使用者唯一 ID + optional string aud =4; // Audience,應該與你的 Client ID 匹配 + optional string exp =5; // 過期時間 (UNIX timestamp) + optional string iat =6; // 發行時間 (UNIX timestamp) + optional string email =7; // 使用者的電子郵件 + optional string email_verified =8; // 郵件是否已驗證 + optional string name =9; // 使用者的名稱 + optional string picture =10; // 使用者的頭像 URL +} + message TwitterAccessTokenResp { string token = 1; } @@ -201,8 +208,18 @@ message LineAccessTokenResp { } message LineUserProfile { - string name = 1; - string email = 2; + string display_name = 1; + string user_id = 2; + string picture_url = 3; + string status_message = 4; +} + +message LineGetTokenReq { + string code = 1; +} + +message LineGetUserInfoReq { + string token = 1; } service Account { @@ -237,12 +254,12 @@ service Account { // CheckRefreshCode 驗證忘記密碼 token 不刪除,只確認) rpc CheckRefreshCode(VerifyRefreshCodeReq) returns(OKResp); // VerifyGoogleAuthResult 驗證 google 登入是否有效 - rpc VerifyGoogleAuthResult(VerifyAuthResultReq)returns(VerifyAuthResultResp); + rpc VerifyGoogleAuthResult(VerifyAuthResultReq)returns(VerifyGoogleAuthResultResp); // VerifyPlatformAuthResult 驗證 google 登入是否有效 rpc VerifyPlatformAuthResult(VerifyAuthResultReq)returns(VerifyAuthResultResp); // LineCodeToAccessToken Line 驗證相關 - rpc LineCodeToAccessToken(NoneReq) returns (LineAccessTokenResp); + rpc LineCodeToAccessToken(LineGetTokenReq) returns (LineAccessTokenResp); // LineGetProfileByAccessToken Line 驗證相關 - rpc LineGetProfileByAccessToken(NoneReq) returns (LineUserProfile); + rpc LineGetProfileByAccessToken(LineGetUserInfoReq) returns (LineUserProfile); } // ================ account ================ \ No newline at end of file diff --git a/go.mod b/go.mod index 2d03672..b42787d 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module app-cloudep-member-server +module code.30cm.net/digimon/app-cloudep-member-server go 1.23.4 diff --git a/internal/config/config.go b/internal/config/config.go index 8d436f1..c05eb6b 100755 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -1,15 +1,14 @@ 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" "time" + + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/zrpc" ) type Config struct { zrpc.RpcServerConf - redis.RedisConf // Redis Cluster Cache cache.CacheConf CacheExpireTime time.Duration diff --git a/internal/logic/account/bind_account_logic.go b/internal/logic/account/bind_account_logic.go index eaa3184..850e89f 100644 --- a/internal/logic/account/bind_account_logic.go +++ b/internal/logic/account/bind_account_logic.go @@ -1,15 +1,16 @@ package accountlogic import ( - domain "app-cloudep-member-server/pkg/domain/member" - "app-cloudep-member-server/pkg/domain/usecase" - "code.30cm.net/digimon/library-go/errs" "context" "fmt" "math" - "app-cloudep-member-server/gen_result/pb/member" - "app-cloudep-member-server/internal/svc" + domain "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/member" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/usecase" + "code.30cm.net/digimon/library-go/errs" + + "code.30cm.net/digimon/app-cloudep-member-server/gen_result/pb/member" + "code.30cm.net/digimon/app-cloudep-member-server/internal/svc" "github.com/zeromicro/go-zero/core/logx" ) @@ -43,43 +44,30 @@ func (l *BindAccountLogic) BindAccount(in *member.BindingUserReq) (*member.Bindi }); err != nil { return nil, errs.InvalidFormat(err.Error()) } - - // 先確定有這個Account - if _, err := l.svcCtx.AccountUseCase.GetUserAccountInfo(l.ctx, usecase.GetUIDByAccountRequest{Account: in.GetLoginId()}); err != nil { - return nil, err - } - - var err error - uid := in.GetUid() - // 有 UID 綁看看,沒帶UID 近來,確認沒重複就直接綁一個給他 - if in.GetUid() == "" { - uid, err = l.svcCtx.AccountUseCase.Generate(l.ctx) - if err != nil { - return nil, err - } - } - t, err := int64ToInt32Safe(in.GetType()) + s, err := safeInt64ToInt32(in.GetType()) if err != nil { return nil, err } - if _, err := l.svcCtx.AccountUseCase.BindAccount(l.ctx, usecase.BindingUser{ - LoginID: in.LoginId, - UID: uid, - Type: domain.AccountType(t), - }); err != nil { + account, err := l.svcCtx.AccountUseCase.BindAccount(l.ctx, usecase.BindingUser{ + UID: in.GetUid(), + LoginID: in.GetLoginId(), + Type: domain.AccountType(s), + }) + if err != nil { return nil, err } return &member.BindingUserResp{ - LoginId: in.LoginId, - Uid: uid, + LoginId: account.LoginID, + Uid: account.UID, Type: in.GetType(), }, nil } -func int64ToInt32Safe(value int64) (int32, error) { - if value > math.MaxInt32 || value < math.MinInt32 { - return 0, fmt.Errorf("value %d is out of int32 range", value) +func safeInt64ToInt32(n int64) (int32, error) { + if n < math.MinInt32 || n > math.MaxInt32 { + return 0, fmt.Errorf("int64 value %d out of int8 range", n) } - return int32(value), nil + + return int32(n), nil } diff --git a/internal/logic/account/bind_user_info_logic.go b/internal/logic/account/bind_user_info_logic.go index e1aed1c..ad4aceb 100644 --- a/internal/logic/account/bind_user_info_logic.go +++ b/internal/logic/account/bind_user_info_logic.go @@ -1,11 +1,15 @@ package accountlogic import ( - "app-cloudep-member-server/gen_result/pb/member" - "app-cloudep-member-server/internal/svc" "context" + "code.30cm.net/digimon/app-cloudep-member-server/gen_result/pb/member" + "code.30cm.net/digimon/app-cloudep-member-server/internal/svc" + domain "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/member" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/usecase" + "code.30cm.net/digimon/library-go/errs" "github.com/zeromicro/go-zero/core/logx" + "google.golang.org/protobuf/proto" ) type BindUserInfoLogic struct { @@ -22,25 +26,42 @@ 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 `validate:"required"` -} - +// 必要的還是在這邊驗一次好了 type createUserInfoReq struct { - Uid string `validate:"required"` // 唯一辨識碼 + UID string `validate:"required"` // 唯一辨識碼 Language string `validate:"required"` Currency string `validate:"required"` } // BindUserInfo 初次,綁定 User Info func (l *BindUserInfoLogic) BindUserInfo(in *member.CreateUserInfoReq) (*member.OKResp, error) { + // 驗證資料 + if err := l.svcCtx.Validate.ValidateAll(&createUserInfoReq{ + UID: in.GetUid(), + Language: in.GetLanguage(), + Currency: in.GetCurrency(), + }); err != nil { + return nil, errs.InvalidFormat(err.Error()) + } + + err := l.svcCtx.AccountUseCase.BindUserInfo(l.ctx, usecase.CreateUserInfoRequest{ + UID: in.GetUid(), + AvatarURL: proto.String(in.GetAvatar()), + FullName: proto.String(in.GetFullName()), + Nickname: proto.String(in.GetNickName()), + GenderCode: proto.Int64(in.GetGender()), + Birthdate: proto.Int64(in.GetBirthdate()), + PhoneNumber: proto.String(in.GetPhoneNumber()), + Email: proto.String(in.GetEmail()), + Address: proto.String(in.GetAddress()), + PreferredLanguage: in.GetLanguage(), + Currency: in.GetCurrency(), + AlarmCategory: domain.AlarmType(in.GetAlarmType().Number()), + UserStatus: domain.Status(in.GetStatus().Number()), + }) + if err != nil { + return nil, err + } return &member.OKResp{}, nil } diff --git a/internal/logic/account/bind_verify_email_logic.go b/internal/logic/account/bind_verify_email_logic.go index 3b264a8..06b12ad 100644 --- a/internal/logic/account/bind_verify_email_logic.go +++ b/internal/logic/account/bind_verify_email_logic.go @@ -3,8 +3,10 @@ package accountlogic import ( "context" - "app-cloudep-member-server/gen_result/pb/member" - "app-cloudep-member-server/internal/svc" + "code.30cm.net/digimon/library-go/errs" + + "code.30cm.net/digimon/app-cloudep-member-server/gen_result/pb/member" + "code.30cm.net/digimon/app-cloudep-member-server/internal/svc" "github.com/zeromicro/go-zero/core/logx" ) @@ -23,9 +25,24 @@ func NewBindVerifyEmailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *B } } +type bindEmailVerifyReq struct { + UID string `validate:"required"` // 唯一辨識碼 + Email string `validate:"required"` // 唯一辨識碼 +} + // BindVerifyEmail 綁定 Email func (l *BindVerifyEmailLogic) BindVerifyEmail(in *member.BindVerifyEmailReq) (*member.OKResp, error) { - // todo: add your logic here and delete this line + if err := l.svcCtx.Validate.ValidateAll(&bindEmailVerifyReq{ + UID: in.GetUid(), + Email: in.GetEmail(), + }); err != nil { + return nil, errs.InvalidFormat(err.Error()) + } + + err := l.svcCtx.AccountUseCase.BindVerifyEmail(l.ctx, in.GetUid(), in.GetEmail()) + if err != nil { + return nil, err + } return &member.OKResp{}, nil } diff --git a/internal/logic/account/bind_verify_phone_logic.go b/internal/logic/account/bind_verify_phone_logic.go index 7ec68fb..fabb432 100644 --- a/internal/logic/account/bind_verify_phone_logic.go +++ b/internal/logic/account/bind_verify_phone_logic.go @@ -3,8 +3,10 @@ package accountlogic import ( "context" - "app-cloudep-member-server/gen_result/pb/member" - "app-cloudep-member-server/internal/svc" + "code.30cm.net/digimon/library-go/errs" + + "code.30cm.net/digimon/app-cloudep-member-server/gen_result/pb/member" + "code.30cm.net/digimon/app-cloudep-member-server/internal/svc" "github.com/zeromicro/go-zero/core/logx" ) @@ -23,9 +25,24 @@ func NewBindVerifyPhoneLogic(ctx context.Context, svcCtx *svc.ServiceContext) *B } } +type bindPhoneVerifyReq struct { + UID string `validate:"required"` // 唯一辨識碼 + Phone string `validate:"required"` // 唯一辨識碼 +} + // BindVerifyPhone 綁定 Phone func (l *BindVerifyPhoneLogic) BindVerifyPhone(in *member.BindVerifyPhoneReq) (*member.OKResp, error) { - // todo: add your logic here and delete this line + if err := l.svcCtx.Validate.ValidateAll(&bindPhoneVerifyReq{ + UID: in.GetUid(), + Phone: in.GetPhone(), + }); err != nil { + return nil, errs.InvalidFormat(err.Error()) + } + + err := l.svcCtx.AccountUseCase.BindVerifyPhone(l.ctx, in.GetUid(), in.GetPhone()) + if err != nil { + return nil, err + } return &member.OKResp{}, nil } diff --git a/internal/logic/account/check_refresh_code_logic.go b/internal/logic/account/check_refresh_code_logic.go index e4f3ce5..6d74bc8 100644 --- a/internal/logic/account/check_refresh_code_logic.go +++ b/internal/logic/account/check_refresh_code_logic.go @@ -3,8 +3,12 @@ package accountlogic import ( "context" - "app-cloudep-member-server/gen_result/pb/member" - "app-cloudep-member-server/internal/svc" + domain "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/member" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/usecase" + "code.30cm.net/digimon/library-go/errs" + + "code.30cm.net/digimon/app-cloudep-member-server/gen_result/pb/member" + "code.30cm.net/digimon/app-cloudep-member-server/internal/svc" "github.com/zeromicro/go-zero/core/logx" ) @@ -23,9 +27,35 @@ func NewCheckRefreshCodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) * } } +type checkRefreshCodeReq struct { + LoginID string `validate:"required"` + VerifyCode string `validate:"required"` +} + // CheckRefreshCode 驗證忘記密碼 token 不刪除,只確認) func (l *CheckRefreshCodeLogic) CheckRefreshCode(in *member.VerifyRefreshCodeReq) (*member.OKResp, error) { - // todo: add your logic here and delete this line + // 驗證資料 + if err := l.svcCtx.Validate.ValidateAll(&checkRefreshCodeReq{ + LoginID: in.GetAccount(), + VerifyCode: in.GetVerifyCode(), + }); err != nil { + return nil, errs.InvalidFormat(err.Error()) + } + code := domain.GenerateCodeType(in.GetCodeType()) + _, status := domain.GetCodeNameByCode(code) + if !status { + return nil, errs.InvalidFormat("codeType is invalid") + } + + // 執行 + err := l.svcCtx.AccountUseCase.CheckRefreshCode(l.ctx, usecase.VerifyRefreshCodeRequest{ + LoginID: in.GetAccount(), + VerifyCode: in.GetVerifyCode(), + CodeType: code, + }) + if err != nil { + return nil, err + } return &member.OKResp{}, nil } diff --git a/internal/logic/account/create_user_account_logic.go b/internal/logic/account/create_user_account_logic.go index 1665198..6e6a694 100644 --- a/internal/logic/account/create_user_account_logic.go +++ b/internal/logic/account/create_user_account_logic.go @@ -2,9 +2,15 @@ package accountlogic import ( "context" + "fmt" + "math" - "app-cloudep-member-server/gen_result/pb/member" - "app-cloudep-member-server/internal/svc" + domain "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/member" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/usecase" + "code.30cm.net/digimon/library-go/errs" + + "code.30cm.net/digimon/app-cloudep-member-server/gen_result/pb/member" + "code.30cm.net/digimon/app-cloudep-member-server/internal/svc" "github.com/zeromicro/go-zero/core/logx" ) @@ -23,9 +29,47 @@ func NewCreateUserAccountLogic(ctx context.Context, svcCtx *svc.ServiceContext) } } +type createUserAccountReq struct { + LoginID string `validate:"required"` + Token string `validate:"required"` +} + // CreateUserAccount 建立帳號與密碼 -> 可登入,但可不可以做其他事情看業務流程,也可以只註冊就好 func (l *CreateUserAccountLogic) CreateUserAccount(in *member.CreateLoginUserReq) (*member.OKResp, error) { - // todo: add your logic here and delete this line + // 驗證資料 + if err := l.svcCtx.Validate.ValidateAll(&createUserAccountReq{ + LoginID: in.GetLoginId(), + Token: in.GetToken(), + }); err != nil { + return nil, errs.InvalidFormat(err.Error()) + } + + toInt8, err := safeInt64ToInt8(in.GetPlatform()) + if err != nil { + return nil, err + } + + platform := domain.Platform(toInt8) + if platform.ToString() == "" { + return nil, errs.InvalidFormat("platform not found") + } + + err = l.svcCtx.AccountUseCase.CreateUserAccount(l.ctx, usecase.CreateLoginUserRequest{ + LoginID: in.GetLoginId(), + Platform: platform, + Token: in.GetToken(), + }) + if err != nil { + return nil, err + } return &member.OKResp{}, nil } + +func safeInt64ToInt8(n int64) (int8, error) { + if n < math.MinInt8 || n > math.MaxInt8 { + return 0, fmt.Errorf("int64 value %d out of int8 range", n) + } + + return int8(n), nil +} diff --git a/internal/logic/account/generate_refresh_code_logic.go b/internal/logic/account/generate_refresh_code_logic.go index 593b86e..f388b02 100644 --- a/internal/logic/account/generate_refresh_code_logic.go +++ b/internal/logic/account/generate_refresh_code_logic.go @@ -3,8 +3,11 @@ package accountlogic import ( "context" - "app-cloudep-member-server/gen_result/pb/member" - "app-cloudep-member-server/internal/svc" + "code.30cm.net/digimon/app-cloudep-member-server/gen_result/pb/member" + "code.30cm.net/digimon/app-cloudep-member-server/internal/svc" + domain "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/member" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/usecase" + "code.30cm.net/digimon/library-go/errs" "github.com/zeromicro/go-zero/core/logx" ) @@ -23,9 +26,34 @@ func NewGenerateRefreshCodeLogic(ctx context.Context, svcCtx *svc.ServiceContext } } +type generateRefreshCodeReq struct { + LoginID string `validate:"required"` +} + // 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{ + LoginID: in.GetAccount(), + }); err != nil { + return nil, errs.InvalidFormat(err.Error()) + } + ct := domain.GenerateCodeType(in.GetCodeType()) + _, status := domain.GetCodeNameByCode(ct) + if !status { + return nil, errs.InvalidFormat("codeType is invalid") + } - return &member.GenerateRefreshCodeResp{}, nil + // 產生 + code, err := l.svcCtx.AccountUseCase.GenerateRefreshCode(l.ctx, usecase.GenerateRefreshCodeRequest{ + LoginID: in.GetAccount(), + CodeType: ct, + }) + if err != nil { + return nil, err + } + + return &member.GenerateRefreshCodeResp{ + Data: &member.VerifyCode{VerifyCode: code.Data.VerifyCode}, + }, nil } diff --git a/internal/logic/account/get_u_i_d_by_account_logic.go b/internal/logic/account/get_u_i_d_by_account_logic.go index 07aacdf..a26b6d3 100644 --- a/internal/logic/account/get_u_i_d_by_account_logic.go +++ b/internal/logic/account/get_u_i_d_by_account_logic.go @@ -3,8 +3,11 @@ package accountlogic import ( "context" - "app-cloudep-member-server/gen_result/pb/member" - "app-cloudep-member-server/internal/svc" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/usecase" + "code.30cm.net/digimon/library-go/errs" + + "code.30cm.net/digimon/app-cloudep-member-server/gen_result/pb/member" + "code.30cm.net/digimon/app-cloudep-member-server/internal/svc" "github.com/zeromicro/go-zero/core/logx" ) @@ -23,9 +26,27 @@ func NewGetUIDByAccountLogic(ctx context.Context, svcCtx *svc.ServiceContext) *G } } +type getUIDByAccountReq struct { + Account string `validate:"required"` +} + // 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, errs.InvalidFormat(err.Error()) + } - return &member.GetUIDByAccountResp{}, nil + account, err := l.svcCtx.AccountUseCase.GetUIDByAccount(l.ctx, usecase.GetUIDByAccountRequest{ + Account: in.GetAccount(), + }) + if err != nil { + return nil, err + } + + return &member.GetUIDByAccountResp{ + Account: account.Account, + Uid: account.UID, + }, nil } diff --git a/internal/logic/account/get_user_account_info_logic.go b/internal/logic/account/get_user_account_info_logic.go index 8fc5d17..62bcb67 100644 --- a/internal/logic/account/get_user_account_info_logic.go +++ b/internal/logic/account/get_user_account_info_logic.go @@ -3,8 +3,11 @@ package accountlogic import ( "context" - "app-cloudep-member-server/gen_result/pb/member" - "app-cloudep-member-server/internal/svc" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/usecase" + "code.30cm.net/digimon/library-go/errs" + + "code.30cm.net/digimon/app-cloudep-member-server/gen_result/pb/member" + "code.30cm.net/digimon/app-cloudep-member-server/internal/svc" "github.com/zeromicro/go-zero/core/logx" ) @@ -23,9 +26,30 @@ func NewGetUserAccountInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) } } +type getUserAccountInfoReq struct { + Account string `validate:"required"` +} + // GetUserAccountInfo 取得帳號密碼資料 func (l *GetUserAccountInfoLogic) GetUserAccountInfo(in *member.GetUIDByAccountReq) (*member.GetAccountInfoResp, error) { - // todo: add your logic here and delete this line + if err := l.svcCtx.Validate.ValidateAll(&getUserAccountInfoReq{ + Account: in.GetAccount(), + }); err != nil { + return nil, errs.InvalidFormat(err.Error()) + } - return &member.GetAccountInfoResp{}, nil + info, err := l.svcCtx.AccountUseCase.GetUserAccountInfo(l.ctx, usecase.GetUIDByAccountRequest{ + Account: in.GetAccount(), + }) + if err != nil { + return nil, err + } + + return &member.GetAccountInfoResp{ + Data: &member.CreateLoginUserReq{ + LoginId: info.Data.LoginID, + Token: info.Data.Token, + Platform: info.Data.Platform.ToInt64(), + }, + }, nil } diff --git a/internal/logic/account/get_user_info_logic.go b/internal/logic/account/get_user_info_logic.go index 3dfca9a..74f48f2 100644 --- a/internal/logic/account/get_user_info_logic.go +++ b/internal/logic/account/get_user_info_logic.go @@ -3,8 +3,9 @@ package accountlogic import ( "context" - "app-cloudep-member-server/gen_result/pb/member" - "app-cloudep-member-server/internal/svc" + "code.30cm.net/digimon/app-cloudep-member-server/gen_result/pb/member" + "code.30cm.net/digimon/app-cloudep-member-server/internal/svc" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/usecase" "github.com/zeromicro/go-zero/core/logx" ) @@ -25,7 +26,31 @@ func NewGetUserInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUs // GetUserInfo 取得會員資訊 func (l *GetUserInfoLogic) GetUserInfo(in *member.GetUserInfoReq) (*member.GetUserInfoResp, error) { - // todo: add your logic here and delete this line + info, err := l.svcCtx.AccountUseCase.GetUserInfo(l.ctx, usecase.GetUserInfoRequest{ + UID: in.GetUid(), + NickName: in.GetNickName(), + }) + if err != nil { + return nil, err + } - return &member.GetUserInfoResp{}, nil + return &member.GetUserInfoResp{ + Data: &member.UserInfo{ + Uid: info.UID, + AvatarUrl: info.AvatarURL, + NickName: info.Nickname, + FullName: info.FullName, + GenderCode: info.GenderCode, + Birthday: info.Birthdate, + Phone: info.PhoneNumber, + Email: info.Email, + Address: info.Address, + AlarmType: member.AlarmType(info.AlarmCategory), + Status: member.MemberStatus(info.UserStatus), + Language: info.PreferredLanguage, + Currency: info.Currency, + CreateTime: info.CreateTime, + UpdateTime: info.UpdateTime, + }, + }, nil } diff --git a/internal/logic/account/line_code_to_access_token_logic.go b/internal/logic/account/line_code_to_access_token_logic.go index a36721c..069461a 100644 --- a/internal/logic/account/line_code_to_access_token_logic.go +++ b/internal/logic/account/line_code_to_access_token_logic.go @@ -3,8 +3,8 @@ package accountlogic import ( "context" - "app-cloudep-member-server/gen_result/pb/member" - "app-cloudep-member-server/internal/svc" + "code.30cm.net/digimon/app-cloudep-member-server/gen_result/pb/member" + "code.30cm.net/digimon/app-cloudep-member-server/internal/svc" "github.com/zeromicro/go-zero/core/logx" ) @@ -24,8 +24,13 @@ func NewLineCodeToAccessTokenLogic(ctx context.Context, svcCtx *svc.ServiceConte } // LineCodeToAccessToken Line 驗證相關 -func (l *LineCodeToAccessTokenLogic) LineCodeToAccessToken(in *member.NoneReq) (*member.LineAccessTokenResp, error) { - // todo: add your logic here and delete this line +func (l *LineCodeToAccessTokenLogic) LineCodeToAccessToken(in *member.LineGetTokenReq) (*member.LineAccessTokenResp, error) { + token, err := l.svcCtx.AccountUseCase.LineCodeToAccessToken(l.ctx, in.GetCode()) + if err != nil { + return nil, err + } - return &member.LineAccessTokenResp{}, nil + return &member.LineAccessTokenResp{ + Token: token.AccessToken, + }, nil } diff --git a/internal/logic/account/line_get_profile_by_access_token_logic.go b/internal/logic/account/line_get_profile_by_access_token_logic.go index 594b3fd..d1b6221 100644 --- a/internal/logic/account/line_get_profile_by_access_token_logic.go +++ b/internal/logic/account/line_get_profile_by_access_token_logic.go @@ -3,8 +3,8 @@ package accountlogic import ( "context" - "app-cloudep-member-server/gen_result/pb/member" - "app-cloudep-member-server/internal/svc" + "code.30cm.net/digimon/app-cloudep-member-server/gen_result/pb/member" + "code.30cm.net/digimon/app-cloudep-member-server/internal/svc" "github.com/zeromicro/go-zero/core/logx" ) @@ -24,8 +24,16 @@ func NewLineGetProfileByAccessTokenLogic(ctx context.Context, svcCtx *svc.Servic } // LineGetProfileByAccessToken Line 驗證相關 -func (l *LineGetProfileByAccessTokenLogic) LineGetProfileByAccessToken(in *member.NoneReq) (*member.LineUserProfile, error) { - // todo: add your logic here and delete this line +func (l *LineGetProfileByAccessTokenLogic) LineGetProfileByAccessToken(in *member.LineGetUserInfoReq) (*member.LineUserProfile, error) { + user, err := l.svcCtx.AccountUseCase.LineGetProfileByAccessToken(l.ctx, in.GetToken()) + if err != nil { + return nil, err + } - return &member.LineUserProfile{}, nil + return &member.LineUserProfile{ + DisplayName: user.DisplayName, + UserId: user.UserID, + PictureUrl: user.PictureURL, + StatusMessage: user.StatusMessage, + }, nil } diff --git a/internal/logic/account/list_member_logic.go b/internal/logic/account/list_member_logic.go index fd11136..d6f0840 100644 --- a/internal/logic/account/list_member_logic.go +++ b/internal/logic/account/list_member_logic.go @@ -3,8 +3,11 @@ package accountlogic import ( "context" - "app-cloudep-member-server/gen_result/pb/member" - "app-cloudep-member-server/internal/svc" + pb "code.30cm.net/digimon/app-cloudep-member-server/gen_result/pb/member" + "code.30cm.net/digimon/app-cloudep-member-server/internal/svc" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/member" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/usecase" + "google.golang.org/protobuf/proto" "github.com/zeromicro/go-zero/core/logx" ) @@ -24,8 +27,72 @@ func NewListMemberLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListMe } // ListMember 取得會員列表 -func (l *ListMemberLogic) ListMember(in *member.ListUserInfoReq) (*member.ListUserInfoResp, error) { - // todo: add your logic here and delete this line +func (l *ListMemberLogic) ListMember(in *pb.ListUserInfoReq) (*pb.ListUserInfoResp, error) { + q := usecase.ListUserInfoRequest{ + PageSize: in.GetPageSize(), + PageIndex: in.GetPageIndex(), + } + if in.CreateStartTime != nil { + q.CreateStartTime = proto.Int64(in.GetCreateStartTime()) + } - return &member.ListUserInfoResp{}, nil + if in.CreateEndTime != nil { + q.CreateEndTime = proto.Int64(in.GetCreateEndTime()) + } + if in.AlarmType != nil { + a := member.AlarmType(in.GetAlarmType().Number()) + q.AlarmCategory = &a + } + + if in.Status != nil { + s := member.Status(in.GetStatus().Number()) + q.UserStatus = &s + } + + members, err := l.svcCtx.AccountUseCase.ListMember(l.ctx, q) + if err != nil { + return nil, err + } + res := make([]*pb.UserInfo, 0, members.Page.Size) + if len(members.Data) == 0 { + return &pb.ListUserInfoResp{ + Data: res, + Page: &pb.Pager{ + Total: 0, + Size: members.Page.Size, + Index: members.Page.Index, + }, + }, nil + } + at := pb.AlarmType(members.Data[0].AlarmCategory) + status := pb.MemberStatus(members.Data[0].UserStatus) + + for _, m := range members.Data { + res = append(res, &pb.UserInfo{ + Uid: m.UID, + AvatarUrl: m.AvatarURL, + FullName: m.FullName, + NickName: m.Nickname, + GenderCode: m.GenderCode, + Birthday: m.Birthdate, + Address: m.Address, + Email: m.Email, + Phone: m.PhoneNumber, + Language: m.PreferredLanguage, + Currency: m.Currency, + AlarmType: at, + Status: status, + CreateTime: m.CreateTime, + UpdateTime: m.UpdateTime, + }) + } + + return &pb.ListUserInfoResp{ + Data: res, + Page: &pb.Pager{ + Total: members.Page.Total, + Size: members.Page.Size, + Index: members.Page.Index, + }, + }, nil } diff --git a/internal/logic/account/update_status_logic.go b/internal/logic/account/update_status_logic.go index 3bc6ced..4712c93 100644 --- a/internal/logic/account/update_status_logic.go +++ b/internal/logic/account/update_status_logic.go @@ -3,8 +3,12 @@ package accountlogic import ( "context" - "app-cloudep-member-server/gen_result/pb/member" - "app-cloudep-member-server/internal/svc" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/member" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/usecase" + "code.30cm.net/digimon/library-go/errs" + + pb "code.30cm.net/digimon/app-cloudep-member-server/gen_result/pb/member" + "code.30cm.net/digimon/app-cloudep-member-server/internal/svc" "github.com/zeromicro/go-zero/core/logx" ) @@ -24,8 +28,16 @@ func NewUpdateStatusLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Upda } // UpdateStatus 修改狀態 -func (l *UpdateStatusLogic) UpdateStatus(in *member.UpdateStatusReq) (*member.OKResp, error) { - // todo: add your logic here and delete this line +func (l *UpdateStatusLogic) UpdateStatus(in *pb.UpdateStatusReq) (*pb.OKResp, error) { + if in.Status == pb.MemberStatus_STATUS_NONE { + return nil, errs.InvalidFormat("failed to get correct status") + } - return &member.OKResp{}, nil + s := member.Status(in.GetStatus().Number()) + err := l.svcCtx.AccountUseCase.UpdateStatus(l.ctx, usecase.UpdateStatusRequest{Status: s, UID: in.GetUid()}) + if err != nil { + return nil, err + } + + return &pb.OKResp{}, nil } diff --git a/internal/logic/account/update_user_info_logic.go b/internal/logic/account/update_user_info_logic.go index c1a3806..b2a36b4 100644 --- a/internal/logic/account/update_user_info_logic.go +++ b/internal/logic/account/update_user_info_logic.go @@ -3,8 +3,11 @@ package accountlogic import ( "context" - "app-cloudep-member-server/gen_result/pb/member" - "app-cloudep-member-server/internal/svc" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/member" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/usecase" + + pb "code.30cm.net/digimon/app-cloudep-member-server/gen_result/pb/member" + "code.30cm.net/digimon/app-cloudep-member-server/internal/svc" "github.com/zeromicro/go-zero/core/logx" ) @@ -24,8 +27,39 @@ func NewUpdateUserInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Up } // UpdateUserInfo 更新 User Info -func (l *UpdateUserInfoLogic) UpdateUserInfo(in *member.UpdateUserInfoReq) (*member.OKResp, error) { - // todo: add your logic here and delete this line +func (l *UpdateUserInfoLogic) UpdateUserInfo(in *pb.UpdateUserInfoReq) (*pb.OKResp, error) { + q := usecase.UpdateUserInfoRequest{ + UID: in.GetUid(), + AvatarURL: in.Avatar, + FullName: in.FullName, + Nickname: in.NickName, + Birthdate: in.Birthdate, + Address: in.Address, + PreferredLanguage: in.Language, + Currency: in.Currency, + } + if in.Gender != nil { + c := *in.Gender + code, err := safeInt64ToInt8(c) + if err == nil { + q.GenderCode = &code + } + } - return &member.OKResp{}, nil + if in.AlarmType != nil { + a := member.AlarmType(in.GetAlarmType().Number()) + q.AlarmCategory = &a + } + + if in.Status != nil { + s := member.Status(in.GetStatus().Number()) + q.UserStatus = &s + } + + err := l.svcCtx.AccountUseCase.UpdateUserInfo(l.ctx, &q) + if err != nil { + return nil, err + } + + return &pb.OKResp{}, nil } diff --git a/internal/logic/account/update_user_token_logic.go b/internal/logic/account/update_user_token_logic.go index ad3b9be..d2df588 100644 --- a/internal/logic/account/update_user_token_logic.go +++ b/internal/logic/account/update_user_token_logic.go @@ -3,8 +3,10 @@ package accountlogic import ( "context" - "app-cloudep-member-server/gen_result/pb/member" - "app-cloudep-member-server/internal/svc" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/usecase" + + "code.30cm.net/digimon/app-cloudep-member-server/gen_result/pb/member" + "code.30cm.net/digimon/app-cloudep-member-server/internal/svc" "github.com/zeromicro/go-zero/core/logx" ) @@ -25,7 +27,15 @@ func NewUpdateUserTokenLogic(ctx context.Context, svcCtx *svc.ServiceContext) *U // UpdateUserToken 更新密碼 func (l *UpdateUserTokenLogic) UpdateUserToken(in *member.UpdateTokenReq) (*member.OKResp, error) { - // todo: add your logic here and delete this line + // 更新密碼 + err := l.svcCtx.AccountUseCase.UpdateUserToken(l.ctx, usecase.UpdateTokenRequest{ + Account: in.GetAccount(), + Token: in.GetToken(), + Platform: in.GetPlatform(), + }) + if err != nil { + return nil, err + } return &member.OKResp{}, nil } diff --git a/internal/logic/account/verify_google_auth_result_logic.go b/internal/logic/account/verify_google_auth_result_logic.go index 842fb04..5dffff0 100644 --- a/internal/logic/account/verify_google_auth_result_logic.go +++ b/internal/logic/account/verify_google_auth_result_logic.go @@ -3,8 +3,10 @@ package accountlogic import ( "context" - "app-cloudep-member-server/gen_result/pb/member" - "app-cloudep-member-server/internal/svc" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/usecase" + + "code.30cm.net/digimon/app-cloudep-member-server/gen_result/pb/member" + "code.30cm.net/digimon/app-cloudep-member-server/internal/svc" "github.com/zeromicro/go-zero/core/logx" ) @@ -24,8 +26,26 @@ func NewVerifyGoogleAuthResultLogic(ctx context.Context, svcCtx *svc.ServiceCont } // VerifyGoogleAuthResult 驗證 google 登入是否有效 -func (l *VerifyGoogleAuthResultLogic) VerifyGoogleAuthResult(in *member.VerifyAuthResultReq) (*member.VerifyAuthResultResp, error) { - // todo: add your logic here and delete this line +func (l *VerifyGoogleAuthResultLogic) VerifyGoogleAuthResult(in *member.VerifyAuthResultReq) (*member.VerifyGoogleAuthResultResp, error) { + result, err := l.svcCtx.AccountUseCase.VerifyGoogleAuthResult(l.ctx, usecase.VerifyAuthResultRequest{ + Account: in.GetAccount(), + Token: in.GetToken(), + }) + if err != nil { + return &member.VerifyGoogleAuthResultResp{ + Status: false, + }, err + } - return &member.VerifyAuthResultResp{}, nil + return &member.VerifyGoogleAuthResultResp{ + Status: true, + Iss: &result.Iss, + Aud: &result.Aud, + Exp: &result.Exp, + Iat: &result.Iat, + Email: &result.Email, + EmailVerified: &result.EmailVerified, + Name: &result.Name, + Picture: &result.Picture, + }, nil } diff --git a/internal/logic/account/verify_platform_auth_result_logic.go b/internal/logic/account/verify_platform_auth_result_logic.go index 2007051..6931b0e 100644 --- a/internal/logic/account/verify_platform_auth_result_logic.go +++ b/internal/logic/account/verify_platform_auth_result_logic.go @@ -3,8 +3,10 @@ package accountlogic import ( "context" - "app-cloudep-member-server/gen_result/pb/member" - "app-cloudep-member-server/internal/svc" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/usecase" + + "code.30cm.net/digimon/app-cloudep-member-server/gen_result/pb/member" + "code.30cm.net/digimon/app-cloudep-member-server/internal/svc" "github.com/zeromicro/go-zero/core/logx" ) @@ -25,7 +27,15 @@ func NewVerifyPlatformAuthResultLogic(ctx context.Context, svcCtx *svc.ServiceCo // VerifyPlatformAuthResult 驗證 google 登入是否有效 func (l *VerifyPlatformAuthResultLogic) VerifyPlatformAuthResult(in *member.VerifyAuthResultReq) (*member.VerifyAuthResultResp, error) { - // todo: add your logic here and delete this line + result, err := l.svcCtx.AccountUseCase.VerifyPlatformAuthResult(l.ctx, usecase.VerifyAuthResultRequest{ + Account: in.GetAccount(), + Token: in.GetToken(), + }) + if err != nil { + return nil, err + } - return &member.VerifyAuthResultResp{}, nil + return &member.VerifyAuthResultResp{ + Status: result.Status, + }, nil } diff --git a/internal/logic/account/verify_refresh_code_logic.go b/internal/logic/account/verify_refresh_code_logic.go index 0cfdfa3..40481a8 100644 --- a/internal/logic/account/verify_refresh_code_logic.go +++ b/internal/logic/account/verify_refresh_code_logic.go @@ -3,8 +3,12 @@ package accountlogic import ( "context" - "app-cloudep-member-server/gen_result/pb/member" - "app-cloudep-member-server/internal/svc" + domain "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/member" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/usecase" + "code.30cm.net/digimon/library-go/errs" + + "code.30cm.net/digimon/app-cloudep-member-server/gen_result/pb/member" + "code.30cm.net/digimon/app-cloudep-member-server/internal/svc" "github.com/zeromicro/go-zero/core/logx" ) @@ -23,9 +27,30 @@ func NewVerifyRefreshCodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) } } +type verifyRefreshCodeRequest struct { + LoginID string `validate:"required"` + VerifyCode string `validate:"required"` + CodeType int32 `validate:"required"` +} + // VerifyRefreshCode 驗證忘記密碼 token func (l *VerifyRefreshCodeLogic) VerifyRefreshCode(in *member.VerifyRefreshCodeReq) (*member.OKResp, error) { - // todo: add your logic here and delete this line + if err := l.svcCtx.Validate.ValidateAll(&verifyRefreshCodeRequest{ + LoginID: in.Account, + VerifyCode: in.VerifyCode, + CodeType: in.CodeType, + }); err != nil { + return nil, errs.InvalidFormat(err.Error()) + } + + err := l.svcCtx.AccountUseCase.VerifyRefreshCode(l.ctx, usecase.VerifyRefreshCodeRequest{ + LoginID: in.Account, + VerifyCode: in.VerifyCode, + CodeType: domain.GenerateCodeType(in.GetCodeType()), + }) + if err != nil { + return nil, err + } return &member.OKResp{}, nil } diff --git a/internal/server/account/account_server.go b/internal/server/account/account_server.go index f08bc35..8dbeff7 100644 --- a/internal/server/account/account_server.go +++ b/internal/server/account/account_server.go @@ -7,9 +7,9 @@ package server import ( "context" - "app-cloudep-member-server/gen_result/pb/member" - accountlogic "app-cloudep-member-server/internal/logic/account" - "app-cloudep-member-server/internal/svc" + "code.30cm.net/digimon/app-cloudep-member-server/gen_result/pb/member" + accountlogic "code.30cm.net/digimon/app-cloudep-member-server/internal/logic/account" + "code.30cm.net/digimon/app-cloudep-member-server/internal/svc" ) type AccountServer struct { @@ -114,7 +114,7 @@ func (s *AccountServer) CheckRefreshCode(ctx context.Context, in *member.VerifyR } // VerifyGoogleAuthResult 驗證 google 登入是否有效 -func (s *AccountServer) VerifyGoogleAuthResult(ctx context.Context, in *member.VerifyAuthResultReq) (*member.VerifyAuthResultResp, error) { +func (s *AccountServer) VerifyGoogleAuthResult(ctx context.Context, in *member.VerifyAuthResultReq) (*member.VerifyGoogleAuthResultResp, error) { l := accountlogic.NewVerifyGoogleAuthResultLogic(ctx, s.svcCtx) return l.VerifyGoogleAuthResult(in) } @@ -126,13 +126,13 @@ func (s *AccountServer) VerifyPlatformAuthResult(ctx context.Context, in *member } // LineCodeToAccessToken Line 驗證相關 -func (s *AccountServer) LineCodeToAccessToken(ctx context.Context, in *member.NoneReq) (*member.LineAccessTokenResp, error) { +func (s *AccountServer) LineCodeToAccessToken(ctx context.Context, in *member.LineGetTokenReq) (*member.LineAccessTokenResp, error) { l := accountlogic.NewLineCodeToAccessTokenLogic(ctx, s.svcCtx) return l.LineCodeToAccessToken(in) } // LineGetProfileByAccessToken Line 驗證相關 -func (s *AccountServer) LineGetProfileByAccessToken(ctx context.Context, in *member.NoneReq) (*member.LineUserProfile, error) { +func (s *AccountServer) LineGetProfileByAccessToken(ctx context.Context, in *member.LineGetUserInfoReq) (*member.LineUserProfile, error) { l := accountlogic.NewLineGetProfileByAccessTokenLogic(ctx, s.svcCtx) return l.LineGetProfileByAccessToken(in) } diff --git a/internal/svc/service_context.go b/internal/svc/service_context.go index 427669b..647e133 100644 --- a/internal/svc/service_context.go +++ b/internal/svc/service_context.go @@ -1,11 +1,13 @@ package svc import ( - "app-cloudep-member-server/internal/config" - cfg "app-cloudep-member-server/pkg/domain/config" - "app-cloudep-member-server/pkg/domain/usecase" - "app-cloudep-member-server/pkg/repository" - uc "app-cloudep-member-server/pkg/usecase" + "context" + + "code.30cm.net/digimon/app-cloudep-member-server/internal/config" + cfg "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/config" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/usecase" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/repository" + uc "code.30cm.net/digimon/app-cloudep-member-server/pkg/usecase" "code.30cm.net/digimon/library-go/errs" "code.30cm.net/digimon/library-go/errs/code" mgo "code.30cm.net/digimon/library-go/mongo" @@ -46,6 +48,10 @@ func NewAccountUC(c *config.Config) usecase.AccountUseCase { EnableStandardReadWriteSplitMode: c.Mongo.EnableStandardReadWriteSplitMode, ConnectTimeoutMs: c.Mongo.ConnectTimeoutMs, } + if c.Mongo.User != "" { + conf.User = c.Mongo.User + conf.Password = c.Mongo.Password + } // 快取選項 cacheOpts := []cache.Option{ @@ -57,36 +63,47 @@ func NewAccountUC(c *config.Config) usecase.AccountUseCase { mgo.InitMongoOptions(*conf), } - newRedis, err := redis.NewRedis(c.RedisConf, redis.Cluster()) + newRedis, err := redis.NewRedis(c.Redis.RedisConf) if err != nil { panic(err) } + ac := repository.NewAccountRepository(repository.AccountRepositoryParam{ + Conf: conf, + CacheConf: c.Cache, + CacheOpts: cacheOpts, + DBOpts: dbOpts, + }) + + u := repository.NewUserRepository(repository.UserRepositoryParam{ + Conf: conf, + CacheConf: c.Cache, + CacheOpts: cacheOpts, + DBOpts: dbOpts, + }) + guid := repository.NewAutoIDRepository(repository.AutoIDRepositoryParam{ + Conf: conf, + DBOpts: dbOpts, + }) + auid := repository.NewAccountUIDRepository(repository.AccountUIDRepositoryParam{ + Conf: conf, + CacheConf: c.Cache, + CacheOpts: cacheOpts, + DBOpts: dbOpts, + }) + + _, _ = ac.Index20241226001UP(context.Background()) + _, _ = u.Index20241226001UP(context.Background()) + _, _ = guid.Index20241226001UP(context.Background()) + _, _ = auid.Index20241226001UP(context.Background()) + return uc.MustMemberUseCase(uc.MemberUseCaseParam{ - Account: repository.NewAccountRepository(repository.AccountRepositoryParam{ - Conf: conf, - CacheConf: c.Cache, - CacheOpts: cacheOpts, - DbOpts: dbOpts, - }), - User: repository.NewUserRepository(repository.UserRepositoryParam{ - Conf: conf, - CacheConf: c.Cache, - CacheOpts: cacheOpts, - DbOpts: dbOpts, - }), - AccountUID: repository.NewAccountUIDRepository(repository.AccountUIDRepositoryParam{ - Conf: conf, - CacheConf: c.Cache, - CacheOpts: cacheOpts, - DbOpts: dbOpts, - }), + Account: ac, + User: u, + AccountUID: auid, VerifyCodeModel: repository.NewVerifyCodeRepository(newRedis), - GenerateUID: repository.NewAutoIDRepository(repository.AutoIDRepositoryParam{ - Conf: conf, - DbOpts: dbOpts, - }), - Config: prepareCfg(c), + GenerateUID: guid, + Config: prepareCfg(c), }) } diff --git a/member.go b/member.go index ccf5344..c0797e3 100644 --- a/member.go +++ b/member.go @@ -5,10 +5,10 @@ import ( "github.com/zeromicro/go-zero/core/logx" - "app-cloudep-member-server/gen_result/pb/member" - "app-cloudep-member-server/internal/config" - accountServer "app-cloudep-member-server/internal/server/account" - "app-cloudep-member-server/internal/svc" + "code.30cm.net/digimon/app-cloudep-member-server/gen_result/pb/member" + "code.30cm.net/digimon/app-cloudep-member-server/internal/config" + accountServer "code.30cm.net/digimon/app-cloudep-member-server/internal/server/account" + "code.30cm.net/digimon/app-cloudep-member-server/internal/svc" "github.com/zeromicro/go-zero/core/conf" "github.com/zeromicro/go-zero/core/service" diff --git a/pkg/domain/entity/account.go b/pkg/domain/entity/account.go index d3b2fb1..ed23057 100644 --- a/pkg/domain/entity/account.go +++ b/pkg/domain/entity/account.go @@ -1,7 +1,7 @@ package entity import ( - "app-cloudep-member-server/pkg/domain/member" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/member" "go.mongodb.org/mongo-driver/bson/primitive" ) diff --git a/pkg/domain/entity/account_uid_table.go b/pkg/domain/entity/account_uid_table.go index 2183d99..7c180b6 100644 --- a/pkg/domain/entity/account_uid_table.go +++ b/pkg/domain/entity/account_uid_table.go @@ -1,7 +1,7 @@ package entity import ( - "app-cloudep-member-server/pkg/domain/member" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/member" "go.mongodb.org/mongo-driver/bson/primitive" ) diff --git a/pkg/domain/entity/user.go b/pkg/domain/entity/user.go index 2e987a1..bc4a37e 100644 --- a/pkg/domain/entity/user.go +++ b/pkg/domain/entity/user.go @@ -1,7 +1,7 @@ package entity import ( - "app-cloudep-member-server/pkg/domain/member" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/member" "go.mongodb.org/mongo-driver/bson/primitive" ) diff --git a/pkg/domain/repository/account.go b/pkg/domain/repository/account.go index af04a17..e13203f 100644 --- a/pkg/domain/repository/account.go +++ b/pkg/domain/repository/account.go @@ -1,9 +1,12 @@ package repository import ( - "app-cloudep-member-server/pkg/domain/entity" "context" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/member" + + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/entity" + "go.mongodb.org/mongo-driver/mongo" ) @@ -13,7 +16,7 @@ type AccountRepository interface { Update(ctx context.Context, data *entity.Account) (*mongo.UpdateResult, error) Delete(ctx context.Context, id string) (int64, error) FindOneByAccount(ctx context.Context, loginID string) (*entity.Account, error) - UpdateTokenByLoginID(ctx context.Context, account string, token string) error + UpdateTokenByLoginID(ctx context.Context, account string, token string, platform member.Platform) error AccountIndexUP } diff --git a/pkg/domain/repository/account_uid.go b/pkg/domain/repository/account_uid.go index a75de31..82a0e82 100644 --- a/pkg/domain/repository/account_uid.go +++ b/pkg/domain/repository/account_uid.go @@ -1,9 +1,10 @@ package repository import ( - "app-cloudep-member-server/pkg/domain/entity" "context" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/entity" + "go.mongodb.org/mongo-driver/mongo" ) diff --git a/pkg/domain/repository/auto_id.go b/pkg/domain/repository/auto_id.go index 407903a..5e0d078 100644 --- a/pkg/domain/repository/auto_id.go +++ b/pkg/domain/repository/auto_id.go @@ -1,9 +1,10 @@ package repository import ( - "app-cloudep-member-server/pkg/domain/entity" "context" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/entity" + "go.mongodb.org/mongo-driver/mongo" ) diff --git a/pkg/domain/repository/user.go b/pkg/domain/repository/user.go index 7c31386..0143a46 100644 --- a/pkg/domain/repository/user.go +++ b/pkg/domain/repository/user.go @@ -1,10 +1,11 @@ package repository import ( - "app-cloudep-member-server/pkg/domain/entity" - "app-cloudep-member-server/pkg/domain/member" "context" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/entity" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/member" + "go.mongodb.org/mongo-driver/mongo" ) diff --git a/pkg/domain/usecase/account.go b/pkg/domain/usecase/account.go index dc939ea..94212ef 100644 --- a/pkg/domain/usecase/account.go +++ b/pkg/domain/usecase/account.go @@ -1,8 +1,9 @@ package usecase import ( - "app-cloudep-member-server/pkg/domain/member" "context" + + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/member" ) // AccountUseCase 定義了帳號服務的操作方法 diff --git a/pkg/mock/repository/account.go b/pkg/mock/repository/account.go index 38ac98e..9d15887 100644 --- a/pkg/mock/repository/account.go +++ b/pkg/mock/repository/account.go @@ -10,10 +10,11 @@ package mock import ( - entity "app-cloudep-member-server/pkg/domain/entity" context "context" reflect "reflect" + entity "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/entity" + member "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/member" mongo "go.mongodb.org/mongo-driver/mongo" gomock "go.uber.org/mock/gomock" ) @@ -132,17 +133,17 @@ func (mr *MockAccountRepositoryMockRecorder) Update(ctx, data any) *gomock.Call } // UpdateTokenByLoginID mocks base method. -func (m *MockAccountRepository) UpdateTokenByLoginID(ctx context.Context, account, token string) error { +func (m *MockAccountRepository) UpdateTokenByLoginID(ctx context.Context, account, token string, platform member.Platform) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "UpdateTokenByLoginID", ctx, account, token) + ret := m.ctrl.Call(m, "UpdateTokenByLoginID", ctx, account, token, platform) ret0, _ := ret[0].(error) return ret0 } // UpdateTokenByLoginID indicates an expected call of UpdateTokenByLoginID. -func (mr *MockAccountRepositoryMockRecorder) UpdateTokenByLoginID(ctx, account, token any) *gomock.Call { +func (mr *MockAccountRepositoryMockRecorder) UpdateTokenByLoginID(ctx, account, token, platform any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateTokenByLoginID", reflect.TypeOf((*MockAccountRepository)(nil).UpdateTokenByLoginID), ctx, account, token) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateTokenByLoginID", reflect.TypeOf((*MockAccountRepository)(nil).UpdateTokenByLoginID), ctx, account, token, platform) } // MockAccountIndexUP is a mock of AccountIndexUP interface. diff --git a/pkg/mock/repository/account_uid.go b/pkg/mock/repository/account_uid.go index 5c5b434..2ea58af 100644 --- a/pkg/mock/repository/account_uid.go +++ b/pkg/mock/repository/account_uid.go @@ -10,10 +10,10 @@ package mock import ( - entity "app-cloudep-member-server/pkg/domain/entity" context "context" reflect "reflect" + entity "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/entity" mongo "go.mongodb.org/mongo-driver/mongo" gomock "go.uber.org/mock/gomock" ) diff --git a/pkg/mock/repository/auto_id.go b/pkg/mock/repository/auto_id.go index b722cfa..956813a 100644 --- a/pkg/mock/repository/auto_id.go +++ b/pkg/mock/repository/auto_id.go @@ -10,10 +10,10 @@ package mock import ( - entity "app-cloudep-member-server/pkg/domain/entity" context "context" reflect "reflect" + entity "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/entity" mongo "go.mongodb.org/mongo-driver/mongo" gomock "go.uber.org/mock/gomock" ) diff --git a/pkg/mock/repository/user.go b/pkg/mock/repository/user.go index 95f9b21..0058afe 100644 --- a/pkg/mock/repository/user.go +++ b/pkg/mock/repository/user.go @@ -10,11 +10,11 @@ package mock import ( - entity "app-cloudep-member-server/pkg/domain/entity" - repository "app-cloudep-member-server/pkg/domain/repository" context "context" reflect "reflect" + entity "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/entity" + repository "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/repository" mongo "go.mongodb.org/mongo-driver/mongo" gomock "go.uber.org/mock/gomock" ) diff --git a/pkg/repository/account.go b/pkg/repository/account.go index 2eb9238..c3ddc5f 100644 --- a/pkg/repository/account.go +++ b/pkg/repository/account.go @@ -1,13 +1,16 @@ package repository import ( - "app-cloudep-member-server/pkg/domain" - "app-cloudep-member-server/pkg/domain/entity" - "app-cloudep-member-server/pkg/domain/repository" "context" "errors" "time" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/member" + + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/entity" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/repository" + mgo "code.30cm.net/digimon/library-go/mongo" "github.com/zeromicro/go-zero/core/stores/cache" "github.com/zeromicro/go-zero/core/stores/mon" @@ -19,7 +22,7 @@ import ( type AccountRepositoryParam struct { Conf *mgo.Conf CacheConf cache.CacheConf - DbOpts []mon.Option + DBOpts []mon.Option CacheOpts []cache.Option } @@ -33,7 +36,7 @@ func NewAccountRepository(param AccountRepositoryParam) repository.AccountReposi param.Conf, e.CollectionName(), param.CacheConf, - param.DbOpts, + param.DBOpts, param.CacheOpts, ) if err != nil { @@ -112,9 +115,9 @@ func (repo *AccountRepository) FindOneByAccount(ctx context.Context, loginID str } } -func (repo *AccountRepository) UpdateTokenByLoginID(ctx context.Context, account string, token string) error { +func (repo *AccountRepository) UpdateTokenByLoginID(ctx context.Context, account string, token string, platform member.Platform) error { // todo: 之後需要同步快取 - filter := bson.M{"login_id": account} + filter := bson.M{"login_id": account, "platform": platform.ToInt64()} update := bson.M{ "$set": bson.M{ "token": token, diff --git a/pkg/repository/account_test.go b/pkg/repository/account_test.go index e27de71..7c946ca 100644 --- a/pkg/repository/account_test.go +++ b/pkg/repository/account_test.go @@ -1,13 +1,16 @@ package repository import ( - "app-cloudep-member-server/pkg/domain/entity" - "app-cloudep-member-server/pkg/domain/repository" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/member" "context" "errors" + "fmt" "testing" "time" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/entity" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/repository" + mgo "code.30cm.net/digimon/library-go/mongo" "github.com/alicebob/miniredis/v2" "github.com/stretchr/testify/assert" @@ -26,8 +29,7 @@ func SetupTestAccountRepository(db string) (repository.AccountRepository, func() conf := &mgo.Conf{ Schema: Schema, - Host: h, - Port: p, + Host: fmt.Sprintf("%s:%s", h, p), Database: db, MaxStaleness: 300, MaxPoolSize: 100, @@ -312,6 +314,7 @@ func TestAccountModel_UpdateTokenByLoginID(t *testing.T) { name string loginID string newToken string + platform int64 expectedErr error expectFound bool }{ @@ -319,6 +322,7 @@ func TestAccountModel_UpdateTokenByLoginID(t *testing.T) { name: "Valid Update Token", loginID: "testuser2", newToken: "newtoken123", + platform: 1, expectedErr: nil, expectFound: true, }, @@ -326,6 +330,7 @@ func TestAccountModel_UpdateTokenByLoginID(t *testing.T) { name: "Account Not Found for Update", loginID: "nonexistentuser", newToken: "newtoken456", + platform: 1, expectedErr: ErrNotFound, expectFound: false, }, @@ -333,7 +338,7 @@ func TestAccountModel_UpdateTokenByLoginID(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - err := repo.UpdateTokenByLoginID(context.Background(), tt.loginID, tt.newToken) + err := repo.UpdateTokenByLoginID(context.Background(), tt.loginID, tt.newToken, member.Platform(tt.platform)) if tt.expectFound { assert.NoError(t, err) diff --git a/pkg/repository/account_uid.go b/pkg/repository/account_uid.go index 795b216..b962df9 100644 --- a/pkg/repository/account_uid.go +++ b/pkg/repository/account_uid.go @@ -1,13 +1,14 @@ package repository import ( - "app-cloudep-member-server/pkg/domain" - "app-cloudep-member-server/pkg/domain/entity" - "app-cloudep-member-server/pkg/domain/repository" "context" "errors" "time" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/entity" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/repository" + mgo "code.30cm.net/digimon/library-go/mongo" "github.com/zeromicro/go-zero/core/stores/cache" "github.com/zeromicro/go-zero/core/stores/mon" @@ -19,7 +20,7 @@ import ( type AccountUIDRepositoryParam struct { Conf *mgo.Conf CacheConf cache.CacheConf - DbOpts []mon.Option + DBOpts []mon.Option CacheOpts []cache.Option } @@ -33,7 +34,7 @@ func NewAccountUIDRepository(param AccountUIDRepositoryParam) repository.Account param.Conf, e.CollectionName(), param.CacheConf, - param.DbOpts, + param.DBOpts, param.CacheOpts, ) if err != nil { diff --git a/pkg/repository/account_uid_test.go b/pkg/repository/account_uid_test.go index 29476b2..b9f168c 100644 --- a/pkg/repository/account_uid_test.go +++ b/pkg/repository/account_uid_test.go @@ -1,12 +1,14 @@ package repository import ( - "app-cloudep-member-server/pkg/domain/entity" - "app-cloudep-member-server/pkg/domain/repository" "context" + "fmt" "testing" "time" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/entity" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/repository" + mgo "code.30cm.net/digimon/library-go/mongo" "github.com/alicebob/miniredis/v2" "github.com/stretchr/testify/assert" @@ -24,8 +26,7 @@ func SetupTestAccountUIDRepository(db string) (repository.AccountUIDRepository, conf := &mgo.Conf{ Schema: Schema, - Host: h, - Port: p, + Host: fmt.Sprintf("%s:%s", h, p), Database: db, MaxStaleness: 300, MaxPoolSize: 100, diff --git a/pkg/repository/auto_id.go b/pkg/repository/auto_id.go index 9d48a70..4df3e88 100644 --- a/pkg/repository/auto_id.go +++ b/pkg/repository/auto_id.go @@ -1,12 +1,13 @@ package repository import ( - "app-cloudep-member-server/pkg/domain/entity" - "app-cloudep-member-server/pkg/domain/repository" "context" "errors" "time" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/entity" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/repository" + GIDLib "code.30cm.net/digimon/library-go/utils/invited_code" mgo "code.30cm.net/digimon/library-go/mongo" @@ -19,7 +20,7 @@ import ( type AutoIDRepositoryParam struct { Conf *mgo.Conf - DbOpts []mon.Option + DBOpts []mon.Option } type AutoIDRepository struct { @@ -29,7 +30,7 @@ type AutoIDRepository struct { func NewAutoIDRepository(param AutoIDRepositoryParam) repository.AutoIDRepository { e := entity.AutoID{} - documentDB, err := mgo.NewDocumentDB(param.Conf, e.CollectionName(), param.DbOpts...) + documentDB, err := mgo.NewDocumentDB(param.Conf, e.CollectionName(), param.DBOpts...) if err != nil { panic(err) } diff --git a/pkg/repository/auto_id_test.go b/pkg/repository/auto_id_test.go index c3b1f34..0aea917 100644 --- a/pkg/repository/auto_id_test.go +++ b/pkg/repository/auto_id_test.go @@ -1,12 +1,14 @@ package repository import ( - "app-cloudep-member-server/pkg/domain/entity" - "app-cloudep-member-server/pkg/domain/repository" "context" + "fmt" "testing" "time" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/entity" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/repository" + mgo "code.30cm.net/digimon/library-go/mongo" "github.com/stretchr/testify/assert" ) @@ -19,8 +21,7 @@ func SetupTestAutoIDRepository(db string) (repository.AutoIDRepository, func(), conf := &mgo.Conf{ Schema: Schema, - Host: h, - Port: p, + Host: fmt.Sprintf("%s:%s", h, p), Database: db, MaxStaleness: 300, MaxPoolSize: 100, diff --git a/pkg/repository/user.go b/pkg/repository/user.go index 8b393df..17b0bbf 100644 --- a/pkg/repository/user.go +++ b/pkg/repository/user.go @@ -1,13 +1,14 @@ package repository import ( - "app-cloudep-member-server/pkg/domain" - "app-cloudep-member-server/pkg/domain/entity" - "app-cloudep-member-server/pkg/domain/repository" "context" "errors" "fmt" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/entity" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/repository" + mgo "code.30cm.net/digimon/library-go/mongo" "time" @@ -23,7 +24,7 @@ import ( type UserRepositoryParam struct { Conf *mgo.Conf CacheConf cache.CacheConf - DbOpts []mon.Option + DBOpts []mon.Option CacheOpts []cache.Option } @@ -37,7 +38,7 @@ func NewUserRepository(param UserRepositoryParam) repository.UserRepository { param.Conf, e.CollectionName(), param.CacheConf, - param.DbOpts, + param.DBOpts, param.CacheOpts, ) if err != nil { diff --git a/pkg/repository/user_test.go b/pkg/repository/user_test.go index b179b29..03a4745 100644 --- a/pkg/repository/user_test.go +++ b/pkg/repository/user_test.go @@ -1,14 +1,16 @@ package repository import ( - "app-cloudep-member-server/pkg/domain/entity" - "app-cloudep-member-server/pkg/domain/member" - "app-cloudep-member-server/pkg/domain/repository" "context" "errors" + "fmt" "testing" "time" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/entity" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/member" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/repository" + mgo "code.30cm.net/digimon/library-go/mongo" "github.com/alicebob/miniredis/v2" "github.com/stretchr/testify/assert" @@ -27,8 +29,7 @@ func SetupTestUserRepository(db string) (repository.UserRepository, func(), erro conf := &mgo.Conf{ Schema: Schema, - Host: h, - Port: p, + Host: fmt.Sprintf("%s:%s", h, p), Database: db, MaxStaleness: 300, MaxPoolSize: 100, diff --git a/pkg/repository/verify_code.go b/pkg/repository/verify_code.go index d100430..4a3dd8e 100644 --- a/pkg/repository/verify_code.go +++ b/pkg/repository/verify_code.go @@ -1,10 +1,10 @@ package repository import ( - "app-cloudep-member-server/pkg/domain" - "app-cloudep-member-server/pkg/domain/repository" "context" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/repository" "github.com/zeromicro/go-zero/core/stores/redis" ) diff --git a/pkg/repository/verify_code_test.go b/pkg/repository/verify_code_test.go index 6841cb8..ddb8092 100644 --- a/pkg/repository/verify_code_test.go +++ b/pkg/repository/verify_code_test.go @@ -1,11 +1,12 @@ package repository import ( - "app-cloudep-member-server/pkg/domain" "context" "fmt" "testing" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain" + "github.com/alicebob/miniredis/v2" "github.com/stretchr/testify/assert" "github.com/zeromicro/go-zero/core/stores/redis" diff --git a/pkg/usecase/account.go b/pkg/usecase/account.go index b8e5a65..04f7e83 100644 --- a/pkg/usecase/account.go +++ b/pkg/usecase/account.go @@ -1,9 +1,9 @@ package usecase import ( - "app-cloudep-member-server/pkg/domain/config" - "app-cloudep-member-server/pkg/domain/repository" - "app-cloudep-member-server/pkg/domain/usecase" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/config" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/repository" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/usecase" ) type MemberUseCaseParam struct { diff --git a/pkg/usecase/binding.go b/pkg/usecase/binding.go index 521f571..8c4193f 100644 --- a/pkg/usecase/binding.go +++ b/pkg/usecase/binding.go @@ -1,13 +1,14 @@ package usecase import ( - "app-cloudep-member-server/pkg/domain" - "app-cloudep-member-server/pkg/domain/entity" - "app-cloudep-member-server/pkg/domain/usecase" "context" "errors" "fmt" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/entity" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/usecase" + "code.30cm.net/digimon/library-go/errs" "code.30cm.net/digimon/library-go/errs/code" "github.com/zeromicro/go-zero/core/logx" diff --git a/pkg/usecase/binding_test.go b/pkg/usecase/binding_test.go index 027aac0..df71cef 100644 --- a/pkg/usecase/binding_test.go +++ b/pkg/usecase/binding_test.go @@ -1,18 +1,19 @@ package usecase import ( - "app-cloudep-member-server/pkg/domain/entity" - "app-cloudep-member-server/pkg/domain/member" - "app-cloudep-member-server/pkg/domain/usecase" "context" "errors" "testing" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/entity" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/member" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/usecase" + "github.com/stretchr/testify/assert" "go.uber.org/mock/gomock" "google.golang.org/protobuf/proto" - mockRepo "app-cloudep-member-server/pkg/mock/repository" + mockRepo "code.30cm.net/digimon/app-cloudep-member-server/pkg/mock/repository" ) func TestMemberUseCase_BindUserInfo(t *testing.T) { diff --git a/pkg/usecase/generate.go b/pkg/usecase/generate.go index 4820896..da7bca4 100644 --- a/pkg/usecase/generate.go +++ b/pkg/usecase/generate.go @@ -1,11 +1,12 @@ package usecase import ( - "app-cloudep-member-server/pkg/domain" - "app-cloudep-member-server/pkg/domain/entity" "context" "math" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/entity" + "code.30cm.net/digimon/library-go/errs" "code.30cm.net/digimon/library-go/errs/code" GIDLib "code.30cm.net/digimon/library-go/utils/invited_code" diff --git a/pkg/usecase/generate_test.go b/pkg/usecase/generate_test.go index b1e2cab..b68fc04 100644 --- a/pkg/usecase/generate_test.go +++ b/pkg/usecase/generate_test.go @@ -1,13 +1,14 @@ package usecase import ( - "app-cloudep-member-server/pkg/domain/entity" - mockRepo "app-cloudep-member-server/pkg/mock/repository" "context" "errors" "math" "testing" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/entity" + mockRepo "code.30cm.net/digimon/app-cloudep-member-server/pkg/mock/repository" + GIDLib "code.30cm.net/digimon/library-go/utils/invited_code" "github.com/stretchr/testify/assert" "go.uber.org/mock/gomock" diff --git a/pkg/usecase/member.go b/pkg/usecase/member.go index 118c790..00c3de8 100644 --- a/pkg/usecase/member.go +++ b/pkg/usecase/member.go @@ -1,14 +1,16 @@ package usecase import ( - "app-cloudep-member-server/pkg/domain" - "app-cloudep-member-server/pkg/domain/entity" - "app-cloudep-member-server/pkg/domain/member" - "app-cloudep-member-server/pkg/domain/repository" - "app-cloudep-member-server/pkg/domain/usecase" "context" "errors" "fmt" + "math" + + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/entity" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/member" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/repository" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/usecase" "code.30cm.net/digimon/library-go/errs" "code.30cm.net/digimon/library-go/errs/code" @@ -68,7 +70,7 @@ func (use *MemberUseCase) GetUIDByAccount(ctx context.Context, req usecase.GetUI e = errs.ResourceNotFoundWithScope( code.CloudEPMember, domain.FailedFindUIDByLoginIDErrorCode, - fmt.Sprintf("failed to insert account: %s", req.Account), + fmt.Sprintf("failed to find uid by account: %s", req.Account), ) default: // 錯誤代碼 20-201-07 @@ -81,7 +83,7 @@ func (use *MemberUseCase) GetUIDByAccount(ctx context.Context, req usecase.GetUI {Key: "func", Value: "AccountUID.FindUIDByLoginID"}, {Key: "err", Value: err.Error()}, }, - "failed to find account").Wrap(err) + "failed to find uid by account").Wrap(err) } return usecase.GetUIDByAccountResponse{}, e @@ -216,8 +218,11 @@ func (use *MemberUseCase) UpdateUserToken(ctx context.Context, req usecase.Updat fmt.Sprintf("failed to encrypt err: %s", e.Error()), ) } - - err := use.Account.UpdateTokenByLoginID(ctx, req.Account, token) + toInt8, err := safeInt64ToInt8(req.Platform) + if err != nil { + return err + } + err = use.Account.UpdateTokenByLoginID(ctx, req.Account, token, member.Platform(toInt8)) if err != nil { var e *errs.LibError switch { @@ -387,3 +392,11 @@ func GetOriginalInt64(value *int64) int64 { return *value } + +func safeInt64ToInt8(n int64) (int8, error) { + if n < math.MinInt8 || n > math.MaxInt8 { + return 0, fmt.Errorf("int64 value %d out of int8 range", n) + } + + return int8(n), nil +} diff --git a/pkg/usecase/member_test.go b/pkg/usecase/member_test.go index b7034ff..378372a 100644 --- a/pkg/usecase/member_test.go +++ b/pkg/usecase/member_test.go @@ -1,17 +1,18 @@ package usecase import ( - "app-cloudep-member-server/pkg/domain" - "app-cloudep-member-server/pkg/domain/config" - "app-cloudep-member-server/pkg/domain/entity" - "app-cloudep-member-server/pkg/domain/member" - "app-cloudep-member-server/pkg/domain/usecase" - mockRepo "app-cloudep-member-server/pkg/mock/repository" - "app-cloudep-member-server/pkg/repository" "context" "errors" "testing" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/config" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/entity" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/member" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/usecase" + mockRepo "code.30cm.net/digimon/app-cloudep-member-server/pkg/mock/repository" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/repository" + "code.30cm.net/digimon/library-go/errs" "code.30cm.net/digimon/library-go/errs/code" "github.com/stretchr/testify/assert" @@ -413,17 +414,17 @@ func TestUpdateUserToken(t *testing.T) { }{ { name: "Successful token update", - req: usecase.UpdateTokenRequest{Account: "testAccount", Token: "newPassword"}, + req: usecase.UpdateTokenRequest{Account: "testAccount", Token: "newPassword", Platform: 1}, mockSetup: func() { mockAccountRepo.EXPECT(). - UpdateTokenByLoginID(gomock.Any(), "testAccount", "encrypted-password"). + UpdateTokenByLoginID(gomock.Any(), "testAccount", "encrypted-password", gomock.Any()). Return(nil) }, wantErr: false, }, { name: "Password encryption failure", - req: usecase.UpdateTokenRequest{Account: "testAccount", Token: "fail"}, + req: usecase.UpdateTokenRequest{Account: "testAccount", Token: "fail", Platform: 1}, mockSetup: func() { // No repo call expected }, @@ -431,20 +432,20 @@ func TestUpdateUserToken(t *testing.T) { }, { name: "Account not found", - req: usecase.UpdateTokenRequest{Account: "nonExistentAccount", Token: "newPassword"}, + req: usecase.UpdateTokenRequest{Account: "nonExistentAccount", Token: "newPassword", Platform: 1}, mockSetup: func() { mockAccountRepo.EXPECT(). - UpdateTokenByLoginID(gomock.Any(), "nonExistentAccount", "encrypted-password"). + UpdateTokenByLoginID(gomock.Any(), "nonExistentAccount", "encrypted-password", gomock.Any()). Return(mon.ErrNotFound) }, wantErr: true, }, { name: "Database error during token update", - req: usecase.UpdateTokenRequest{Account: "errorAccount", Token: "newPassword"}, + req: usecase.UpdateTokenRequest{Account: "errorAccount", Token: "newPassword", Platform: 1}, mockSetup: func() { mockAccountRepo.EXPECT(). - UpdateTokenByLoginID(gomock.Any(), "errorAccount", "encrypted-password"). + UpdateTokenByLoginID(gomock.Any(), "errorAccount", "encrypted-password", gomock.Any()). Return(errors.New("database error")) }, wantErr: true, diff --git a/pkg/usecase/verify.go b/pkg/usecase/verify.go index 2a08e64..539bba1 100644 --- a/pkg/usecase/verify.go +++ b/pkg/usecase/verify.go @@ -1,12 +1,13 @@ package usecase import ( - "app-cloudep-member-server/pkg/domain" - "app-cloudep-member-server/pkg/domain/member" - "app-cloudep-member-server/pkg/domain/usecase" "context" "fmt" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/member" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/usecase" + "code.30cm.net/digimon/library-go/errs" "code.30cm.net/digimon/library-go/errs/code" ) diff --git a/pkg/usecase/verify_google.go b/pkg/usecase/verify_google.go index 0ef08ec..5cd7314 100644 --- a/pkg/usecase/verify_google.go +++ b/pkg/usecase/verify_google.go @@ -1,8 +1,6 @@ package usecase import ( - "app-cloudep-member-server/pkg/domain" - "app-cloudep-member-server/pkg/domain/usecase" "context" "encoding/json" "errors" @@ -12,6 +10,9 @@ import ( "strconv" "time" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/usecase" + "code.30cm.net/digimon/library-go/errs" "code.30cm.net/digimon/library-go/errs/code" ) diff --git a/pkg/usecase/verify_google_test.go b/pkg/usecase/verify_google_test.go index 54edbf6..de76fcf 100644 --- a/pkg/usecase/verify_google_test.go +++ b/pkg/usecase/verify_google_test.go @@ -1,14 +1,16 @@ package usecase import ( - "app-cloudep-member-server/pkg/domain" - "app-cloudep-member-server/pkg/domain/usecase" - "code.30cm.net/digimon/library-go/errs" - "code.30cm.net/digimon/library-go/errs/code" - "github.com/stretchr/testify/assert" "strconv" "testing" "time" + + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/usecase" + + "code.30cm.net/digimon/library-go/errs" + "code.30cm.net/digimon/library-go/errs/code" + "github.com/stretchr/testify/assert" ) func TestValidateGoogleTokenInfo(t *testing.T) { diff --git a/pkg/usecase/verify_line.go b/pkg/usecase/verify_line.go index 67f88b9..f3ec971 100644 --- a/pkg/usecase/verify_line.go +++ b/pkg/usecase/verify_line.go @@ -1,8 +1,6 @@ package usecase import ( - "app-cloudep-member-server/pkg/domain" - "app-cloudep-member-server/pkg/domain/usecase" "bytes" "context" "encoding/json" @@ -10,6 +8,9 @@ import ( "net/http" "net/url" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/usecase" + "code.30cm.net/digimon/library-go/errs" "code.30cm.net/digimon/library-go/errs/code" ) diff --git a/pkg/usecase/verify_test.go b/pkg/usecase/verify_test.go index cb9a4c8..7fdca13 100644 --- a/pkg/usecase/verify_test.go +++ b/pkg/usecase/verify_test.go @@ -1,15 +1,16 @@ package usecase import ( - "app-cloudep-member-server/pkg/domain/entity" - "app-cloudep-member-server/pkg/domain/member" - "app-cloudep-member-server/pkg/domain/usecase" - mockRepo "app-cloudep-member-server/pkg/mock/repository" "context" "errors" "fmt" "testing" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/entity" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/member" + "code.30cm.net/digimon/app-cloudep-member-server/pkg/domain/usecase" + mockRepo "code.30cm.net/digimon/app-cloudep-member-server/pkg/mock/repository" + "code.30cm.net/digimon/library-go/errs" "github.com/stretchr/testify/assert" "go.uber.org/mock/gomock" diff --git a/readme.md b/readme.md index e69de29..cea7b59 100644 --- a/readme.md +++ b/readme.md @@ -0,0 +1,220 @@ +# Member Service: User Account Management System + +The Member Service is a comprehensive user account management system designed to handle user authentication, account creation, and profile management. This service provides a robust backend for applications requiring user management functionality, supporting various authentication methods and integrating with external services. + +The system is built using a microservices architecture, leveraging technologies such as MongoDB for data storage, Redis for caching, and Etcd for distributed configuration. It offers a wide range of features including user registration, account binding, profile management, and support for third-party authentication providers like Google and LINE. + +Key features of the Member Service include: + +- User account creation and management +- Multiple authentication methods (email, phone, Google, LINE) +- Account binding for different platforms +- User profile management +- Refresh token generation and verification +- Scalable architecture using microservices +- Integration with MongoDB, Redis, and Etcd +- Docker support for easy deployment and scaling + +## Repository Structure + +``` +. +├── docker-compose.yml +├── etc/ +│ ├── member.example.yaml +│ └── member.yaml +├── internal/ +│ ├── config/ +│ ├── logic/account/ +│ ├── server/account/ +│ └── svc/ +├── member.go +├── pkg/ +│ ├── domain/ +│ ├── mock/ +│ ├── repository/ +│ └── usecase/ +└── readme.md +``` + +### Key Files and Directories: + +- `docker-compose.yml`: Defines the multi-container Docker environment +- `etc/member.yaml`: Configuration file for the Member Service +- `internal/`: Contains internal application code + - `logic/account/`: Business logic for account-related operations + - `server/account/`: gRPC server implementation for account service +- `pkg/`: Reusable package code + - `domain/`: Domain models and interfaces + - `repository/`: Data access layer implementations + - `usecase/`: Use case implementations +- `member.go`: Main entry point for the Member Service + +## Usage Instructions + +### Prerequisites + +- Go 1.16 or later +- Docker and Docker Compose +- MongoDB 8.0 +- Etcd 3.5.5 +- Redis 7.0 + +### Installation + +1. Clone the repository: + ``` + git clone + cd + ``` + +2. Start the required services using Docker Compose: + ``` + docker-compose up -d + ``` + +3. Copy the example configuration file and modify it as needed: + ``` + cp etc/member.example.yaml etc/member.yaml + ``` + +4. Build and run the Member Service: + ``` + go build + ./member + ``` + +### Configuration + +The `etc/member.yaml` file contains the main configuration for the Member Service. Key configuration options include: + +- `ListenOn`: The address and port the service listens on +- `Etcd`: Configuration for Etcd connection +- `Cache`: Redis cache configuration +- `Mongo`: MongoDB connection details +- `Bcrypt`: Password hashing cost +- `GoogleAuth`: Google authentication settings +- `LineAuth`: LINE authentication settings + +Ensure all configuration values are set correctly before starting the service. + +### Common Use Cases + +1. Creating a new user account: + ```go + resp, err := accountService.CreateUserAccount(ctx, &account.CreateUserAccountReq{ + Email: "user@example.com", + Password: "securepassword", + }) + ``` + +2. Authenticating a user: + ```go + resp, err := accountService.VerifyPlatformAuthResult(ctx, &account.VerifyPlatformAuthResultReq{ + Platform: member.Platform_EMAIL, + Email: "user@example.com", + Password: "securepassword", + }) + ``` + +3. Updating user information: + ```go + resp, err := accountService.UpdateUserInfo(ctx, &account.UpdateUserInfoReq{ + Uid: "user123", + Nickname: "New Nickname", + }) + ``` + +### Testing & Quality + +To run the test suite: + +``` +go test ./... +``` + +### Troubleshooting + +1. Connection issues with MongoDB: + - Ensure MongoDB is running and accessible + - Check the MongoDB connection string in `etc/member.yaml` + - Verify network connectivity between the service and MongoDB + +2. Authentication failures: + - Double-check the configuration for Google and LINE authentication in `etc/member.yaml` + - Ensure the correct client IDs and secrets are set + +3. Performance issues: + - Monitor Redis cache usage and adjust cache settings if necessary + - Check MongoDB query performance and add indexes if needed + - Use Go's pprof tool to profile the application: + ``` + go tool pprof http://localhost:8080/debug/pprof/profile + ``` + +## Data Flow + +The Member Service follows a typical request-response flow: + +1. Client sends a request to the gRPC server +2. Server routes the request to the appropriate logic handler +3. Logic handler processes the request, interacting with repositories as needed +4. Repositories interact with the database (MongoDB) or cache (Redis) +5. Results are returned through the logic handler back to the client + +``` +Client -> gRPC Server -> Logic Handler -> Repository -> Database/Cache + ^ | + | | + +---------------------------------------------------------+ +``` + +Important technical considerations: +- Use of caching to improve performance for frequently accessed data +- Proper error handling and logging throughout the flow +- Secure handling of sensitive information (e.g., passwords, tokens) + +## Deployment + +The Member Service can be deployed using Docker containers. The `docker-compose.yml` file provides a template for deploying the service along with its dependencies (MongoDB, Etcd, and Redis). + +To deploy: + +1. Ensure Docker and Docker Compose are installed on the target system +2. Modify the `docker-compose.yml` file if necessary (e.g., to change ports or add volumes) +3. Run the following command in the project root: + ``` + docker-compose up -d + ``` + +4. Monitor the logs to ensure all services start correctly: + ``` + docker-compose logs -f + ``` + +For production deployments, consider using orchestration tools like Kubernetes for better scalability and management. + +## Infrastructure + +The Member Service relies on the following infrastructure components: + +- MongoDB (mongo): + - Image: mongo:8.0 + - Purpose: Primary data storage for user accounts and related information + - Configuration: + - Root username and password set via environment variables + +- Etcd (etcd): + - Image: quay.io/coreos/etcd:v3.5.5 + - Purpose: Distributed key-value store for service discovery and configuration + - Configuration: + - Listens on port 2379 for client connections + - Data directory set to /etcd-data + +- Redis (redis): + - Image: redis:7.0 + - Purpose: Caching layer for improved performance + - Configuration: + - Default configuration with no password + +These infrastructure components are defined in the `docker-compose.yml` file, allowing for easy local development and testing. For production deployments, these services should be properly secured and scaled according to the application's needs. \ No newline at end of file