feature/rename_package (#1)

Reviewed-on: #1
This commit is contained in:
王性驊 2025-02-08 02:23:54 +00:00
parent 80f6caf86d
commit c89aa9f14c
65 changed files with 1047 additions and 355 deletions

View File

@ -104,7 +104,7 @@ issues:
- contextcheck
exclude-dirs:
- internal/logic
- gen_result/
exclude-files:
- .*_test.go

View File

@ -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 \

View File

View File

@ -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:
- "6379:6379"

View File

@ -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

View File

@ -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 ================

2
go.mod
View File

@ -1,4 +1,4 @@
module app-cloudep-member-server
module code.30cm.net/digimon/app-cloudep-member-server
go 1.23.4

View File

@ -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

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -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),
})
}

View File

@ -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"

View File

@ -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"
)

View File

@ -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"
)

View File

@ -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"
)

View File

@ -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
}

View File

@ -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"
)

View File

@ -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"
)

View File

@ -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"
)

View File

@ -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 定義了帳號服務的操作方法

View File

@ -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.

View File

@ -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"
)

View File

@ -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"
)

View File

@ -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"
)

View File

@ -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,

View File

@ -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)

View File

@ -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 {

View File

@ -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,

View File

@ -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)
}

View File

@ -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,

View File

@ -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 {

View File

@ -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,

View File

@ -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"
)

View File

@ -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"

View File

@ -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 {

View File

@ -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"

View File

@ -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) {

View File

@ -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"

View File

@ -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"

View File

@ -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
}

View File

@ -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,

View File

@ -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"
)

View File

@ -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"
)

View File

@ -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) {

View File

@ -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"
)

View File

@ -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"

220
readme.md
View File

@ -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 <repository_url>
cd <repository_directory>
```
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.