From b4ebcebf6683bd69860fc3dee17d312790e57267 Mon Sep 17 00:00:00 2001 From: vhbkbk Date: Mon, 23 Oct 2023 15:27:26 +0800 Subject: [PATCH 1/2] feat(user): user get --- hextech/errors/my_errors.go | 10 +++++----- user/app/command/user.go | 5 ++++- user/app/query/user.go | 14 +++++++++++++- user/dto/user.go | 24 ++++++++---------------- user/infra/po/user.go | 17 ++++++++++++++--- user/middleware/http/jwt.go | 7 ++++--- user/model/service/user.go | 3 ++- user/router/http.go | 2 +- 8 files changed, 51 insertions(+), 31 deletions(-) diff --git a/hextech/errors/my_errors.go b/hextech/errors/my_errors.go index 0c332a5..27a7b0d 100644 --- a/hextech/errors/my_errors.go +++ b/hextech/errors/my_errors.go @@ -19,9 +19,9 @@ var ( ) func init() { - Register(defaultCoder{ErrSystemErrorCode, http.StatusInternalServerError, "System inner error", ""}) - Register(defaultCoder{ErrInvalidParamCode, http.StatusBadRequest, "Invalid param", ""}) - Register(defaultCoder{ErrUnauthorizedCode, http.StatusUnauthorized, "Unauthorized", ""}) - Register(defaultCoder{ErrVerifyCaptchaFailedCode, http.StatusBadRequest, "Captcha verification failed", ""}) - Register(defaultCoder{ErrLoginFailedCode, http.StatusBadRequest, "Incorrect username or password", ""}) + Register(defaultCoder{ErrSystemErrorCode, http.StatusInternalServerError, "system inner error", ""}) + Register(defaultCoder{ErrInvalidParamCode, http.StatusBadRequest, "invalid param", ""}) + Register(defaultCoder{ErrUnauthorizedCode, http.StatusUnauthorized, "unauthorized", ""}) + Register(defaultCoder{ErrVerifyCaptchaFailedCode, http.StatusBadRequest, "captcha verification failed", ""}) + Register(defaultCoder{ErrLoginFailedCode, http.StatusBadRequest, "incorrect username or password", ""}) } diff --git a/user/app/command/user.go b/user/app/command/user.go index e2d8031..e2d4a62 100644 --- a/user/app/command/user.go +++ b/user/app/command/user.go @@ -26,10 +26,13 @@ func Login(ctx *gin.Context) { } // 登录成功,记录上下文登录成功标记,用于中间件刷新jwt utils.SetContextValue(ctx, constant.CtxUserLoginFlag, userID) + message.Success(ctx, dto.CreateUserResponse{ + ID: userID, + }) return } -func CreateUser(ctx *gin.Context) { +func Create(ctx *gin.Context) { args := &dto.CreateUserRequest{} err := ctx.ShouldBindJSON(args) diff --git a/user/app/query/user.go b/user/app/query/user.go index c3c2f26..3776f7c 100644 --- a/user/app/query/user.go +++ b/user/app/query/user.go @@ -30,7 +30,19 @@ func UserInfo(ctx *gin.Context) { message.Failed(ctx, errors.New("user not exist")) return } - message.Success(ctx, user) + + userInfo := dto.UserInfoResponse{ + ID: user.ID, + Email: user.Email, + Enable: user.IsEnable(), + HeadImage: user.HeadImage, + Mobile: user.Mobile, + Telephone: user.Telephone, + Embed: user.IsEmbed(), + DescInfo: user.DescInfo, + } + message.Success(ctx, userInfo) + return } func GetCaptcha(ctx *gin.Context) { diff --git a/user/dto/user.go b/user/dto/user.go index 4f48516..09b1c1f 100644 --- a/user/dto/user.go +++ b/user/dto/user.go @@ -15,22 +15,14 @@ type UserInfoRequest struct { } type UserInfoResponse struct { - ID int64 `json:"id"` - TenantId int64 `json:"tenant_id"` // 租户id - Name string `json:"name"` // 姓名 - Email string `json:"email"` // 邮箱 - Enable int64 `json:"enable"` // 是否可用 - HeadImage string `json:"head_image"` // 头像minio路径 - Mobile string `json:"mobile"` // 手机 - Telephone string `json:"telephone"` // 座机 - Embed int64 `json:"embed"` // 是否为内置账户 - LastLoginAt int64 `json:"last_login_at"` // 最近登录时间 - LastLogoutAt int64 `json:"last_logout_at"` // 最近登出时间 - JWTRefreshAt int64 `json:"jwt_refresh_at"` // jwt最后刷新时间 - DescInfo string `json:"desc_info"` // 描述 - DeleteAt int64 `json:"delete_at"` // 删除时间 - CreateAt int64 `json:"create_at"` // 创建时间 - UpdateAt int64 `json:"update_at"` // 更新时间 + ID int64 `json:"id"` + Email string `json:"email"` // 邮箱 + Enable bool `json:"enable"` // 是否可用 + HeadImage string `json:"head_image"` // 头像minio路径 + Mobile string `json:"mobile"` // 手机 + Telephone string `json:"telephone"` // 座机 + Embed bool `json:"embed"` // 是否为内置账户 + DescInfo string `json:"desc_info"` // 描述 } type CreateUserRequest struct { diff --git a/user/infra/po/user.go b/user/infra/po/user.go index f80b992..1e0d562 100644 --- a/user/infra/po/user.go +++ b/user/infra/po/user.go @@ -6,15 +6,26 @@ type User struct { Name string `gorm:"column:name"` // 姓名 Email string `gorm:"column:email"` // 邮箱 Password string `gorm:"column:password"` // 密码 - Enable int8 `gorm:"column:enable"` // 是否可用 + Enable int8 `gorm:"column:enable"` // 是否可用 1可用,其他暂停使用 HeadImage string `gorm:"column:head_image"` // 头像minio路径 Mobile string `gorm:"column:mobile"` // 手机 Telephone string `gorm:"column:telephone"` // 座机 - Embed int8 `gorm:"column:embed"` // 是否为内置账户 + Embed int8 `gorm:"column:embed"` // 是否为内置账户 1是,其他不是 DescInfo string `gorm:"column:desc_info"` // 描述 DeleteAt int64 `gorm:"column:delete_at"` // 删除时间 } -func (User) TableName() string { +func (*User) TableName() string { return "user" } + +const UserEnableNormal int8 = 1 +const UserEmbedIn int8 = 1 + +func (p *User) IsEnable() bool { + return p != nil && p.Enable == UserEnableNormal +} + +func (p *User) IsEmbed() bool { + return p != nil && p.Embed == UserEmbedIn +} diff --git a/user/middleware/http/jwt.go b/user/middleware/http/jwt.go index dfe4a00..cb35cad 100644 --- a/user/middleware/http/jwt.go +++ b/user/middleware/http/jwt.go @@ -9,6 +9,7 @@ import ( "octopus/hextech/nlog" "octopus/hextech/server" "octopus/hextech/utils" + "octopus/user/dto" ) func JWT(ctx *gin.Context) { @@ -48,7 +49,7 @@ func verifyJWT(ctx *gin.Context) (userID int64, newToken string, err error) { // 判断tokenID是否相等 if !claims.EqTokenID(tokenID) { - err = errors.New("Token has expired") + err = errors.New("token has expired") return } @@ -74,9 +75,9 @@ func LoginAfterRefreshJWT(ctx *gin.Context) { defer utils.SetContextValue(ctx, constant.CtxUserLoginFlag, 0) err := jwt.New().WithCtx(ctx).MakeClaims(loginUserID).MakeToken().SaveTokenID(server.APP.GetRedis()) if err != nil { - message.FailedWithMsg(ctx, "Login failed", errors.ErrLoginFailed) + message.FailedWithMsg(ctx, "login failed", errors.ErrLoginFailed) ctx.Abort() } - message.Success(ctx, struct{}{}) + message.Success(ctx, dto.CreateUserResponse{ID: loginUserID}) return } diff --git a/user/model/service/user.go b/user/model/service/user.go index a66555e..f1385a5 100644 --- a/user/model/service/user.go +++ b/user/model/service/user.go @@ -3,6 +3,7 @@ package service import ( "context" "errors" + myerrors "octopus/hextech/errors" "octopus/user/dto" "octopus/user/infra/acl/convert" "octopus/user/infra/query" @@ -56,7 +57,7 @@ func (u *UserService) Login(args *dto.LoginRequest) (userID int64, err error) { userDomain := convert.UserPo2Domain(u.ctx, info) // check password if !userDomain.GetPassword().Check(args.Password) { - return 0, errors.New("incorrect user password") + return 0, myerrors.ErrLoginFailed } // update last login at and access ip diff --git a/user/router/http.go b/user/router/http.go index 7e40fbc..7d41560 100644 --- a/user/router/http.go +++ b/user/router/http.go @@ -34,7 +34,7 @@ func HTTP(engine *gin.Engine) { versionGroup := engine.Group("/v1") userRouter := versionGroup.Group("/user") { - userRouter.POST("/create", command.CreateUser) + userRouter.POST("/create", command.Create) userRouter.GET("/info", query.UserInfo) } } -- Gitee From 5c59d1062dc89c5da2011c2b335ae1fd3adaaa09 Mon Sep 17 00:00:00 2001 From: vhbkbk Date: Thu, 26 Oct 2023 18:22:25 +0800 Subject: [PATCH 2/2] feat(storage): add storage module --- .../app/command/workspace.go | 4 +- .../conf/dev.yml | 0 .../dto/workspace.go | 0 .../infra/acl/convert/wokspace.go | 6 +- .../infra/db/workspace.sql | 0 .../infra/po/base.go | 0 .../infra/po/workspace.go | 0 .../infra/query/store.go | 0 .../infra/query/workspace.go | 2 +- .../infra/repository/workspace.go | 6 +- experiment_module/main.go | 13 ++++ .../model/domain/base/aggregate_root.go | 0 .../model/domain/base/entity.go | 0 .../model/domain/base/role.go | 0 .../model/domain/base/value_object.go | 0 .../model/domain/workspace/desc.go | 0 .../model/domain/workspace/member.go | 2 +- .../model/domain/workspace/workspace.go | 2 +- .../model/domain/workspace/workspace_repo.go | 0 .../model/service/workspace.go | 10 +-- .../router/http.go | 2 +- hextech/config/options.go | 30 +++++++++ hextech/core/rpcxserver.go | 2 +- hextech/errors/my_errors.go | 8 ++- {user => hextech}/middleware/http/jwt.go | 6 +- hextech/minio/client.go | 5 ++ hextech/server/server.go | 5 ++ hextech/utils/string.go | 9 +++ storage_module/app/command/storage.go | 50 +++++++++++++++ storage_module/app/query/storage.go | 63 +++++++++++++++++++ storage_module/conf/dev.yml | 23 +++++++ storage_module/constant/bucket.go | 10 +++ storage_module/constant/constant.go | 11 ++++ storage_module/dto/storage.go | 19 ++++++ storage_module/infra/query/storage.go | 36 +++++++++++ storage_module/infra/query/store.go | 16 +++++ storage_module/infra/repository/storage.go | 56 +++++++++++++++++ {experiment => storage_module}/main.go | 2 +- .../model/domain/storage/storage_repo.go | 18 ++++++ storage_module/model/service/storage.go | 33 ++++++++++ storage_module/router/http.go | 13 ++++ storage_module/router/storage.go | 16 +++++ storage_module/utils/storage.go | 35 +++++++++++ {user => user_module}/app/command/user.go | 9 ++- {user => user_module}/app/query/user.go | 9 +-- {user => user_module}/conf/dev.yml | 0 {user => user_module}/dto/captcha.go | 0 {user => user_module}/dto/user.go | 14 +++-- .../infra/acl/convert/user.go | 50 +++++++++------ .../infra/acl/convert/user_login_history.go | 4 +- {user => user_module}/infra/db/user.sql | 0 .../infra/db/user_login_history.sql | 0 {user => user_module}/infra/db/user_role.sql | 0 {user => user_module}/infra/po/base.go | 0 {user => user_module}/infra/po/user.go | 0 .../infra/po/user_login_history.go | 0 {user => user_module}/infra/query/store.go | 0 {user => user_module}/infra/query/user.go | 4 +- .../infra/repository/user.go | 4 +- .../infra/repository/user_login_history.go | 4 +- {user => user_module}/main.go | 2 +- .../middleware/http/captcha.go | 4 +- .../model/domain/base/aggregate_root.go | 0 .../model/domain/base/entity.go | 0 .../model/domain/base/role.go | 0 .../model/domain/base/value_object.go | 0 .../model/domain/user/email.go | 0 .../model/domain/user/headimg.go | 21 ++----- .../model/domain/user/login_attr.go | 0 .../model/domain/user/mobile.go | 0 .../model/domain/user/password.go | 0 .../model/domain/user/user.go | 45 ++++++++++--- .../model/domain/user/user_repo.go | 0 .../model/service/captcha.go | 2 +- {user => user_module}/model/service/user.go | 10 +-- {user => user_module}/router/captcha.go | 2 +- {user => user_module}/router/http.go | 11 ++-- {user => user_module}/test/user_test.go | 0 78 files changed, 607 insertions(+), 101 deletions(-) rename {experiment => experiment_module}/app/command/workspace.go (92%) rename {experiment => experiment_module}/conf/dev.yml (100%) rename {experiment => experiment_module}/dto/workspace.go (100%) rename {experiment => experiment_module}/infra/acl/convert/wokspace.go (78%) rename {experiment => experiment_module}/infra/db/workspace.sql (100%) rename {experiment => experiment_module}/infra/po/base.go (100%) rename {experiment => experiment_module}/infra/po/workspace.go (100%) rename {experiment => experiment_module}/infra/query/store.go (100%) rename {experiment => experiment_module}/infra/query/workspace.go (91%) rename {experiment => experiment_module}/infra/repository/workspace.go (89%) create mode 100644 experiment_module/main.go rename {experiment => experiment_module}/model/domain/base/aggregate_root.go (100%) rename {experiment => experiment_module}/model/domain/base/entity.go (100%) rename {experiment => experiment_module}/model/domain/base/role.go (100%) rename {experiment => experiment_module}/model/domain/base/value_object.go (100%) rename {experiment => experiment_module}/model/domain/workspace/desc.go (100%) rename {experiment => experiment_module}/model/domain/workspace/member.go (63%) rename {experiment => experiment_module}/model/domain/workspace/workspace.go (95%) rename {experiment => experiment_module}/model/domain/workspace/workspace_repo.go (100%) rename {experiment => experiment_module}/model/service/workspace.go (81%) rename {experiment => experiment_module}/router/http.go (90%) rename {user => hextech}/middleware/http/jwt.go (94%) create mode 100644 storage_module/app/command/storage.go create mode 100644 storage_module/app/query/storage.go create mode 100644 storage_module/conf/dev.yml create mode 100644 storage_module/constant/bucket.go create mode 100644 storage_module/constant/constant.go create mode 100644 storage_module/dto/storage.go create mode 100644 storage_module/infra/query/storage.go create mode 100644 storage_module/infra/query/store.go create mode 100644 storage_module/infra/repository/storage.go rename {experiment => storage_module}/main.go (86%) create mode 100644 storage_module/model/domain/storage/storage_repo.go create mode 100644 storage_module/model/service/storage.go create mode 100644 storage_module/router/http.go create mode 100644 storage_module/router/storage.go create mode 100644 storage_module/utils/storage.go rename {user => user_module}/app/command/user.go (83%) rename {user => user_module}/app/query/user.go (88%) rename {user => user_module}/conf/dev.yml (100%) rename {user => user_module}/dto/captcha.go (100%) rename {user => user_module}/dto/user.go (66%) rename {user => user_module}/infra/acl/convert/user.go (47%) rename {user => user_module}/infra/acl/convert/user_login_history.go (79%) rename {user => user_module}/infra/db/user.sql (100%) rename {user => user_module}/infra/db/user_login_history.sql (100%) rename {user => user_module}/infra/db/user_role.sql (100%) rename {user => user_module}/infra/po/base.go (100%) rename {user => user_module}/infra/po/user.go (100%) rename {user => user_module}/infra/po/user_login_history.go (100%) rename {user => user_module}/infra/query/store.go (100%) rename {user => user_module}/infra/query/user.go (90%) rename {user => user_module}/infra/repository/user.go (91%) rename {user => user_module}/infra/repository/user_login_history.go (73%) rename {user => user_module}/main.go (87%) rename {user => user_module}/middleware/http/captcha.go (92%) rename {user => user_module}/model/domain/base/aggregate_root.go (100%) rename {user => user_module}/model/domain/base/entity.go (100%) rename {user => user_module}/model/domain/base/role.go (100%) rename {user => user_module}/model/domain/base/value_object.go (100%) rename {user => user_module}/model/domain/user/email.go (100%) rename {user => user_module}/model/domain/user/headimg.go (32%) rename {user => user_module}/model/domain/user/login_attr.go (100%) rename {user => user_module}/model/domain/user/mobile.go (100%) rename {user => user_module}/model/domain/user/password.go (100%) rename {user => user_module}/model/domain/user/user.go (52%) rename {user => user_module}/model/domain/user/user_repo.go (100%) rename {user => user_module}/model/service/captcha.go (97%) rename {user => user_module}/model/service/user.go (88%) rename {user => user_module}/router/captcha.go (90%) rename {user => user_module}/router/http.go (69%) rename {user => user_module}/test/user_test.go (100%) diff --git a/experiment/app/command/workspace.go b/experiment_module/app/command/workspace.go similarity index 92% rename from experiment/app/command/workspace.go rename to experiment_module/app/command/workspace.go index dea594a..8bb9262 100644 --- a/experiment/app/command/workspace.go +++ b/experiment_module/app/command/workspace.go @@ -1,8 +1,8 @@ package command import ( - "octopus/experiment/dto" - "octopus/experiment/model/service" + "octopus/experiment_module/dto" + "octopus/experiment_module/model/service" "octopus/hextech/message" "github.com/gin-gonic/gin" diff --git a/experiment/conf/dev.yml b/experiment_module/conf/dev.yml similarity index 100% rename from experiment/conf/dev.yml rename to experiment_module/conf/dev.yml diff --git a/experiment/dto/workspace.go b/experiment_module/dto/workspace.go similarity index 100% rename from experiment/dto/workspace.go rename to experiment_module/dto/workspace.go diff --git a/experiment/infra/acl/convert/wokspace.go b/experiment_module/infra/acl/convert/wokspace.go similarity index 78% rename from experiment/infra/acl/convert/wokspace.go rename to experiment_module/infra/acl/convert/wokspace.go index 10b18b2..fdc37ba 100644 --- a/experiment/infra/acl/convert/wokspace.go +++ b/experiment_module/infra/acl/convert/wokspace.go @@ -2,9 +2,9 @@ package convert import ( "context" - "octopus/experiment/dto" - "octopus/experiment/infra/po" - "octopus/experiment/model/domain/workspace" + "octopus/experiment_module/dto" + "octopus/experiment_module/infra/po" + "octopus/experiment_module/model/domain/workspace" ) func WsCreateReqToWorkspace(ctx context.Context, req *dto.WorkSpaceCreateRequest) *workspace.WorkSpace { diff --git a/experiment/infra/db/workspace.sql b/experiment_module/infra/db/workspace.sql similarity index 100% rename from experiment/infra/db/workspace.sql rename to experiment_module/infra/db/workspace.sql diff --git a/experiment/infra/po/base.go b/experiment_module/infra/po/base.go similarity index 100% rename from experiment/infra/po/base.go rename to experiment_module/infra/po/base.go diff --git a/experiment/infra/po/workspace.go b/experiment_module/infra/po/workspace.go similarity index 100% rename from experiment/infra/po/workspace.go rename to experiment_module/infra/po/workspace.go diff --git a/experiment/infra/query/store.go b/experiment_module/infra/query/store.go similarity index 100% rename from experiment/infra/query/store.go rename to experiment_module/infra/query/store.go diff --git a/experiment/infra/query/workspace.go b/experiment_module/infra/query/workspace.go similarity index 91% rename from experiment/infra/query/workspace.go rename to experiment_module/infra/query/workspace.go index 7841325..3b082ee 100644 --- a/experiment/infra/query/workspace.go +++ b/experiment_module/infra/query/workspace.go @@ -3,7 +3,7 @@ package query import ( "errors" - "octopus/experiment/infra/po" + "octopus/experiment_module/infra/po" "gorm.io/gorm" ) diff --git a/experiment/infra/repository/workspace.go b/experiment_module/infra/repository/workspace.go similarity index 89% rename from experiment/infra/repository/workspace.go rename to experiment_module/infra/repository/workspace.go index 0844743..738caf6 100644 --- a/experiment/infra/repository/workspace.go +++ b/experiment_module/infra/repository/workspace.go @@ -2,9 +2,9 @@ package repository import ( "context" - "octopus/experiment/infra/acl/convert" - "octopus/experiment/infra/po" - "octopus/experiment/model/domain/workspace" + "octopus/experiment_module/infra/acl/convert" + "octopus/experiment_module/infra/po" + "octopus/experiment_module/model/domain/workspace" "octopus/hextech/server" "time" diff --git a/experiment_module/main.go b/experiment_module/main.go new file mode 100644 index 0000000..7fe04cb --- /dev/null +++ b/experiment_module/main.go @@ -0,0 +1,13 @@ +package main + +import ( + "octopus/experiment_module/router" + "octopus/hextech/server" +) + +const LocalConfigFile = "dev.yml" +const LocalConfigPath = "conf" + +func main() { + server.New(LocalConfigFile, LocalConfigPath).SetHttpRouter(router.HTTP).Run() +} diff --git a/experiment/model/domain/base/aggregate_root.go b/experiment_module/model/domain/base/aggregate_root.go similarity index 100% rename from experiment/model/domain/base/aggregate_root.go rename to experiment_module/model/domain/base/aggregate_root.go diff --git a/experiment/model/domain/base/entity.go b/experiment_module/model/domain/base/entity.go similarity index 100% rename from experiment/model/domain/base/entity.go rename to experiment_module/model/domain/base/entity.go diff --git a/experiment/model/domain/base/role.go b/experiment_module/model/domain/base/role.go similarity index 100% rename from experiment/model/domain/base/role.go rename to experiment_module/model/domain/base/role.go diff --git a/experiment/model/domain/base/value_object.go b/experiment_module/model/domain/base/value_object.go similarity index 100% rename from experiment/model/domain/base/value_object.go rename to experiment_module/model/domain/base/value_object.go diff --git a/experiment/model/domain/workspace/desc.go b/experiment_module/model/domain/workspace/desc.go similarity index 100% rename from experiment/model/domain/workspace/desc.go rename to experiment_module/model/domain/workspace/desc.go diff --git a/experiment/model/domain/workspace/member.go b/experiment_module/model/domain/workspace/member.go similarity index 63% rename from experiment/model/domain/workspace/member.go rename to experiment_module/model/domain/workspace/member.go index 2205be0..b914a5b 100644 --- a/experiment/model/domain/workspace/member.go +++ b/experiment_module/model/domain/workspace/member.go @@ -1,6 +1,6 @@ package workspace -import "octopus/experiment/model/domain/base" +import "octopus/experiment_module/model/domain/base" type Member struct { base.AggregateRoot diff --git a/experiment/model/domain/workspace/workspace.go b/experiment_module/model/domain/workspace/workspace.go similarity index 95% rename from experiment/model/domain/workspace/workspace.go rename to experiment_module/model/domain/workspace/workspace.go index 5e9124c..aea7648 100644 --- a/experiment/model/domain/workspace/workspace.go +++ b/experiment_module/model/domain/workspace/workspace.go @@ -2,7 +2,7 @@ package workspace import ( "context" - "octopus/experiment/model/domain/base" + "octopus/experiment_module/model/domain/base" ) type WorkSpace struct { diff --git a/experiment/model/domain/workspace/workspace_repo.go b/experiment_module/model/domain/workspace/workspace_repo.go similarity index 100% rename from experiment/model/domain/workspace/workspace_repo.go rename to experiment_module/model/domain/workspace/workspace_repo.go diff --git a/experiment/model/service/workspace.go b/experiment_module/model/service/workspace.go similarity index 81% rename from experiment/model/service/workspace.go rename to experiment_module/model/service/workspace.go index a7e15c4..0ca4928 100644 --- a/experiment/model/service/workspace.go +++ b/experiment_module/model/service/workspace.go @@ -3,11 +3,11 @@ package service import ( "context" "errors" - "octopus/experiment/dto" - "octopus/experiment/infra/acl/convert" - "octopus/experiment/infra/query" - "octopus/experiment/infra/repository" - "octopus/experiment/model/domain/workspace" + "octopus/experiment_module/dto" + "octopus/experiment_module/infra/acl/convert" + "octopus/experiment_module/infra/query" + "octopus/experiment_module/infra/repository" + "octopus/experiment_module/model/domain/workspace" ) type WorkSpaceService struct { diff --git a/experiment/router/http.go b/experiment_module/router/http.go similarity index 90% rename from experiment/router/http.go rename to experiment_module/router/http.go index 9bad435..115ad71 100644 --- a/experiment/router/http.go +++ b/experiment_module/router/http.go @@ -1,7 +1,7 @@ package router import ( - "octopus/experiment/app/command" + "octopus/experiment_module/app/command" "github.com/gin-gonic/gin" ) diff --git a/hextech/config/options.go b/hextech/config/options.go index dfcc699..c97cfa3 100644 --- a/hextech/config/options.go +++ b/hextech/config/options.go @@ -2,6 +2,7 @@ package config import ( "fmt" + "octopus/hextech/minio" "time" "octopus/hextech/captcha" @@ -21,6 +22,7 @@ type Options struct { RpcXServer *core.RpcXServer Db *gorm.DB Redis *redis.Client + Minio *minio.Client } func NewOptions(configName string, configPath string) (*Options, error) { @@ -82,6 +84,12 @@ func (o *Options) registerBasic() error { fmt.Printf("[REGISTER] register redis failed, err: %v\n", err.Error()) return err } + + // 注册minio + if err := o.registerMinio(); err != nil { + fmt.Printf("[REGISTER] register minio failed, err: %v\n", err.Error()) + return err + } return nil } @@ -179,6 +187,9 @@ func (o *Options) registerLogger() error { func (o *Options) registerDatabase() (err error) { dbConf := o.ComponentConfig.Mysql + if dbConf.Addr == "" { + return nil + } dbOptions := &db.MySQLOptions{ Host: dbConf.Addr, Username: dbConf.User, @@ -220,6 +231,9 @@ func (o *Options) registerWebServer() error { func (o *Options) registerRedis() error { redisConf := o.ComponentConfig.Redis + if redisConf.Addr == "" { + return nil + } redisOpt := &cache.Options{ Addr: redisConf.Addr, Port: redisConf.Port, @@ -294,5 +308,21 @@ func (o *Options) registerCaptcha() error { Rds: o.Redis, } captcha.Init(opt) + fmt.Println("[REGISTER] register captcha successful") + return nil +} + +func (o *Options) registerMinio() error { + conf := o.ComponentConfig.Minio + if conf.Host == "" { + return nil + } + o.Minio = &minio.Client{ + Host: conf.Host, + AccessKey: conf.AccessKey, + Secret: conf.Secret, + Bucket: "", // // 注册时无值,SetBucket进去 + } + fmt.Println("[REGISTER] register minio successful") return nil } diff --git a/hextech/core/rpcxserver.go b/hextech/core/rpcxserver.go index 64e486a..c5246cf 100644 --- a/hextech/core/rpcxserver.go +++ b/hextech/core/rpcxserver.go @@ -107,7 +107,7 @@ func NewRpcXServer(config *RpcXServerConfig) (*RpcXServer, error) { if opt == nil { opt = new(RpcXServerOptionsConfig) } - cert, _ := tls.LoadX509KeyPair("server.pem", "server.key") + cert, _ := tls.LoadX509KeyPair(base.CertFile, base.KeyFile) opt.tlsConfig = &tls.Config{Certificates: []tls.Certificate{cert}} } var opts []server.OptionFn diff --git a/hextech/errors/my_errors.go b/hextech/errors/my_errors.go index 27a7b0d..24b0e70 100644 --- a/hextech/errors/my_errors.go +++ b/hextech/errors/my_errors.go @@ -3,7 +3,9 @@ package errors import "net/http" const ( - ErrSystemErrorCode int = iota + 1000 + Err400Code int = iota + 1000 + Err404Code + ErrSystemErrorCode ErrInvalidParamCode ErrUnauthorizedCode ErrVerifyCaptchaFailedCode @@ -11,6 +13,8 @@ const ( ) var ( + Err400 = WithCode(Err400Code, "") + Err404 = WithCode(Err404Code, "") ErrSystemError = WithCode(ErrSystemErrorCode, "") ErrInvalidParam = WithCode(ErrInvalidParamCode, "") ErrUnauthorized = WithCode(ErrUnauthorizedCode, "") @@ -19,6 +23,8 @@ var ( ) func init() { + Register(defaultCoder{Err400Code, http.StatusBadRequest, "400", ""}) + Register(defaultCoder{Err404Code, http.StatusNotFound, "404", ""}) Register(defaultCoder{ErrSystemErrorCode, http.StatusInternalServerError, "system inner error", ""}) Register(defaultCoder{ErrInvalidParamCode, http.StatusBadRequest, "invalid param", ""}) Register(defaultCoder{ErrUnauthorizedCode, http.StatusUnauthorized, "unauthorized", ""}) diff --git a/user/middleware/http/jwt.go b/hextech/middleware/http/jwt.go similarity index 94% rename from user/middleware/http/jwt.go rename to hextech/middleware/http/jwt.go index cb35cad..1eed266 100644 --- a/user/middleware/http/jwt.go +++ b/hextech/middleware/http/jwt.go @@ -9,7 +9,6 @@ import ( "octopus/hextech/nlog" "octopus/hextech/server" "octopus/hextech/utils" - "octopus/user/dto" ) func JWT(ctx *gin.Context) { @@ -78,6 +77,9 @@ func LoginAfterRefreshJWT(ctx *gin.Context) { message.FailedWithMsg(ctx, "login failed", errors.ErrLoginFailed) ctx.Abort() } - message.Success(ctx, dto.CreateUserResponse{ID: loginUserID}) + type LoginResponse struct { + ID int64 `json:"id"` + } + message.Success(ctx, LoginResponse{ID: loginUserID}) return } diff --git a/hextech/minio/client.go b/hextech/minio/client.go index 1ce3180..e7184dc 100644 --- a/hextech/minio/client.go +++ b/hextech/minio/client.go @@ -12,6 +12,11 @@ type Client struct { Bucket string // 桶名称 } +func (store *Client) SetBucket(bucket string) *Client { + store.Bucket = bucket + return store +} + func newMinioClient(store *Client) (*minio.Client, error) { minioClient, err := minio.New(store.Host, &minio.Options{ Creds: credentials.NewStaticV4(store.AccessKey, store.Secret, ""), diff --git a/hextech/server/server.go b/hextech/server/server.go index 7629b96..f6f970b 100644 --- a/hextech/server/server.go +++ b/hextech/server/server.go @@ -2,6 +2,7 @@ package server import ( "context" + "octopus/hextech/minio" "os" "os/signal" "syscall" @@ -105,3 +106,7 @@ func (d *Server) GetDB() *gorm.DB { func (d *Server) GetRedis() *redis.Client { return d.options.Redis } + +func (d *Server) GetMinio() *minio.Client { + return d.options.Minio +} diff --git a/hextech/utils/string.go b/hextech/utils/string.go index 53bcfed..8dabf08 100755 --- a/hextech/utils/string.go +++ b/hextech/utils/string.go @@ -122,3 +122,12 @@ func UnmarshalJson(jsonVal []byte, objVal interface{}) error { err := decoder.Decode(objVal) return err } + +func IsStringNotEmpty(str ...string) bool { + for _, v := range str { + if v == "" { + return false + } + } + return true +} diff --git a/storage_module/app/command/storage.go b/storage_module/app/command/storage.go new file mode 100644 index 0000000..79ecc51 --- /dev/null +++ b/storage_module/app/command/storage.go @@ -0,0 +1,50 @@ +package command + +import ( + "github.com/gin-gonic/gin" + "octopus/hextech/errors" + "octopus/hextech/message" + "octopus/storage_module/constant" + "octopus/storage_module/dto" + "octopus/storage_module/model/service" + "strings" +) + +func UploadStorage(ctx *gin.Context) { + bucket := strings.TrimSpace(ctx.Param("bucket")) + if bucket == "" { + message.Failed(ctx, errors.ErrInvalidParam) + return + } + // 从文件流中获取文件信息 + multiForm, err := ctx.MultipartForm() + if err != nil { + message.FailedWithMsg(ctx, err.Error(), errors.ErrInvalidParam) + return + } + defer func() { + _ = multiForm.RemoveAll() + }() + + f, fh, err := ctx.Request.FormFile(constant.UploadFileKey) + if err != nil { + message.FailedWithMsg(ctx, err.Error(), errors.ErrInvalidParam) + return + } + defer func() { + _ = f.Close() + }() + args := &dto.UploadStorageRequest{ + BucketName: bucket, + Stream: f, + Filename: fh.Filename, + Filesize: fh.Size, + } + resp, err := service.NewStorageService(ctx).Upload(args) + if err != nil { + message.FailedWithMsg(ctx, err.Error(), errors.Err400) + return + } + message.Success(ctx, resp) + return +} diff --git a/storage_module/app/query/storage.go b/storage_module/app/query/storage.go new file mode 100644 index 0000000..f414ba0 --- /dev/null +++ b/storage_module/app/query/storage.go @@ -0,0 +1,63 @@ +package query + +import ( + "fmt" + "github.com/gin-gonic/gin" + "github.com/minio/minio-go/v7" + "net/http" + "net/url" + "octopus/hextech/errors" + "octopus/hextech/message" + "octopus/hextech/utils" + "octopus/storage_module/constant" + "octopus/storage_module/dto" + "octopus/storage_module/infra/query" + "runtime" +) + +// GetStorage 前端调用下载资源 +func GetStorage(ctx *gin.Context) { + args := &dto.GetStorageRequest{} + if err := ctx.ShouldBindUri(&args); err != nil { + message.Failed(ctx, errors.ErrInvalidParam) + return + } + if !utils.IsStringNotEmpty(args.BucketName, args.ObjectName) { + message.Failed(ctx, errors.ErrInvalidParam) + return + } + object, err := query.NewStore(ctx).GetObject(args.BucketName, args.ObjectName) + if err != nil { + message.FailedWithMsg(ctx, err.Error(), errors.ErrInvalidParam) + return + } + RenderStorageObject(ctx, object) + return +} + +// RenderStorageObject 下载资源 +func RenderStorageObject(ctx *gin.Context, object *minio.Object) { + if object == nil { + message.FailedWithMsg(ctx, "file not found", errors.Err404) + return + } + store := query.NewStore(ctx) + objectInfo, err := store.GetObjectInfo(object) + if err != nil { + message.FailedWithMsg(ctx, err.Error(), errors.ErrInvalidParam) + return + } + + headers := make(map[string]string) + rawFileName := store.GetObjectInfoFilename(objectInfo) + if rawFileName != "" { + headers["Content-Disposition"] = fmt.Sprintf("attachment; filename=%s", url.QueryEscape(rawFileName)) + } + + // 文件大小超过 OverSizeRunGC 时,手动GC + if objectInfo.Size > constant.OverSizeRunGC { + defer runtime.GC() + } + + ctx.DataFromReader(http.StatusOK, objectInfo.Size, objectInfo.ContentType, object, headers) +} diff --git a/storage_module/conf/dev.yml b/storage_module/conf/dev.yml new file mode 100644 index 0000000..fa41e00 --- /dev/null +++ b/storage_module/conf/dev.yml @@ -0,0 +1,23 @@ +app: + name: "base" + version: "1.0.0" + env: "dev" # dev, test, prod + +log: + # 日志级别, 支持 debug info warn error panic fatal ,默认info + level: debug + # 是否输出到终端,仅在开发环境有效 + stdout: true + logRate: false + logRateConf: + maxAge: 30 + maxBackups: 0 + +httpServer: + port: 8102 + address: "0.0.0.0" + +minio: + host: "127.0.0.1:9000" + accessKey: "7VU3JXE0HRB3PP6ZOZCI" + secret: "LdUMGhlWRl3EPeDEEndcZ1Bwnh6TWeYVn4Wc+v9F" \ No newline at end of file diff --git a/storage_module/constant/bucket.go b/storage_module/constant/bucket.go new file mode 100644 index 0000000..40141a0 --- /dev/null +++ b/storage_module/constant/bucket.go @@ -0,0 +1,10 @@ +package constant + +const ( + RouterBucketAvatar = "avatar" // 用户头像路由bucket +) + +// RouterBucketMap 路由bucket和Minio真实存储bucket映射关系 +var RouterBucketMap = map[string]string{ + RouterBucketAvatar: "image/avatar", +} diff --git a/storage_module/constant/constant.go b/storage_module/constant/constant.go new file mode 100644 index 0000000..35f885e --- /dev/null +++ b/storage_module/constant/constant.go @@ -0,0 +1,11 @@ +package constant + +const RawFileName = "Filename" // 原始文件名 + +const OverSizeRunGC int64 = 64 * 1024 + +const UploadFileKey = "file" + +const UploadMaxSize = 512 * 1024 * 1024 // 512M + +const StorageRouterPrefix = "/storage" diff --git a/storage_module/dto/storage.go b/storage_module/dto/storage.go new file mode 100644 index 0000000..1fed3dc --- /dev/null +++ b/storage_module/dto/storage.go @@ -0,0 +1,19 @@ +package dto + +import "io" + +type GetStorageRequest struct { + BucketName string `uri:"bucket" binding:"required,min=2,max=64"` + ObjectName string `uri:"object" binding:"required,min=5"` +} + +type UploadStorageRequest struct { + BucketName string + Stream io.Reader + Filename string + Filesize int64 +} + +type UploadStorageResponse struct { + URL string `json:"url"` +} diff --git a/storage_module/infra/query/storage.go b/storage_module/infra/query/storage.go new file mode 100644 index 0000000..54a73c2 --- /dev/null +++ b/storage_module/infra/query/storage.go @@ -0,0 +1,36 @@ +package query + +import ( + miniogo "github.com/minio/minio-go/v7" + "octopus/storage_module/constant" + "octopus/storage_module/utils" + "path" + "path/filepath" +) + +func (s *Store) GetObject(bucket string, objectName string) (object *miniogo.Object, err error) { + var objectPath string + bucket, objectPath = utils.GetBucket(bucket) + object, err = s.minio.SetBucket(bucket).GetAOSObject(s.ctx, path.Join(objectPath, objectName)) + if err != nil { + return nil, err + } + return +} + +func (s *Store) GetObjectInfo(object *miniogo.Object) (objectInfo *miniogo.ObjectInfo, err error) { + o, err := object.Stat() + if err != nil { + return nil, err + } + objectInfo = &o + return +} + +func (s *Store) GetObjectInfoFilename(objectInfo *miniogo.ObjectInfo) string { + filename := objectInfo.UserMetadata[constant.RawFileName] + if filename == "" { + filename = filepath.Base(objectInfo.Key) + } + return filename +} diff --git a/storage_module/infra/query/store.go b/storage_module/infra/query/store.go new file mode 100644 index 0000000..d51d26f --- /dev/null +++ b/storage_module/infra/query/store.go @@ -0,0 +1,16 @@ +package query + +import ( + "context" + "octopus/hextech/minio" + "octopus/hextech/server" +) + +type Store struct { + ctx context.Context + minio *minio.Client +} + +func NewStore(ctx context.Context) *Store { + return &Store{minio: server.APP.GetMinio(), ctx: ctx} +} diff --git a/storage_module/infra/repository/storage.go b/storage_module/infra/repository/storage.go new file mode 100644 index 0000000..7abcf82 --- /dev/null +++ b/storage_module/infra/repository/storage.go @@ -0,0 +1,56 @@ +package repository + +import ( + "context" + "errors" + "fmt" + "github.com/google/uuid" + miniogo "github.com/minio/minio-go/v7" + "io" + "mime" + "octopus/hextech/minio" + "octopus/hextech/server" + "octopus/storage_module/constant" + "octopus/storage_module/model/domain/storage" + "octopus/storage_module/utils" + "path" + "path/filepath" + "strings" +) + +type StorageRepoImpl struct { + ctx context.Context + minio *minio.Client +} + +func NewStorageRepoImpl(ctx context.Context) storage.Repository { + r := new(StorageRepoImpl) + r.minio = server.APP.GetMinio() + r.ctx = ctx + return r +} + +func (s *StorageRepoImpl) Upload(bucket string, stream io.Reader, filename string, size int64) (*miniogo.UploadInfo, error) { + if size > constant.UploadMaxSize { + return nil, errors.New("file size too large") + } + + ext := filepath.Ext(filename) + var objectPath string + + bucket, objectPath = utils.GetBucket(bucket) + + contentType := mime.TypeByExtension(ext) + if contentType == "" { + contentType = "application/octet-stream" + } + + objectName := path.Join(objectPath, strings.ReplaceAll(uuid.NewString(), "-", "")+ext) + metadata := map[string]string{constant.RawFileName: filepath.Base(filename)} + uploadInfo, err := s.minio.SetBucket(bucket).UploadStream(s.ctx, objectName, stream, size, contentType, metadata) + if err != nil { + return nil, fmt.Errorf("file upload failed. bucket: %v, filename: %v", bucket, filename) + } + + return &uploadInfo, nil +} diff --git a/experiment/main.go b/storage_module/main.go similarity index 86% rename from experiment/main.go rename to storage_module/main.go index 7122544..2191df9 100644 --- a/experiment/main.go +++ b/storage_module/main.go @@ -1,8 +1,8 @@ package main import ( - "octopus/experiment/router" "octopus/hextech/server" + "octopus/storage_module/router" ) const LocalConfigFile = "dev.yml" diff --git a/storage_module/model/domain/storage/storage_repo.go b/storage_module/model/domain/storage/storage_repo.go new file mode 100644 index 0000000..90ce147 --- /dev/null +++ b/storage_module/model/domain/storage/storage_repo.go @@ -0,0 +1,18 @@ +package storage + +import ( + miniogo "github.com/minio/minio-go/v7" + "io" +) + +type Repository interface { + Upload(bucket string, stream io.Reader, filename string, size int64) (*miniogo.UploadInfo, error) +} + +type Repo struct { + storageRepo Repository +} + +func (r *Repo) GetStorageRepo() Repository { + return r.storageRepo +} diff --git a/storage_module/model/service/storage.go b/storage_module/model/service/storage.go new file mode 100644 index 0000000..f0dd813 --- /dev/null +++ b/storage_module/model/service/storage.go @@ -0,0 +1,33 @@ +package service + +import ( + "context" + "octopus/storage_module/dto" + "octopus/storage_module/infra/repository" + "octopus/storage_module/model/domain/storage" + "octopus/storage_module/utils" +) + +type StorageService struct { + ctx context.Context + repo storage.Repository +} + +func NewStorageService(ctx context.Context) *StorageService { + p := &StorageService{ + ctx: ctx, + repo: repository.NewStorageRepoImpl(ctx), + } + return p +} + +func (s *StorageService) Upload(args *dto.UploadStorageRequest) (resp *dto.UploadStorageResponse, err error) { + uploadInfo, err := s.repo.Upload(args.BucketName, args.Stream, args.Filename, args.Filesize) + if err != nil { + return nil, err + } + resp = &dto.UploadStorageResponse{ + URL: utils.GetURL(args.BucketName, uploadInfo.Key), + } + return resp, nil +} diff --git a/storage_module/router/http.go b/storage_module/router/http.go new file mode 100644 index 0000000..288e160 --- /dev/null +++ b/storage_module/router/http.go @@ -0,0 +1,13 @@ +package router + +import ( + "github.com/gin-gonic/gin" + hexmiddleware "octopus/hextech/middleware/http" +) + +func HTTP(engine *gin.Engine) { + engine.Use(gin.Recovery()) + versionGroup := engine.Group("/v1") + engine.Use(hexmiddleware.JWT) + storageRouterGroup(versionGroup) +} diff --git a/storage_module/router/storage.go b/storage_module/router/storage.go new file mode 100644 index 0000000..e418226 --- /dev/null +++ b/storage_module/router/storage.go @@ -0,0 +1,16 @@ +package router + +import ( + "github.com/gin-gonic/gin" + "octopus/storage_module/app/command" + "octopus/storage_module/app/query" +) + +// storageRouterGroup 资源路由组 +func storageRouterGroup(group *gin.RouterGroup) { + storageRouter := group.Group("/storage") + // 下载资源 + storageRouter.GET("/:bucket/*object", query.GetStorage) + // 上传资源 + storageRouter.POST("/:bucket", command.UploadStorage) +} diff --git a/storage_module/utils/storage.go b/storage_module/utils/storage.go new file mode 100644 index 0000000..03ce11e --- /dev/null +++ b/storage_module/utils/storage.go @@ -0,0 +1,35 @@ +package utils + +import ( + "octopus/storage_module/constant" + "path" + "strings" +) + +// GetBucket 转换为真实的bucket及对象路径 +// 如没做映射,则用routerBucket表示实际的bucket +func GetBucket(routerBucket string) (bucket, objectPath string) { + bucket = strings.TrimSpace(routerBucket) + if v, ok := constant.RouterBucketMap[routerBucket]; ok { + bucket = v + } + + if pos := strings.Index(bucket, "/"); pos != -1 { + bucket, objectPath = strings.TrimSpace(bucket[:pos]), strings.TrimSpace(bucket[pos+1:]) + } + + return +} + +// GetURL 获取页面显示url +func GetURL(bucket string, storagePath string) string { + // storagePath == image/avatar/abc.png 存储路径 + // RouterBucketAvatar == "avatar" 路由bucket + if _, objectPath := GetBucket(bucket); objectPath != "" { + if strings.HasPrefix(storagePath, objectPath+"/") { + storagePath = storagePath[len(objectPath)+1:] + } + } + + return path.Join(constant.StorageRouterPrefix, bucket, storagePath) +} diff --git a/user/app/command/user.go b/user_module/app/command/user.go similarity index 83% rename from user/app/command/user.go rename to user_module/app/command/user.go index e2d4a62..be8c839 100644 --- a/user/app/command/user.go +++ b/user_module/app/command/user.go @@ -6,8 +6,8 @@ import ( "octopus/hextech/errors" "octopus/hextech/message" "octopus/hextech/utils" - "octopus/user/dto" - "octopus/user/model/service" + "octopus/user_module/dto" + "octopus/user_module/model/service" ) func Login(ctx *gin.Context) { @@ -40,6 +40,11 @@ func Create(ctx *gin.Context) { message.Failed(ctx, errors.ErrInvalidParam) return } + // 手机号和邮箱必填 + if !utils.IsStringNotEmpty(args.Mobile, args.Email) { + message.Failed(ctx, errors.ErrInvalidParam) + return + } if err := service.NewUserService(ctx).Create(args); err != nil { message.FailedWithMsg(ctx, err.Error(), err) diff --git a/user/app/query/user.go b/user_module/app/query/user.go similarity index 88% rename from user/app/query/user.go rename to user_module/app/query/user.go index 3776f7c..c698bd8 100644 --- a/user/app/query/user.go +++ b/user_module/app/query/user.go @@ -3,9 +3,9 @@ package query import ( "octopus/hextech/errors" "octopus/hextech/message" - "octopus/user/dto" - "octopus/user/infra/query" - "octopus/user/model/service" + "octopus/user_module/dto" + "octopus/user_module/infra/query" + "octopus/user_module/model/service" "path" "strings" @@ -16,7 +16,7 @@ func UserInfo(ctx *gin.Context) { args := &dto.UserInfoRequest{} err := ctx.ShouldBindJSON(args) if err != nil { - message.Failed(ctx, err) + message.Failed(ctx, errors.ErrInvalidParam) return } @@ -48,6 +48,7 @@ func UserInfo(ctx *gin.Context) { func GetCaptcha(ctx *gin.Context) { resp := service.NewCaptchaService(ctx).Get() message.Success(ctx, resp) + return } func ShowCaptcha(ctx *gin.Context) { diff --git a/user/conf/dev.yml b/user_module/conf/dev.yml similarity index 100% rename from user/conf/dev.yml rename to user_module/conf/dev.yml diff --git a/user/dto/captcha.go b/user_module/dto/captcha.go similarity index 100% rename from user/dto/captcha.go rename to user_module/dto/captcha.go diff --git a/user/dto/user.go b/user_module/dto/user.go similarity index 66% rename from user/dto/user.go rename to user_module/dto/user.go index 09b1c1f..f97dbd4 100644 --- a/user/dto/user.go +++ b/user_module/dto/user.go @@ -26,12 +26,14 @@ type UserInfoResponse struct { } type CreateUserRequest struct { - Name string `json:"name"` // 姓名 - Password string `json:"password"` // 密码 - Email string `json:"email"` // 邮箱 - Mobile string `json:"mobile"` // 手机 - Telephone string `json:"telephone"` // 座机 - DescInfo string `json:"desc_info"` // 描述 + Name string `json:"name"` // 姓名 + Password string `json:"password"` // 密码 + Email string `json:"email"` // 邮箱 + Mobile string `json:"mobile"` // 手机 + Telephone string `json:"telephone"` // 座机 + DescInfo string `json:"desc_info"` // 描述 + HeadImage string `json:"head_image"` // 头像路径 + Enable bool `json:"enable"` // 是否可用 } type CreateUserResponse struct { diff --git a/user/infra/acl/convert/user.go b/user_module/infra/acl/convert/user.go similarity index 47% rename from user/infra/acl/convert/user.go rename to user_module/infra/acl/convert/user.go index 62f613a..8d1b081 100644 --- a/user/infra/acl/convert/user.go +++ b/user_module/infra/acl/convert/user.go @@ -2,9 +2,9 @@ package convert import ( "context" - "octopus/user/dto" - "octopus/user/infra/po" - "octopus/user/model/domain/user" + "octopus/user_module/dto" + "octopus/user_module/infra/po" + "octopus/user_module/model/domain/user" ) const ( @@ -12,19 +12,28 @@ const ( ) func CreateUserDTO2User(ctx context.Context, request *dto.CreateUserRequest) *user.User { + userAttr := &user.UserAttr{ + ID: NotCreateUserID, + Username: request.Name, + Password: request.Password, + Email: request.Email, + Mobile: request.Mobile, + Telephone: request.Telephone, + DescInfo: request.DescInfo, + HeadImage: request.HeadImage, + Enable: request.Enable, + } return user.NewUser( ctx, - NotCreateUserID, - request.Name, - request.Password, - request.Email, - request.Mobile, - request.Telephone, - request.DescInfo, + userAttr, ) } func UserDomain2Po(userDomain *user.User) *po.User { + var enable int8 + if userDomain.GetEnable() { + enable = po.UserEnableNormal + } u := &po.User{ Model: po.Model{ ID: userDomain.AggregateRoot.ID(), @@ -32,7 +41,7 @@ func UserDomain2Po(userDomain *user.User) *po.User { Name: userDomain.GetUsername(), Email: userDomain.GetEmail().Get(), Password: userDomain.GetPassword().Get(), - Enable: 0, + Enable: enable, HeadImage: "", Mobile: userDomain.GetMobile().Get(), Telephone: userDomain.GetTelephone(), @@ -43,15 +52,20 @@ func UserDomain2Po(userDomain *user.User) *po.User { } func UserPo2Domain(ctx context.Context, userPo *po.User) *user.User { + userAttr := &user.UserAttr{ + ID: userPo.ID, + Username: userPo.Name, + Password: userPo.Password, + Email: userPo.Email, + Mobile: userPo.Mobile, + Telephone: userPo.Telephone, + DescInfo: userPo.DescInfo, + HeadImage: userPo.HeadImage, + Enable: userPo.IsEnable(), + } u := user.NewUser( ctx, - userPo.ID, - userPo.Name, - userPo.Password, - userPo.Email, - userPo.Mobile, - userPo.Telephone, - userPo.DescInfo, + userAttr, ) return u } diff --git a/user/infra/acl/convert/user_login_history.go b/user_module/infra/acl/convert/user_login_history.go similarity index 79% rename from user/infra/acl/convert/user_login_history.go rename to user_module/infra/acl/convert/user_login_history.go index 004ba48..b4aad44 100644 --- a/user/infra/acl/convert/user_login_history.go +++ b/user_module/infra/acl/convert/user_login_history.go @@ -1,8 +1,8 @@ package convert import ( - "octopus/user/infra/po" - "octopus/user/model/domain/user" + "octopus/user_module/infra/po" + "octopus/user_module/model/domain/user" ) func UserDomain2LoginPo(userDomain *user.User) *po.UserLoginHistory { diff --git a/user/infra/db/user.sql b/user_module/infra/db/user.sql similarity index 100% rename from user/infra/db/user.sql rename to user_module/infra/db/user.sql diff --git a/user/infra/db/user_login_history.sql b/user_module/infra/db/user_login_history.sql similarity index 100% rename from user/infra/db/user_login_history.sql rename to user_module/infra/db/user_login_history.sql diff --git a/user/infra/db/user_role.sql b/user_module/infra/db/user_role.sql similarity index 100% rename from user/infra/db/user_role.sql rename to user_module/infra/db/user_role.sql diff --git a/user/infra/po/base.go b/user_module/infra/po/base.go similarity index 100% rename from user/infra/po/base.go rename to user_module/infra/po/base.go diff --git a/user/infra/po/user.go b/user_module/infra/po/user.go similarity index 100% rename from user/infra/po/user.go rename to user_module/infra/po/user.go diff --git a/user/infra/po/user_login_history.go b/user_module/infra/po/user_login_history.go similarity index 100% rename from user/infra/po/user_login_history.go rename to user_module/infra/po/user_login_history.go diff --git a/user/infra/query/store.go b/user_module/infra/query/store.go similarity index 100% rename from user/infra/query/store.go rename to user_module/infra/query/store.go diff --git a/user/infra/query/user.go b/user_module/infra/query/user.go similarity index 90% rename from user/infra/query/user.go rename to user_module/infra/query/user.go index 14c23eb..85f5cff 100644 --- a/user/infra/query/user.go +++ b/user_module/infra/query/user.go @@ -3,7 +3,7 @@ package query import ( "errors" "octopus/hextech/nlog" - "octopus/user/infra/po" + "octopus/user_module/infra/po" "gorm.io/gorm" ) @@ -36,7 +36,7 @@ func (s *Store) GetUser(email, mobile string) (resp *po.User, exist bool, err er func (s *Store) UserInfoByID(userID int64) (resp *po.User, exist bool, err error) { res := s.db.WithContext(s.ctx).Where("id = ?", userID).First(&resp) if res.Error != nil && !errors.Is(res.Error, gorm.ErrRecordNotFound) { - nlog.Warn(s.ctx, "query customer info by customer id error:", res.Error, "params is : ", userID) + nlog.Warn(s.ctx, "query user info by id error: ", res.Error, " params: ", userID) return nil, false, err } else if errors.Is(res.Error, gorm.ErrRecordNotFound) { return nil, true, nil diff --git a/user/infra/repository/user.go b/user_module/infra/repository/user.go similarity index 91% rename from user/infra/repository/user.go rename to user_module/infra/repository/user.go index 9998c0f..a46cd15 100644 --- a/user/infra/repository/user.go +++ b/user_module/infra/repository/user.go @@ -3,8 +3,8 @@ package repository import ( "context" "octopus/hextech/server" - "octopus/user/infra/acl/convert" - "octopus/user/model/domain/user" + "octopus/user_module/infra/acl/convert" + "octopus/user_module/model/domain/user" "github.com/go-redis/redis/v7" "gorm.io/gorm" diff --git a/user/infra/repository/user_login_history.go b/user_module/infra/repository/user_login_history.go similarity index 73% rename from user/infra/repository/user_login_history.go rename to user_module/infra/repository/user_login_history.go index b4cee79..11f9612 100644 --- a/user/infra/repository/user_login_history.go +++ b/user_module/infra/repository/user_login_history.go @@ -1,8 +1,8 @@ package repository import ( - "octopus/user/infra/acl/convert" - "octopus/user/model/domain/user" + "octopus/user_module/infra/acl/convert" + "octopus/user_module/model/domain/user" ) func (u *UserRepoImpl) CreateLoginHistory(user *user.User) error { diff --git a/user/main.go b/user_module/main.go similarity index 87% rename from user/main.go rename to user_module/main.go index 187673c..f048140 100644 --- a/user/main.go +++ b/user_module/main.go @@ -2,7 +2,7 @@ package main import ( "octopus/hextech/server" - "octopus/user/router" + "octopus/user_module/router" ) const LocalConfigFile = "dev.yml" diff --git a/user/middleware/http/captcha.go b/user_module/middleware/http/captcha.go similarity index 92% rename from user/middleware/http/captcha.go rename to user_module/middleware/http/captcha.go index 8b86c4c..125d29b 100644 --- a/user/middleware/http/captcha.go +++ b/user_module/middleware/http/captcha.go @@ -7,8 +7,8 @@ import ( "io/ioutil" "octopus/hextech/errors" "octopus/hextech/message" - "octopus/user/dto" - "octopus/user/model/service" + "octopus/user_module/dto" + "octopus/user_module/model/service" ) // VerifyCaptcha 校验验证码 diff --git a/user/model/domain/base/aggregate_root.go b/user_module/model/domain/base/aggregate_root.go similarity index 100% rename from user/model/domain/base/aggregate_root.go rename to user_module/model/domain/base/aggregate_root.go diff --git a/user/model/domain/base/entity.go b/user_module/model/domain/base/entity.go similarity index 100% rename from user/model/domain/base/entity.go rename to user_module/model/domain/base/entity.go diff --git a/user/model/domain/base/role.go b/user_module/model/domain/base/role.go similarity index 100% rename from user/model/domain/base/role.go rename to user_module/model/domain/base/role.go diff --git a/user/model/domain/base/value_object.go b/user_module/model/domain/base/value_object.go similarity index 100% rename from user/model/domain/base/value_object.go rename to user_module/model/domain/base/value_object.go diff --git a/user/model/domain/user/email.go b/user_module/model/domain/user/email.go similarity index 100% rename from user/model/domain/user/email.go rename to user_module/model/domain/user/email.go diff --git a/user/model/domain/user/headimg.go b/user_module/model/domain/user/headimg.go similarity index 32% rename from user/model/domain/user/headimg.go rename to user_module/model/domain/user/headimg.go index 7c5e652..649ee31 100644 --- a/user/model/domain/user/headimg.go +++ b/user_module/model/domain/user/headimg.go @@ -2,27 +2,14 @@ package user type HeaderImg struct { objectPath string - url string } func NewHeaderImg(objectPath string) *HeaderImg { - h := &HeaderImg{} - return h + return &HeaderImg{ + objectPath: objectPath, + } } -func (h *HeaderImg) ObjectPath() string { +func (h *HeaderImg) GetObjectPath() string { return h.objectPath } - -func (h *HeaderImg) Url() string { - // - return h.url -} - -func (h *HeaderImg) SetObjectPath(objectPath string) { - h.objectPath = objectPath -} - -func (h *HeaderImg) SetUrl(url string) { - h.url = url -} diff --git a/user/model/domain/user/login_attr.go b/user_module/model/domain/user/login_attr.go similarity index 100% rename from user/model/domain/user/login_attr.go rename to user_module/model/domain/user/login_attr.go diff --git a/user/model/domain/user/mobile.go b/user_module/model/domain/user/mobile.go similarity index 100% rename from user/model/domain/user/mobile.go rename to user_module/model/domain/user/mobile.go diff --git a/user/model/domain/user/password.go b/user_module/model/domain/user/password.go similarity index 100% rename from user/model/domain/user/password.go rename to user_module/model/domain/user/password.go diff --git a/user/model/domain/user/user.go b/user_module/model/domain/user/user.go similarity index 52% rename from user/model/domain/user/user.go rename to user_module/model/domain/user/user.go index 3e30547..0f60446 100644 --- a/user/model/domain/user/user.go +++ b/user_module/model/domain/user/user.go @@ -3,7 +3,7 @@ package user import ( "context" "octopus/hextech/utils" - "octopus/user/model/domain/base" + "octopus/user_module/model/domain/base" ) type User struct { @@ -15,19 +15,38 @@ type User struct { mobile *Mobile telephone string descInfo string + headImage *HeaderImg + enable bool loginAttr *LoginAttr } -func NewUser(ctx context.Context, id int64, username, password, email, mobile, telephone, descInfo string) *User { +type UserAttr struct { + ID int64 + Username string + Password string + Email string + Mobile string + Telephone string + DescInfo string + HeadImage string + Enable bool +} + +func NewUser(ctx context.Context, attr *UserAttr) *User { + if attr == nil { + attr = new(UserAttr) + } return &User{ ctx: ctx, - AggregateRoot: base.NewAggregateRoot(id), - username: username, - password: NewPassword(password), - email: NewEmail(email), - mobile: NewMobile(mobile), - telephone: telephone, - descInfo: descInfo, + AggregateRoot: base.NewAggregateRoot(attr.ID), + username: attr.Username, + password: NewPassword(attr.Password), + email: NewEmail(attr.Email), + mobile: NewMobile(attr.Mobile), + telephone: attr.Telephone, + descInfo: attr.DescInfo, + headImage: NewHeaderImg(attr.HeadImage), + enable: attr.Enable, loginAttr: NewLoginAttr(utils.GetClientIp(ctx)), } } @@ -60,6 +79,14 @@ func (u *User) GetLoginAttr() *LoginAttr { return u.loginAttr } +func (u *User) GetHeadImage() *HeaderImg { + return u.headImage +} + +func (u *User) GetEnable() bool { + return u.enable +} + func (u *User) Valid() bool { if u.email.IsValid() && u.mobile.IsValid() && u.password.GetValid() { return true diff --git a/user/model/domain/user/user_repo.go b/user_module/model/domain/user/user_repo.go similarity index 100% rename from user/model/domain/user/user_repo.go rename to user_module/model/domain/user/user_repo.go diff --git a/user/model/service/captcha.go b/user_module/model/service/captcha.go similarity index 97% rename from user/model/service/captcha.go rename to user_module/model/service/captcha.go index 8ad7277..d33d037 100644 --- a/user/model/service/captcha.go +++ b/user_module/model/service/captcha.go @@ -4,7 +4,7 @@ import ( "errors" "github.com/gin-gonic/gin" "octopus/hextech/captcha" - "octopus/user/dto" + "octopus/user_module/dto" "path" ) diff --git a/user/model/service/user.go b/user_module/model/service/user.go similarity index 88% rename from user/model/service/user.go rename to user_module/model/service/user.go index f1385a5..1c0df8d 100644 --- a/user/model/service/user.go +++ b/user_module/model/service/user.go @@ -4,11 +4,11 @@ import ( "context" "errors" myerrors "octopus/hextech/errors" - "octopus/user/dto" - "octopus/user/infra/acl/convert" - "octopus/user/infra/query" - "octopus/user/infra/repository" - "octopus/user/model/domain/user" + "octopus/user_module/dto" + "octopus/user_module/infra/acl/convert" + "octopus/user_module/infra/query" + "octopus/user_module/infra/repository" + "octopus/user_module/model/domain/user" ) type UserService struct { diff --git a/user/router/captcha.go b/user_module/router/captcha.go similarity index 90% rename from user/router/captcha.go rename to user_module/router/captcha.go index db1874d..7bef11a 100644 --- a/user/router/captcha.go +++ b/user_module/router/captcha.go @@ -2,7 +2,7 @@ package router import ( "github.com/gin-gonic/gin" - "octopus/user/app/query" + "octopus/user_module/app/query" ) // captchaRouterGroup 验证码路由组 diff --git a/user/router/http.go b/user_module/router/http.go similarity index 69% rename from user/router/http.go rename to user_module/router/http.go index 7d41560..1530a8b 100644 --- a/user/router/http.go +++ b/user_module/router/http.go @@ -1,9 +1,10 @@ package router import ( - "octopus/user/app/command" - "octopus/user/app/query" - middleware "octopus/user/middleware/http" + hexmiddleware "octopus/hextech/middleware/http" + "octopus/user_module/app/command" + "octopus/user_module/app/query" + middleware "octopus/user_module/middleware/http" "time" "octopus/hextech/message" @@ -28,9 +29,9 @@ func HTTP(engine *gin.Engine) { } captchaRouterGroup(baseGroup) - baseGroup.POST("/login", middleware.VerifyCaptcha, middleware.LoginAfterRefreshJWT, command.Login) + baseGroup.POST("/login", middleware.VerifyCaptcha, hexmiddleware.LoginAfterRefreshJWT, command.Login) - engine.Use(middleware.JWT) + engine.Use(hexmiddleware.JWT) versionGroup := engine.Group("/v1") userRouter := versionGroup.Group("/user") { diff --git a/user/test/user_test.go b/user_module/test/user_test.go similarity index 100% rename from user/test/user_test.go rename to user_module/test/user_test.go -- Gitee