diff --git a/api/captcha_api/captcha_api.go b/api/captcha_api/captcha_api.go index 7d2fdac..c0fa196 100644 --- a/api/captcha_api/captcha_api.go +++ b/api/captcha_api/captcha_api.go @@ -10,7 +10,6 @@ import ( "github.com/wenlng/go-captcha/v2/rotate" "github.com/wenlng/go-captcha/v2/slide" "log" - "schisandra-cloud-album/api/captcha_api/dto" "schisandra-cloud-album/common/constant" "schisandra-cloud-album/common/redis" "schisandra-cloud-album/common/result" @@ -72,7 +71,7 @@ func (CaptchaAPI) GenerateRotateCaptcha(c *gin.Context) { // @Success 200 {string} json // @Router /api/captcha/rotate/check [post] func (CaptchaAPI) CheckRotateData(c *gin.Context) { - var rotateRequest dto.RotateCaptchaRequest + var rotateRequest RotateCaptchaRequest if err := c.ShouldBindJSON(&rotateRequest); err != nil { result.FailWithNull(c) return diff --git a/api/captcha_api/dto/request_dto.go b/api/captcha_api/request_param.go similarity index 86% rename from api/captcha_api/dto/request_dto.go rename to api/captcha_api/request_param.go index 9991310..e189bbf 100644 --- a/api/captcha_api/dto/request_dto.go +++ b/api/captcha_api/request_param.go @@ -1,4 +1,4 @@ -package dto +package captcha_api type RotateCaptchaRequest struct { Angle int `json:"angle" binding:"required"` diff --git a/api/comment_api/comment.go b/api/comment_api/comment.go index 4d9f53a..6432599 100644 --- a/api/comment_api/comment.go +++ b/api/comment_api/comment.go @@ -1,16 +1,7 @@ package comment_api import ( - "encoding/base64" - "errors" - "github.com/acmestack/gorm-plus/gplus" - "io" - "regexp" - "schisandra-cloud-album/api/comment_api/dto" - "schisandra-cloud-album/global" - "schisandra-cloud-album/model" "schisandra-cloud-album/service" - "strings" "sync" "time" ) @@ -61,166 +52,3 @@ type CommentResponse struct { Current int `json:"current"` Comments []CommentContent `json:"comments"` } - -// base64ToBytes 将base64字符串转换为字节数组 -func base64ToBytes(base64Str string) ([]byte, error) { - reader := base64.NewDecoder(base64.StdEncoding, strings.NewReader(base64Str)) - data, err := io.ReadAll(reader) - if err != nil { - return nil, errors.New("failed to decode base64 string") - } - return data, nil -} - -// processImages 处理图片,将 base64 字符串转换为字节数组 -func processImages(images []string) ([][]byte, error) { - var imagesData [][]byte - dataChan := make(chan []byte, len(images)) // 创建一个带缓冲的 channel - re := regexp.MustCompile(`^data:image/\w+;base64,`) - - for _, img := range images { - wg.Add(1) // 增加 WaitGroup 的计数 - go func(img string) { - defer wg.Done() // 函数结束时减少计数 - - imgWithoutPrefix := re.ReplaceAllString(img, "") - data, err := base64ToBytes(imgWithoutPrefix) - if err != nil { - return // 出错时直接返回 - } - dataChan <- data // 将结果发送到 channel - }(img) - } - - wg.Wait() // 等待所有 goroutine 完成 - close(dataChan) // 关闭 channel - - for data := range dataChan { // 收集所有结果 - imagesData = append(imagesData, data) - } - - return imagesData, nil -} - -// getMimeType 获取 MIME 类型 -func getMimeType(data []byte) string { - if len(data) < 4 { - return "application/octet-stream" // 默认类型 - } - - // 判断 JPEG - if data[0] == 0xFF && data[1] == 0xD8 { - return "image/jpeg" - } - - // 判断 PNG - if len(data) >= 8 && data[0] == 0x89 && data[1] == 0x50 && data[2] == 0x4E && data[3] == 0x47 && - data[4] == 0x0D && data[5] == 0x0A && data[6] == 0x1A && data[7] == 0x0A { - return "image/png" - } - - // 判断 GIF - if len(data) >= 6 && data[0] == 'G' && data[1] == 'I' && data[2] == 'F' { - return "image/gif" - } - // 判断 WEBP - if len(data) >= 12 && data[0] == 0x52 && data[1] == 0x49 && data[2] == 0x46 && data[3] == 0x46 && - data[8] == 0x57 && data[9] == 0x45 && data[10] == 0x42 && data[11] == 0x50 { - return "image/webp" - } - // 判断svg - if len(data) >= 4 && data[0] == '<' && data[1] == '?' && data[2] == 'x' && data[3] == 'm' { - return "image/svg+xml" - } - // 判断JPG - if len(data) >= 3 && data[0] == 0xFF && data[1] == 0xD8 && data[2] == 0xFF { - return "image/jpeg" - } - - return "application/octet-stream" // 默认类型 -} - -// 点赞 -var likeChannel = make(chan dto.CommentLikeRequest, 100) -var cancelLikeChannel = make(chan dto.CommentLikeRequest, 100) // 取消点赞 - -func init() { - go likeConsumer() // 启动消费者 - go cancelLikeConsumer() // 启动消费者 -} -func likeConsumer() { - for likeRequest := range likeChannel { - processLike(likeRequest) // 处理点赞 - } -} -func cancelLikeConsumer() { - for cancelLikeRequest := range cancelLikeChannel { - processCancelLike(cancelLikeRequest) // 处理取消点赞 - } -} - -func processLike(likeRequest dto.CommentLikeRequest) { - mx.Lock() - defer mx.Unlock() - - likes := model.ScaCommentLikes{ - CommentId: likeRequest.CommentId, - UserId: likeRequest.UserID, - TopicId: likeRequest.TopicId, - } - - tx := global.DB.Begin() - defer func() { - if r := recover(); r != nil { - tx.Rollback() - } - }() - - res := global.DB.Create(&likes) // 假设这是插入数据库的方法 - if res.Error != nil { - tx.Rollback() - global.LOG.Errorln(res.Error) - return - } - - // 异步更新点赞计数 - go func() { - if err := commentReplyService.UpdateCommentLikesCount(likeRequest.CommentId, likeRequest.TopicId); err != nil { - global.LOG.Errorln(err) - } - }() - - tx.Commit() -} -func processCancelLike(cancelLikeRequest dto.CommentLikeRequest) { - mx.Lock() - defer mx.Unlock() - - tx := global.DB.Begin() - defer func() { - if r := recover(); r != nil { - tx.Rollback() - } - }() - - query, u := gplus.NewQuery[model.ScaCommentLikes]() - query.Eq(&u.CommentId, cancelLikeRequest.CommentId). - Eq(&u.UserId, cancelLikeRequest.UserID). - Eq(&u.TopicId, cancelLikeRequest.TopicId) - - res := gplus.Delete[model.ScaCommentLikes](query) - if res.Error != nil { - tx.Rollback() - return // 返回错误而非打印 - } - - // 异步更新点赞计数 - go func() { - if err := commentReplyService.DecrementCommentLikesCount(cancelLikeRequest.CommentId, cancelLikeRequest.TopicId); err != nil { - global.LOG.Errorln(err) - } - }() - - tx.Commit() - return -} diff --git a/api/comment_api/comment_api.go b/api/comment_api/comment_api.go index c98cb99..b962c4a 100644 --- a/api/comment_api/comment_api.go +++ b/api/comment_api/comment_api.go @@ -10,7 +10,6 @@ import ( "github.com/mssola/useragent" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" - "schisandra-cloud-album/api/comment_api/dto" "schisandra-cloud-album/common/enum" "schisandra-cloud-album/common/result" "schisandra-cloud-album/global" @@ -25,10 +24,10 @@ import ( // @Tags 评论 // @Accept json // @Produce json -// @Param comment_request body dto.CommentRequest true "评论请求" +// @Param comment_request body CommentRequest true "评论请求" // @Router /auth/comment/submit [post] func (CommentAPI) CommentSubmit(c *gin.Context) { - commentRequest := dto.CommentRequest{} + commentRequest := CommentRequest{} if err := c.ShouldBindJSON(&commentRequest); err != nil { return } @@ -146,10 +145,10 @@ func (CommentAPI) CommentSubmit(c *gin.Context) { // @Tags 评论 // @Accept json // @Produce json -// @Param reply_comment_request body dto.ReplyCommentRequest true "回复评论请求" +// @Param reply_comment_request body ReplyCommentRequest true "回复评论请求" // @Router /auth/reply/submit [post] func (CommentAPI) ReplySubmit(c *gin.Context) { - replyCommentRequest := dto.ReplyCommentRequest{} + replyCommentRequest := ReplyCommentRequest{} if err := c.ShouldBindJSON(&replyCommentRequest); err != nil { result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) return @@ -273,10 +272,10 @@ func (CommentAPI) ReplySubmit(c *gin.Context) { // @Tags 评论 // @Accept json // @Produce json -// @Param reply_reply_request body dto.ReplyReplyRequest true "回复回复请求" +// @Param reply_reply_request body ReplyReplyRequest true "回复回复请求" // @Router /auth/reply/reply/submit [post] func (CommentAPI) ReplyReplySubmit(c *gin.Context) { - replyReplyRequest := dto.ReplyReplyRequest{} + replyReplyRequest := ReplyReplyRequest{} if err := c.ShouldBindJSON(&replyReplyRequest); err != nil { result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) return @@ -398,10 +397,10 @@ func (CommentAPI) ReplyReplySubmit(c *gin.Context) { // @Tags 评论 // @Accept json // @Produce json -// @Param comment_list_request body dto.CommentListRequest true "评论列表请求" +// @Param comment_list_request body CommentListRequest true "评论列表请求" // @Router /auth/comment/list [post] func (CommentAPI) CommentList(c *gin.Context) { - commentListRequest := dto.CommentListRequest{} + commentListRequest := CommentListRequest{} err := c.ShouldBindJSON(&commentListRequest) if err != nil { result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) @@ -573,10 +572,10 @@ func (CommentAPI) CommentList(c *gin.Context) { // @Tags 评论 // @Accept json // @Produce json -// @Param reply_list_request body dto.ReplyListRequest true "回复列表请求" +// @Param reply_list_request body ReplyListRequest true "回复列表请求" // @Router /auth/reply/list [post] func (CommentAPI) ReplyList(c *gin.Context) { - replyListRequest := dto.ReplyListRequest{} + replyListRequest := ReplyListRequest{} err := c.ShouldBindJSON(&replyListRequest) if err != nil { result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) @@ -754,10 +753,10 @@ func (CommentAPI) ReplyList(c *gin.Context) { // @Tags 评论 // @Accept json // @Produce json -// @Param comment_like_request body dto.CommentLikeRequest true "点赞请求" +// @Param comment_like_request body CommentLikeRequest true "点赞请求" // @Router /auth/comment/like [post] func (CommentAPI) CommentLikes(c *gin.Context) { - likeRequest := dto.CommentLikeRequest{} + likeRequest := CommentLikeRequest{} err := c.ShouldBindJSON(&likeRequest) if err != nil { result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) @@ -765,7 +764,7 @@ func (CommentAPI) CommentLikes(c *gin.Context) { } // 将点赞请求发送到 channel 中 - likeChannel <- dto.CommentLikeRequest{ + likeChannel <- CommentLikeRequest{ CommentId: likeRequest.CommentId, UserID: likeRequest.UserID, TopicId: likeRequest.TopicId, @@ -780,16 +779,16 @@ func (CommentAPI) CommentLikes(c *gin.Context) { // @Tags 评论 // @Accept json // @Produce json -// @Param comment_like_request body dto.CommentLikeRequest true "取消点赞请求" +// @Param comment_like_request body CommentLikeRequest true "取消点赞请求" // @Router /auth/comment/cancel_like [post] func (CommentAPI) CancelCommentLikes(c *gin.Context) { - likeRequest := dto.CommentLikeRequest{} + likeRequest := CommentLikeRequest{} if err := c.ShouldBindJSON(&likeRequest); err != nil { result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) return } // 将取消点赞请求发送到 channel - cancelLikeChannel <- dto.CommentLikeRequest{ + cancelLikeChannel <- CommentLikeRequest{ CommentId: likeRequest.CommentId, UserID: likeRequest.UserID, TopicId: likeRequest.TopicId, diff --git a/api/comment_api/handler.go b/api/comment_api/handler.go new file mode 100644 index 0000000..8860f07 --- /dev/null +++ b/api/comment_api/handler.go @@ -0,0 +1,175 @@ +package comment_api + +import ( + "encoding/base64" + "errors" + "github.com/acmestack/gorm-plus/gplus" + "io" + "regexp" + "schisandra-cloud-album/global" + "schisandra-cloud-album/model" + "strings" +) + +// base64ToBytes 将base64字符串转换为字节数组 +func base64ToBytes(base64Str string) ([]byte, error) { + reader := base64.NewDecoder(base64.StdEncoding, strings.NewReader(base64Str)) + data, err := io.ReadAll(reader) + if err != nil { + return nil, errors.New("failed to decode base64 string") + } + return data, nil +} + +// processImages 处理图片,将 base64 字符串转换为字节数组 +func processImages(images []string) ([][]byte, error) { + var imagesData [][]byte + dataChan := make(chan []byte, len(images)) // 创建一个带缓冲的 channel + re := regexp.MustCompile(`^data:image/\w+;base64,`) + + for _, img := range images { + wg.Add(1) // 增加 WaitGroup 的计数 + go func(img string) { + defer wg.Done() // 函数结束时减少计数 + + imgWithoutPrefix := re.ReplaceAllString(img, "") + data, err := base64ToBytes(imgWithoutPrefix) + if err != nil { + return // 出错时直接返回 + } + dataChan <- data // 将结果发送到 channel + }(img) + } + + wg.Wait() // 等待所有 goroutine 完成 + close(dataChan) // 关闭 channel + + for data := range dataChan { // 收集所有结果 + imagesData = append(imagesData, data) + } + + return imagesData, nil +} + +// getMimeType 获取 MIME 类型 +func getMimeType(data []byte) string { + if len(data) < 4 { + return "application/octet-stream" // 默认类型 + } + + // 判断 JPEG + if data[0] == 0xFF && data[1] == 0xD8 { + return "image/jpeg" + } + + // 判断 PNG + if len(data) >= 8 && data[0] == 0x89 && data[1] == 0x50 && data[2] == 0x4E && data[3] == 0x47 && + data[4] == 0x0D && data[5] == 0x0A && data[6] == 0x1A && data[7] == 0x0A { + return "image/png" + } + + // 判断 GIF + if len(data) >= 6 && data[0] == 'G' && data[1] == 'I' && data[2] == 'F' { + return "image/gif" + } + // 判断 WEBP + if len(data) >= 12 && data[0] == 0x52 && data[1] == 0x49 && data[2] == 0x46 && data[3] == 0x46 && + data[8] == 0x57 && data[9] == 0x45 && data[10] == 0x42 && data[11] == 0x50 { + return "image/webp" + } + // 判断svg + if len(data) >= 4 && data[0] == '<' && data[1] == '?' && data[2] == 'x' && data[3] == 'm' { + return "image/svg+xml" + } + // 判断JPG + if len(data) >= 3 && data[0] == 0xFF && data[1] == 0xD8 && data[2] == 0xFF { + return "image/jpeg" + } + + return "application/octet-stream" // 默认类型 +} + +// 点赞 +var likeChannel = make(chan CommentLikeRequest, 100) +var cancelLikeChannel = make(chan CommentLikeRequest, 100) // 取消点赞 + +func init() { + go likeConsumer() // 启动消费者 + go cancelLikeConsumer() // 启动消费者 +} +func likeConsumer() { + for likeRequest := range likeChannel { + processLike(likeRequest) // 处理点赞 + } +} +func cancelLikeConsumer() { + for cancelLikeRequest := range cancelLikeChannel { + processCancelLike(cancelLikeRequest) // 处理取消点赞 + } +} + +func processLike(likeRequest CommentLikeRequest) { + mx.Lock() + defer mx.Unlock() + + likes := model.ScaCommentLikes{ + CommentId: likeRequest.CommentId, + UserId: likeRequest.UserID, + TopicId: likeRequest.TopicId, + } + + tx := global.DB.Begin() + defer func() { + if r := recover(); r != nil { + tx.Rollback() + } + }() + + res := global.DB.Create(&likes) // 假设这是插入数据库的方法 + if res.Error != nil { + tx.Rollback() + global.LOG.Errorln(res.Error) + return + } + + // 异步更新点赞计数 + go func() { + if err := commentReplyService.UpdateCommentLikesCount(likeRequest.CommentId, likeRequest.TopicId); err != nil { + global.LOG.Errorln(err) + } + }() + + tx.Commit() +} +func processCancelLike(cancelLikeRequest CommentLikeRequest) { + mx.Lock() + defer mx.Unlock() + + tx := global.DB.Begin() + defer func() { + if r := recover(); r != nil { + tx.Rollback() + } + }() + + query, u := gplus.NewQuery[model.ScaCommentLikes]() + query.Eq(&u.CommentId, cancelLikeRequest.CommentId). + Eq(&u.UserId, cancelLikeRequest.UserID). + Eq(&u.TopicId, cancelLikeRequest.TopicId) + + res := gplus.Delete[model.ScaCommentLikes](query) + if res.Error != nil { + tx.Rollback() + return // 返回错误而非打印 + } + + // 异步更新点赞计数 + go func() { + if err := commentReplyService.DecrementCommentLikesCount(cancelLikeRequest.CommentId, cancelLikeRequest.TopicId); err != nil { + global.LOG.Errorln(err) + } + }() + + tx.Commit() + return +} diff --git a/api/comment_api/dto/request_dto.go b/api/comment_api/request_param.go similarity index 99% rename from api/comment_api/dto/request_dto.go rename to api/comment_api/request_param.go index c2ad2a4..5302bcf 100644 --- a/api/comment_api/dto/request_dto.go +++ b/api/comment_api/request_param.go @@ -1,4 +1,4 @@ -package dto +package comment_api type CommentRequest struct { Content string `json:"content" binding:"required"` diff --git a/api/oauth_api/oauth.go b/api/oauth_api/oauth.go index 42435a0..daec188 100644 --- a/api/oauth_api/oauth.go +++ b/api/oauth_api/oauth.go @@ -8,7 +8,6 @@ import ( "github.com/mssola/useragent" "gorm.io/gorm" "net/http" - "schisandra-cloud-album/api/user_api/dto" "schisandra-cloud-album/common/constant" "schisandra-cloud-album/common/redis" "schisandra-cloud-album/common/result" @@ -95,13 +94,13 @@ func HandelUserLogin(userId string, c *gin.Context) (bool, result.Response) { case expiresAt = <-expiresAtChan: } - data := dto.ResponseData{ + data := ResponseData{ AccessToken: accessToken, RefreshToken: refreshToken, ExpiresAt: expiresAt, UID: &userId, } - wrong := utils.SetSession(c, "user", data) + wrong := utils.SetSession(c, constant.SessionKey, data) if wrong != nil { return false, result.Response{} } diff --git a/api/oauth_api/request_param.go b/api/oauth_api/request_param.go new file mode 100644 index 0000000..4f07c02 --- /dev/null +++ b/api/oauth_api/request_param.go @@ -0,0 +1,19 @@ +package oauth_api + +import "encoding/json" + +// ResponseData 返回数据 +type ResponseData struct { + AccessToken string `json:"access_token"` + RefreshToken string `json:"refresh_token"` + ExpiresAt int64 `json:"expires_at"` + UID *string `json:"uid"` +} + +func (res ResponseData) MarshalBinary() ([]byte, error) { + return json.Marshal(res) +} + +func (res ResponseData) UnmarshalBinary(data []byte) error { + return json.Unmarshal(data, &res) +} diff --git a/api/oauth_api/wechat_api.go b/api/oauth_api/wechat_api.go index bfbc1b6..8e22a21 100644 --- a/api/oauth_api/wechat_api.go +++ b/api/oauth_api/wechat_api.go @@ -14,7 +14,6 @@ import ( "github.com/gin-gonic/gin" "github.com/yitter/idgenerator-go/idgen" "gorm.io/gorm" - "schisandra-cloud-album/api/user_api/dto" "schisandra-cloud-album/api/websocket_api" "schisandra-cloud-album/common/constant" "schisandra-cloud-album/common/enum" @@ -291,7 +290,7 @@ func handelUserLogin(userId string, clientId string, c *gin.Context) bool { return } refreshToken, expiresAt := utils.GenerateRefreshToken(utils.RefreshJWTPayload{UserID: &userId}, time.Hour*24*7) - data := dto.ResponseData{ + data := ResponseData{ AccessToken: accessToken, RefreshToken: refreshToken, ExpiresAt: expiresAt, @@ -313,8 +312,8 @@ func handelUserLogin(userId string, clientId string, c *gin.Context) bool { resultChan <- false return } - gob.Register(dto.ResponseData{}) - wrong := utils.SetSession(c, "user", data) + gob.Register(ResponseData{}) + wrong := utils.SetSession(c, constant.SessionKey, data) if wrong != nil { resultChan <- false return diff --git a/api/permission_api/permission_api.go b/api/permission_api/permission_api.go index 1e1b907..83ea909 100644 --- a/api/permission_api/permission_api.go +++ b/api/permission_api/permission_api.go @@ -3,7 +3,6 @@ package permission_api import ( ginI18n "github.com/gin-contrib/i18n" "github.com/gin-gonic/gin" - "schisandra-cloud-album/api/permission_api/dto" "schisandra-cloud-album/common/result" "schisandra-cloud-album/global" "schisandra-cloud-album/service" @@ -17,16 +16,16 @@ var permissionService = service.Service.PermissionService // @Tags 权限管理 // @Accept json // @Produce json -// @Param permissions body dto.AddPermissionRequestDto true "权限列表" +// @Param permissions body AddPermissionRequest true "权限列表" // @Router /api/auth/permission/add [post] func (PermissionAPI) AddPermissions(c *gin.Context) { - addPermissionRequestDto := dto.AddPermissionRequestDto{} - err := c.ShouldBind(&addPermissionRequestDto.Permissions) + addPermissionRequest := AddPermissionRequest{} + err := c.ShouldBind(&addPermissionRequest.Permissions) if err != nil { global.LOG.Error(err) return } - err = permissionService.CreatePermissions(addPermissionRequestDto.Permissions) + err = permissionService.CreatePermissions(addPermissionRequest.Permissions) if err != nil { global.LOG.Error(err) result.FailWithMessage(ginI18n.MustGetMessage(c, "CreatedFailed"), c) @@ -42,12 +41,12 @@ func (PermissionAPI) AddPermissions(c *gin.Context) { // @Tags 权限管理 // @Accept json // @Produce json -// @Param permissions body dto.AddPermissionToRoleRequestDto true "权限列表" +// @Param permissions body AddPermissionToRoleRequest true "权限列表" // @Router /api/auth/permission/assign [post] func (PermissionAPI) AssignPermissionsToRole(c *gin.Context) { - permissionToRoleRequestDto := dto.AddPermissionToRoleRequestDto{} + permissionToRoleRequest := AddPermissionToRoleRequest{} - err := c.ShouldBind(&permissionToRoleRequestDto) + err := c.ShouldBind(&permissionToRoleRequest) if err != nil { global.LOG.Error(err) @@ -55,7 +54,7 @@ func (PermissionAPI) AssignPermissionsToRole(c *gin.Context) { return } - policy, err := global.Casbin.AddPolicy(permissionToRoleRequestDto.RoleKey, permissionToRoleRequestDto.Permission, permissionToRoleRequestDto.Method) + policy, err := global.Casbin.AddPolicy(permissionToRoleRequest.RoleKey, permissionToRoleRequest.Permission, permissionToRoleRequest.Method) if err != nil { global.LOG.Error(err) result.FailWithMessage(ginI18n.MustGetMessage(c, "AssignFailed"), c) @@ -71,7 +70,7 @@ func (PermissionAPI) AssignPermissionsToRole(c *gin.Context) { // GetUserPermissions 获取用户角色权限 func (PermissionAPI) GetUserPermissions(c *gin.Context) { - getPermissionRequest := dto.GetPermissionRequest{} + getPermissionRequest := GetPermissionRequest{} err := c.ShouldBindJSON(&getPermissionRequest) if err != nil { global.LOG.Error(err) diff --git a/api/permission_api/dto/request_dto.go b/api/permission_api/request_param.go similarity index 53% rename from api/permission_api/dto/request_dto.go rename to api/permission_api/request_param.go index 8e81f4c..da76c24 100644 --- a/api/permission_api/dto/request_dto.go +++ b/api/permission_api/request_param.go @@ -1,16 +1,14 @@ -package dto +package permission_api -import ( - "schisandra-cloud-album/model" -) +import "schisandra-cloud-album/model" -// AddPermissionRequestDto 添加权限请求dto -type AddPermissionRequestDto struct { +// AddPermissionToRoleRequest 添加权限请求 +type AddPermissionRequest struct { Permissions []model.ScaAuthPermission `form:"permissions[]" json:"permissions"` } -// AddPermissionToRoleRequestDto 添加权限到角色请求dto -type AddPermissionToRoleRequestDto struct { +// AddPermissionToRoleRequest 添加权限到角色请求 +type AddPermissionToRoleRequest struct { RoleKey string `json:"role_key"` Permission string `json:"permission"` Method string `json:"method"` diff --git a/api/role_api/dto/request_dto.go b/api/role_api/request_param.go similarity index 73% rename from api/role_api/dto/request_dto.go rename to api/role_api/request_param.go index f224806..e32ac4a 100644 --- a/api/role_api/dto/request_dto.go +++ b/api/role_api/request_param.go @@ -1,11 +1,11 @@ -package dto +package role_api -type RoleRequestDto struct { +type RoleRequest struct { RoleName string `json:"role_name" binding:"required"` RoleKey string `json:"role_key" binding:"required"` } -type AddRoleToUserRequestDto struct { +type AddRoleToUserRequest struct { Uid string `json:"uid" binding:"required"` RoleKey string `json:"role_key" binding:"required"` } diff --git a/api/role_api/role_api.go b/api/role_api/role_api.go index 64d6706..e37cb13 100644 --- a/api/role_api/role_api.go +++ b/api/role_api/role_api.go @@ -3,7 +3,6 @@ package role_api import ( ginI18n "github.com/gin-contrib/i18n" "github.com/gin-gonic/gin" - "schisandra-cloud-album/api/role_api/dto" "schisandra-cloud-album/common/result" "schisandra-cloud-album/global" "schisandra-cloud-album/model" @@ -18,18 +17,18 @@ var roleService = service.Service.RoleService // @Tags 角色 // @Accept json // @Produce json -// @Param roleRequestDto body dto.RoleRequestDto true "角色信息" +// @Param roleRequestDto body RoleRequest true "角色信息" // @Router /api/auth/role/create [post] func (RoleAPI) CreateRole(c *gin.Context) { - roleRequestDto := dto.RoleRequestDto{} - err := c.ShouldBindJSON(&roleRequestDto) + roleRequest := RoleRequest{} + err := c.ShouldBindJSON(&roleRequest) if err != nil { result.FailWithMessage(ginI18n.MustGetMessage(c, "CreatedFailed"), c) return } role := model.ScaAuthRole{ - RoleName: roleRequestDto.RoleName, - RoleKey: roleRequestDto.RoleKey, + RoleName: roleRequest.RoleName, + RoleKey: roleRequest.RoleKey, } err = roleService.AddRole(role) if err != nil { @@ -46,16 +45,16 @@ func (RoleAPI) CreateRole(c *gin.Context) { // @Tags 角色 // @Accept json // @Produce json -// @Param addRoleToUserRequestDto body dto.AddRoleToUserRequestDto true "给指定用户添加角色" +// @Param addRoleToUserRequestDto body AddRoleToUserRequest true "给指定用户添加角色" // @Router /api/auth/role/add_role_to_user [post] func (RoleAPI) AddRoleToUser(c *gin.Context) { - addRoleToUserRequestDto := dto.AddRoleToUserRequestDto{} - err := c.ShouldBindJSON(&addRoleToUserRequestDto) + addRoleToUserRequest := AddRoleToUserRequest{} + err := c.ShouldBindJSON(&addRoleToUserRequest) if err != nil { global.LOG.Error(err) return } - user, err := global.Casbin.AddRoleForUser(addRoleToUserRequestDto.Uid, addRoleToUserRequestDto.RoleKey) + user, err := global.Casbin.AddRoleForUser(addRoleToUserRequest.Uid, addRoleToUserRequest.RoleKey) if err != nil { global.LOG.Error(err) return diff --git a/api/sms_api/dto/request_dto.go b/api/sms_api/request_param.go similarity index 91% rename from api/sms_api/dto/request_dto.go rename to api/sms_api/request_param.go index 99fb94e..a211515 100644 --- a/api/sms_api/dto/request_dto.go +++ b/api/sms_api/request_param.go @@ -1,4 +1,4 @@ -package dto +package sms_api type SmsRequest struct { Phone string `json:"phone" binding:"required"` diff --git a/api/sms_api/sms_api.go b/api/sms_api/sms_api.go index 2c62830..b156c02 100644 --- a/api/sms_api/sms_api.go +++ b/api/sms_api/sms_api.go @@ -7,7 +7,6 @@ import ( "github.com/pkg6/go-sms/gateways" "github.com/pkg6/go-sms/gateways/aliyun" "github.com/pkg6/go-sms/gateways/smsbao" - "schisandra-cloud-album/api/sms_api/dto" "schisandra-cloud-album/common/constant" "schisandra-cloud-album/common/redis" "schisandra-cloud-album/common/result" @@ -24,7 +23,7 @@ import ( // @Param phone query string true "手机号" // @Router /api/sms/ali/send [get] func (SmsAPI) SendMessageByAli(c *gin.Context) { - smsRequest := dto.SmsRequest{} + smsRequest := SmsRequest{} err := c.ShouldBindJSON(&smsRequest) if err != nil { result.FailWithMessage(ginI18n.MustGetMessage(c, "CaptchaSendFailed"), c) @@ -83,7 +82,7 @@ func (SmsAPI) SendMessageByAli(c *gin.Context) { // @Param phone query string true "手机号" // @Router /api/sms/smsbao/send [post] func (SmsAPI) SendMessageBySmsBao(c *gin.Context) { - smsRequest := dto.SmsRequest{} + smsRequest := SmsRequest{} err := c.ShouldBindJSON(&smsRequest) if err != nil { result.FailWithMessage(ginI18n.MustGetMessage(c, "CaptchaSendFailed"), c) @@ -135,7 +134,7 @@ func (SmsAPI) SendMessageBySmsBao(c *gin.Context) { // @Param phone query string true "手机号" // @Router /api/sms/test/send [post] func (SmsAPI) SendMessageTest(c *gin.Context) { - smsRequest := dto.SmsRequest{} + smsRequest := SmsRequest{} err := c.ShouldBindJSON(&smsRequest) if err != nil { result.FailWithMessage(ginI18n.MustGetMessage(c, "CaptchaSendFailed"), c) diff --git a/api/user_api/handler.go b/api/user_api/handler.go new file mode 100644 index 0000000..f8ae59c --- /dev/null +++ b/api/user_api/handler.go @@ -0,0 +1,134 @@ +package user_api + +import ( + "encoding/gob" + "errors" + ginI18n "github.com/gin-contrib/i18n" + "github.com/gin-gonic/gin" + "github.com/mssola/useragent" + "gorm.io/gorm" + "schisandra-cloud-album/common/constant" + "schisandra-cloud-album/common/redis" + "schisandra-cloud-album/common/result" + "schisandra-cloud-album/global" + "schisandra-cloud-album/model" + "schisandra-cloud-album/utils" + "time" +) + +// getUserLoginDevice 获取用户登录设备 +func getUserLoginDevice(user model.ScaAuthUser, c *gin.Context) bool { + + // 检查user.UID是否为空 + if user.UID == nil { + global.LOG.Errorln("user.UID is nil") + return false + } + userAgent := c.GetHeader("User-Agent") + if userAgent == "" { + global.LOG.Errorln("user-agent is empty") + return false + } + ua := useragent.New(userAgent) + + ip := utils.GetClientIP(c) + location, err := global.IP2Location.SearchByStr(ip) + if err != nil { + global.LOG.Errorln(err) + return false + } + location = utils.RemoveZeroAndAdjust(location) + + isBot := ua.Bot() + browser, browserVersion := ua.Browser() + os := ua.OS() + mobile := ua.Mobile() + mozilla := ua.Mozilla() + platform := ua.Platform() + engine, engineVersion := ua.Engine() + + device := model.ScaAuthUserDevice{ + UserID: user.UID, + IP: &ip, + Location: &location, + Agent: userAgent, + Browser: &browser, + BrowserVersion: &browserVersion, + OperatingSystem: &os, + Mobile: &mobile, + Bot: &isBot, + Mozilla: &mozilla, + Platform: &platform, + EngineName: &engine, + EngineVersion: &engineVersion, + } + + mu.Lock() + defer mu.Unlock() + + userDevice, err := userDeviceService.GetUserDeviceByUIDIPAgent(*user.UID, ip, userAgent) + if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { + err = userDeviceService.AddUserDevice(&device) + if err != nil { + global.LOG.Errorln(err) + return false + } + } else if err != nil { + global.LOG.Errorln(err) + return false + } else { + err := userDeviceService.UpdateUserDevice(userDevice.ID, &device) + if err != nil { + global.LOG.Errorln(err) + return false + } + } + + return true +} + +// handelUserLogin 处理用户登录 +func handelUserLogin(user model.ScaAuthUser, autoLogin bool, c *gin.Context) { + // 检查 user.UID 是否为 nil + if user.UID == nil { + result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) + return + } + if !getUserLoginDevice(user, c) { + result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) + return + } + accessToken, err := utils.GenerateAccessToken(utils.AccessJWTPayload{UserID: user.UID}) + if err != nil { + result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) + return + } + + var days time.Duration + if autoLogin { + days = 7 * 24 * time.Hour + } else { + days = time.Minute * 30 + } + + refreshToken, expiresAt := utils.GenerateRefreshToken(utils.RefreshJWTPayload{UserID: user.UID}, days) + data := ResponseData{ + AccessToken: accessToken, + RefreshToken: refreshToken, + ExpiresAt: expiresAt, + UID: user.UID, + } + + err = redis.Set(constant.UserLoginTokenRedisKey+*user.UID, data, days).Err() + if err != nil { + result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) + return + } + gob.Register(ResponseData{}) + err = utils.SetSession(c, constant.SessionKey, data) + if err != nil { + result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) + return + } + result.OkWithData(data, c) +} diff --git a/api/user_api/dto/request_dto.go b/api/user_api/request_param.go similarity index 99% rename from api/user_api/dto/request_dto.go rename to api/user_api/request_param.go index 9ff9802..7def8ab 100644 --- a/api/user_api/dto/request_dto.go +++ b/api/user_api/request_param.go @@ -1,4 +1,4 @@ -package dto +package user_api import "encoding/json" diff --git a/api/user_api/user_api.go b/api/user_api/user_api.go index 4c08216..fa66853 100644 --- a/api/user_api/user_api.go +++ b/api/user_api/user_api.go @@ -1,15 +1,11 @@ package user_api import ( - "encoding/gob" - "errors" ginI18n "github.com/gin-contrib/i18n" "github.com/gin-gonic/gin" - "github.com/mssola/useragent" "github.com/yitter/idgenerator-go/idgen" "gorm.io/gorm" "reflect" - "schisandra-cloud-album/api/user_api/dto" "schisandra-cloud-album/common/constant" "schisandra-cloud-album/common/enum" "schisandra-cloud-album/common/randomname" @@ -107,11 +103,11 @@ func (UserAPI) QueryUserByPhone(c *gin.Context) { // AccountLogin 账号登录 // @Summary 账号登录 // @Tags 用户模块 -// @Param user body dto.AccountLoginRequest true "用户信息" +// @Param user body AccountLoginRequest true "用户信息" // @Success 200 {string} json // @Router /api/user/login [post] func (UserAPI) AccountLogin(c *gin.Context) { - accountLoginRequest := dto.AccountLoginRequest{} + accountLoginRequest := AccountLoginRequest{} err := c.ShouldBindJSON(&accountLoginRequest) if err != nil { result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) @@ -152,11 +148,11 @@ func (UserAPI) AccountLogin(c *gin.Context) { // PhoneLogin 手机号登录/注册 // @Summary 手机号登录/注册 // @Tags 用户模块 -// @Param user body dto.PhoneLoginRequest true "用户信息" +// @Param user body PhoneLoginRequest true "用户信息" // @Success 200 {string} json // @Router /api/user/phone_login [post] func (UserAPI) PhoneLogin(c *gin.Context) { - request := dto.PhoneLoginRequest{} + request := PhoneLoginRequest{} err := c.ShouldBind(&request) if err != nil { result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) @@ -265,7 +261,7 @@ func (UserAPI) PhoneLogin(c *gin.Context) { // @Success 200 {string} json // @Router /api/token/refresh [post] func (UserAPI) RefreshHandler(c *gin.Context) { - request := dto.RefreshTokenRequest{} + request := RefreshTokenRequest{} if err := c.ShouldBindJSON(&request); err != nil { result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) return @@ -289,7 +285,7 @@ func (UserAPI) RefreshHandler(c *gin.Context) { result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginExpired"), c) return } - data := dto.ResponseData{ + data := ResponseData{ AccessToken: accessTokenString, RefreshToken: refreshToken, UID: parseRefreshToken.UserID, @@ -301,60 +297,14 @@ func (UserAPI) RefreshHandler(c *gin.Context) { result.OkWithData(data, c) } -// handelUserLogin 处理用户登录 -func handelUserLogin(user model.ScaAuthUser, autoLogin bool, c *gin.Context) { - // 检查 user.UID 是否为 nil - if user.UID == nil { - result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) - return - } - if !getUserLoginDevice(user, c) { - result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) - return - } - accessToken, err := utils.GenerateAccessToken(utils.AccessJWTPayload{UserID: user.UID}) - if err != nil { - result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) - return - } - - var days time.Duration - if autoLogin { - days = 7 * 24 * time.Hour - } else { - days = time.Minute * 30 - } - - refreshToken, expiresAt := utils.GenerateRefreshToken(utils.RefreshJWTPayload{UserID: user.UID}, days) - data := dto.ResponseData{ - AccessToken: accessToken, - RefreshToken: refreshToken, - ExpiresAt: expiresAt, - UID: user.UID, - } - - err = redis.Set(constant.UserLoginTokenRedisKey+*user.UID, data, days).Err() - if err != nil { - result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) - return - } - gob.Register(dto.ResponseData{}) - err = utils.SetSession(c, "user", data) - if err != nil { - result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) - return - } - result.OkWithData(data, c) -} - // ResetPassword 重置密码 // @Summary 重置密码 // @Tags 用户模块 -// @Param user body dto.ResetPasswordRequest true "用户信息" +// @Param user body ResetPasswordRequest true "用户信息" // @Success 200 {string} json // @Router /api/user/reset_password [post] func (UserAPI) ResetPassword(c *gin.Context) { - var resetPasswordRequest dto.ResetPasswordRequest + var resetPasswordRequest ResetPasswordRequest if err := c.ShouldBindJSON(&resetPasswordRequest); err != nil { result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) return @@ -432,77 +382,6 @@ func (UserAPI) ResetPassword(c *gin.Context) { result.OkWithMessage(ginI18n.MustGetMessage(c, "ResetPasswordSuccess"), c) } -// getUserLoginDevice 获取用户登录设备 -func getUserLoginDevice(user model.ScaAuthUser, c *gin.Context) bool { - - // 检查user.UID是否为空 - if user.UID == nil { - global.LOG.Errorln("user.UID is nil") - return false - } - userAgent := c.GetHeader("User-Agent") - if userAgent == "" { - global.LOG.Errorln("user-agent is empty") - return false - } - ua := useragent.New(userAgent) - - ip := utils.GetClientIP(c) - location, err := global.IP2Location.SearchByStr(ip) - if err != nil { - global.LOG.Errorln(err) - return false - } - location = utils.RemoveZeroAndAdjust(location) - - isBot := ua.Bot() - browser, browserVersion := ua.Browser() - os := ua.OS() - mobile := ua.Mobile() - mozilla := ua.Mozilla() - platform := ua.Platform() - engine, engineVersion := ua.Engine() - - device := model.ScaAuthUserDevice{ - UserID: user.UID, - IP: &ip, - Location: &location, - Agent: userAgent, - Browser: &browser, - BrowserVersion: &browserVersion, - OperatingSystem: &os, - Mobile: &mobile, - Bot: &isBot, - Mozilla: &mozilla, - Platform: &platform, - EngineName: &engine, - EngineVersion: &engineVersion, - } - - mu.Lock() - defer mu.Unlock() - - userDevice, err := userDeviceService.GetUserDeviceByUIDIPAgent(*user.UID, ip, userAgent) - if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { - err = userDeviceService.AddUserDevice(&device) - if err != nil { - global.LOG.Errorln(err) - return false - } - } else if err != nil { - global.LOG.Errorln(err) - return false - } else { - err := userDeviceService.UpdateUserDevice(userDevice.ID, &device) - if err != nil { - global.LOG.Errorln(err) - return false - } - } - - return true -} - // Logout 退出登录 // @Summary 退出登录 // @Tags 用户模块 diff --git a/common/constant/session_key.go b/common/constant/session_key.go new file mode 100644 index 0000000..c25b2ab --- /dev/null +++ b/common/constant/session_key.go @@ -0,0 +1,5 @@ +package constant + +const ( + SessionKey = "SESSION" +) diff --git a/config/conf_nsq.go b/config/conf_nsq.go new file mode 100644 index 0000000..e176f2a --- /dev/null +++ b/config/conf_nsq.go @@ -0,0 +1,12 @@ +package config + +import "fmt" + +type NSQ struct { + Host string `yaml:"host"` + Port int `yaml:"port"` +} + +func (n *NSQ) Addr() string { + return fmt.Sprintf("%s:%d", n.Host, n.Port) +} diff --git a/config/config.go b/config/config.go index 6f526d2..227dc6a 100644 --- a/config/config.go +++ b/config/config.go @@ -13,4 +13,5 @@ type Config struct { Swagger Swagger `yaml:"swagger"` Casbin Casbin `yaml:"casbin"` MongoDB MongoDB `yaml:"mongodb"` + NSQ NSQ `yaml:"nsq"` } diff --git a/core/ip2region.go b/core/ip2region.go index 073f080..82d0394 100644 --- a/core/ip2region.go +++ b/core/ip2region.go @@ -6,7 +6,7 @@ import ( ) func InitIP2Region() { - var dbPath = "ip2region/ip2region.xdb" + var dbPath = "resource/ip2region/ip2region.xdb" cBuff, err := xdb.LoadContentFromFile(dbPath) if err != nil { global.LOG.Errorf("failed to load vector index from `%s`: %s\n", dbPath, err) diff --git a/core/nsq.go b/core/nsq.go new file mode 100644 index 0000000..668cc20 --- /dev/null +++ b/core/nsq.go @@ -0,0 +1,31 @@ +package core + +import ( + "fmt" + "github.com/nsqio/go-nsq" + "schisandra-cloud-album/global" + "time" +) + +// InitNSQProducer 初始化生产者 +func InitNSQProducer() *nsq.Producer { + config := nsq.NewConfig() + producer, err := nsq.NewProducer(global.CONFIG.NSQ.Addr(), config) + if err != nil { + global.LOG.Error(fmt.Sprintf("InitNSQ producer error: %v", err)) + return nil + } + return producer +} + +// InitConsumer 初始化消费者 +func InitConsumer(topic string, channel string) *nsq.Consumer { + config := nsq.NewConfig() + config.LookupdPollInterval = 15 * time.Second + consumer, err := nsq.NewConsumer(topic, channel, config) + if err != nil { + fmt.Printf("InitNSQ consumer error: %v\n", err) + return nil + } + return consumer +} diff --git a/docs/docs.go b/docs/docs.go index 1f4ce99..8c85a94 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -35,7 +35,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.AddPermissionRequestDto" + "$ref": "#/definitions/permission_api.AddPermissionRequest" } } ], @@ -62,7 +62,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.AddPermissionToRoleRequestDto" + "$ref": "#/definitions/permission_api.AddPermissionToRoleRequest" } } ], @@ -89,7 +89,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.AddRoleToUserRequestDto" + "$ref": "#/definitions/role_api.AddRoleToUserRequest" } } ], @@ -116,7 +116,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.RoleRequestDto" + "$ref": "#/definitions/role_api.RoleRequest" } } ], @@ -305,23 +305,6 @@ const docTemplate = `{ } } }, - "/api/captcha/shape/check": { - "get": { - "description": "生成点击形状基础验证码", - "tags": [ - "点击形状验证码" - ], - "summary": "生成点击形状基础验证码", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, "/api/captcha/shape/get": { "get": { "description": "生成点击形状验证码", @@ -341,11 +324,11 @@ const docTemplate = `{ }, "/api/captcha/shape/slide/check": { "get": { - "description": "验证点击形状验证码", + "description": "验证滑动验证码", "tags": [ - "点击形状验证码" + "验证滑动验证码" ], - "summary": "验证点击形状验证码", + "summary": "验证滑动验证码", "parameters": [ { "type": "string", @@ -374,11 +357,28 @@ const docTemplate = `{ }, "/api/captcha/shape/slide/region/get": { "get": { - "description": "生成点击形状验证码", + "description": "生成滑动区域形状验证码", "tags": [ - "点击形状验证码" + "生成滑动区域形状验证码" ], - "summary": "生成点击形状验证码", + "summary": "生成滑动区域形状验证码", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/captcha/slide/generate": { + "get": { + "description": "滑块基础验证码", + "tags": [ + "滑块基础验证码" + ], + "summary": "滑块基础验证码", "responses": { "200": { "description": "OK", @@ -448,60 +448,6 @@ const docTemplate = `{ } } }, - "/api/comment/reply": { - "post": { - "description": "提交回复", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "评论" - ], - "summary": "提交回复", - "parameters": [ - { - "description": "回复评论请求", - "name": "reply_comment_request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ReplyCommentRequest" - } - } - ], - "responses": {} - } - }, - "/api/comment/submit": { - "post": { - "description": "提交评论", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "评论" - ], - "summary": "提交评论", - "parameters": [ - { - "description": "评论请求", - "name": "comment_request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.CommentRequest" - } - } - ], - "responses": {} - } - }, "/api/oauth/callback_notify": { "post": { "description": "微信回调", @@ -701,7 +647,7 @@ const docTemplate = `{ } }, "/api/sms/smsbao/send": { - "get": { + "post": { "description": "短信宝发送短信验证码", "produces": [ "application/json" @@ -723,7 +669,7 @@ const docTemplate = `{ } }, "/api/sms/test/send": { - "get": { + "post": { "description": "发送测试短信验证码", "produces": [ "application/json" @@ -782,7 +728,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.AccountLoginRequest" + "$ref": "#/definitions/user_api.AccountLoginRequest" } } ], @@ -809,7 +755,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.PhoneLoginRequest" + "$ref": "#/definitions/user_api.PhoneLoginRequest" } } ], @@ -836,7 +782,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.ResetPasswordRequest" + "$ref": "#/definitions/user_api.ResetPasswordRequest" } } ], @@ -859,62 +805,258 @@ const docTemplate = `{ "summary": "创建websocket服务", "responses": {} } + }, + "/auth/comment/cancel_like": { + "post": { + "description": "取消点赞评论", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "评论" + ], + "summary": "取消点赞评论", + "parameters": [ + { + "description": "取消点赞请求", + "name": "comment_like_request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/comment_api.CommentLikeRequest" + } + } + ], + "responses": {} + } + }, + "/auth/comment/like": { + "post": { + "description": "点赞评论", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "评论" + ], + "summary": "点赞评论", + "parameters": [ + { + "description": "点赞请求", + "name": "comment_like_request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/comment_api.CommentLikeRequest" + } + } + ], + "responses": {} + } + }, + "/auth/comment/list": { + "post": { + "description": "获取评论列表", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "评论" + ], + "summary": "获取评论列表", + "parameters": [ + { + "description": "评论列表请求", + "name": "comment_list_request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/comment_api.CommentListRequest" + } + } + ], + "responses": {} + } + }, + "/auth/comment/submit": { + "post": { + "description": "提交评论", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "评论" + ], + "summary": "提交评论", + "parameters": [ + { + "description": "评论请求", + "name": "comment_request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/comment_api.CommentRequest" + } + } + ], + "responses": {} + } + }, + "/auth/reply/list": { + "post": { + "description": "获取回复列表", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "评论" + ], + "summary": "获取回复列表", + "parameters": [ + { + "description": "回复列表请求", + "name": "reply_list_request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/comment_api.ReplyListRequest" + } + } + ], + "responses": {} + } + }, + "/auth/reply/reply/submit": { + "post": { + "description": "提交回复的回复", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "评论" + ], + "summary": "提交回复的回复", + "parameters": [ + { + "description": "回复回复请求", + "name": "reply_reply_request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/comment_api.ReplyReplyRequest" + } + } + ], + "responses": {} + } + }, + "/auth/reply/submit": { + "post": { + "description": "提交回复", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "评论" + ], + "summary": "提交回复", + "parameters": [ + { + "description": "回复评论请求", + "name": "reply_comment_request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/comment_api.ReplyCommentRequest" + } + } + ], + "responses": {} + } } }, "definitions": { - "dto.AccountLoginRequest": { + "comment_api.CommentLikeRequest": { "type": "object", + "required": [ + "comment_id", + "topic_id", + "user_id" + ], "properties": { - "account": { + "comment_id": { + "type": "integer" + }, + "topic_id": { "type": "string" }, - "auto_login": { - "type": "boolean" - }, - "password": { + "user_id": { "type": "string" } } }, - "dto.AddPermissionRequestDto": { + "comment_api.CommentListRequest": { "type": "object", + "required": [ + "topic_id", + "user_id" + ], "properties": { - "permissions": { - "type": "array", - "items": { - "$ref": "#/definitions/model.ScaAuthPermission" - } - } - } - }, - "dto.AddPermissionToRoleRequestDto": { - "type": "object", - "properties": { - "method": { + "is_hot": { + "type": "boolean", + "default": true + }, + "page": { + "type": "integer", + "default": 1 + }, + "size": { + "type": "integer", + "default": 5 + }, + "topic_id": { "type": "string" }, - "permission": { - "type": "string" - }, - "role_key": { + "user_id": { "type": "string" } } }, - "dto.AddRoleToUserRequestDto": { + "comment_api.CommentRequest": { "type": "object", + "required": [ + "author", + "content", + "key", + "point", + "topic_id", + "user_id" + ], "properties": { - "role_key": { + "author": { "type": "string" }, - "uid": { - "type": "string" - } - } - }, - "dto.CommentRequest": { - "type": "object", - "properties": { "content": { "type": "string" }, @@ -924,6 +1066,15 @@ const docTemplate = `{ "type": "string" } }, + "key": { + "type": "string" + }, + "point": { + "type": "array", + "items": { + "type": "integer" + } + }, "topic_id": { "type": "string" }, @@ -932,23 +1083,22 @@ const docTemplate = `{ } } }, - "dto.PhoneLoginRequest": { + "comment_api.ReplyCommentRequest": { "type": "object", + "required": [ + "author", + "content", + "key", + "point", + "reply_id", + "reply_user", + "topic_id", + "user_id" + ], "properties": { - "auto_login": { - "type": "boolean" - }, - "captcha": { + "author": { "type": "string" }, - "phone": { - "type": "string" - } - } - }, - "dto.ReplyCommentRequest": { - "type": "object", - "properties": { "content": { "type": "string" }, @@ -958,9 +1108,18 @@ const docTemplate = `{ "type": "string" } }, - "reply_id": { + "key": { "type": "string" }, + "point": { + "type": "array", + "items": { + "type": "integer" + } + }, + "reply_id": { + "type": "integer" + }, "reply_user": { "type": "string" }, @@ -972,30 +1131,81 @@ const docTemplate = `{ } } }, - "dto.ResetPasswordRequest": { + "comment_api.ReplyListRequest": { "type": "object", + "required": [ + "comment_id", + "topic_id", + "user_id" + ], "properties": { - "captcha": { + "comment_id": { + "type": "integer" + }, + "page": { + "type": "integer", + "default": 1 + }, + "size": { + "type": "integer", + "default": 5 + }, + "topic_id": { "type": "string" }, - "password": { - "type": "string" - }, - "phone": { - "type": "string" - }, - "repassword": { + "user_id": { "type": "string" } } }, - "dto.RoleRequestDto": { + "comment_api.ReplyReplyRequest": { "type": "object", + "required": [ + "author", + "content", + "key", + "point", + "reply_id", + "reply_to", + "reply_user", + "topic_id", + "user_id" + ], "properties": { - "role_key": { + "author": { "type": "string" }, - "role_name": { + "content": { + "type": "string" + }, + "images": { + "type": "array", + "items": { + "type": "string" + } + }, + "key": { + "type": "string" + }, + "point": { + "type": "array", + "items": { + "type": "integer" + } + }, + "reply_id": { + "type": "integer" + }, + "reply_to": { + "type": "integer" + }, + "reply_user": { + "type": "string" + }, + "topic_id": { + "type": "string" + }, + "user_id": { "type": "string" } } @@ -1067,6 +1277,130 @@ const docTemplate = `{ "type": "string" } } + }, + "permission_api.AddPermissionRequest": { + "type": "object", + "properties": { + "permissions": { + "type": "array", + "items": { + "$ref": "#/definitions/model.ScaAuthPermission" + } + } + } + }, + "permission_api.AddPermissionToRoleRequest": { + "type": "object", + "properties": { + "method": { + "type": "string" + }, + "permission": { + "type": "string" + }, + "role_key": { + "type": "string" + } + } + }, + "role_api.AddRoleToUserRequest": { + "type": "object", + "required": [ + "role_key", + "uid" + ], + "properties": { + "role_key": { + "type": "string" + }, + "uid": { + "type": "string" + } + } + }, + "role_api.RoleRequest": { + "type": "object", + "required": [ + "role_key", + "role_name" + ], + "properties": { + "role_key": { + "type": "string" + }, + "role_name": { + "type": "string" + } + } + }, + "user_api.AccountLoginRequest": { + "type": "object", + "required": [ + "account", + "angle", + "auto_login", + "key", + "password" + ], + "properties": { + "account": { + "type": "string" + }, + "angle": { + "type": "integer" + }, + "auto_login": { + "type": "boolean" + }, + "key": { + "type": "string" + }, + "password": { + "type": "string" + } + } + }, + "user_api.PhoneLoginRequest": { + "type": "object", + "required": [ + "auto_login", + "captcha", + "phone" + ], + "properties": { + "auto_login": { + "type": "boolean" + }, + "captcha": { + "type": "string" + }, + "phone": { + "type": "string" + } + } + }, + "user_api.ResetPasswordRequest": { + "type": "object", + "required": [ + "captcha", + "password", + "phone", + "repassword" + ], + "properties": { + "captcha": { + "type": "string" + }, + "password": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "repassword": { + "type": "string" + } + } } } }` diff --git a/docs/swagger.json b/docs/swagger.json index 1e315bb..1e9edbb 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -24,7 +24,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.AddPermissionRequestDto" + "$ref": "#/definitions/permission_api.AddPermissionRequest" } } ], @@ -51,7 +51,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.AddPermissionToRoleRequestDto" + "$ref": "#/definitions/permission_api.AddPermissionToRoleRequest" } } ], @@ -78,7 +78,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.AddRoleToUserRequestDto" + "$ref": "#/definitions/role_api.AddRoleToUserRequest" } } ], @@ -105,7 +105,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.RoleRequestDto" + "$ref": "#/definitions/role_api.RoleRequest" } } ], @@ -294,23 +294,6 @@ } } }, - "/api/captcha/shape/check": { - "get": { - "description": "生成点击形状基础验证码", - "tags": [ - "点击形状验证码" - ], - "summary": "生成点击形状基础验证码", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, "/api/captcha/shape/get": { "get": { "description": "生成点击形状验证码", @@ -330,11 +313,11 @@ }, "/api/captcha/shape/slide/check": { "get": { - "description": "验证点击形状验证码", + "description": "验证滑动验证码", "tags": [ - "点击形状验证码" + "验证滑动验证码" ], - "summary": "验证点击形状验证码", + "summary": "验证滑动验证码", "parameters": [ { "type": "string", @@ -363,11 +346,28 @@ }, "/api/captcha/shape/slide/region/get": { "get": { - "description": "生成点击形状验证码", + "description": "生成滑动区域形状验证码", "tags": [ - "点击形状验证码" + "生成滑动区域形状验证码" ], - "summary": "生成点击形状验证码", + "summary": "生成滑动区域形状验证码", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/captcha/slide/generate": { + "get": { + "description": "滑块基础验证码", + "tags": [ + "滑块基础验证码" + ], + "summary": "滑块基础验证码", "responses": { "200": { "description": "OK", @@ -437,60 +437,6 @@ } } }, - "/api/comment/reply": { - "post": { - "description": "提交回复", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "评论" - ], - "summary": "提交回复", - "parameters": [ - { - "description": "回复评论请求", - "name": "reply_comment_request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.ReplyCommentRequest" - } - } - ], - "responses": {} - } - }, - "/api/comment/submit": { - "post": { - "description": "提交评论", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "评论" - ], - "summary": "提交评论", - "parameters": [ - { - "description": "评论请求", - "name": "comment_request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.CommentRequest" - } - } - ], - "responses": {} - } - }, "/api/oauth/callback_notify": { "post": { "description": "微信回调", @@ -690,7 +636,7 @@ } }, "/api/sms/smsbao/send": { - "get": { + "post": { "description": "短信宝发送短信验证码", "produces": [ "application/json" @@ -712,7 +658,7 @@ } }, "/api/sms/test/send": { - "get": { + "post": { "description": "发送测试短信验证码", "produces": [ "application/json" @@ -771,7 +717,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.AccountLoginRequest" + "$ref": "#/definitions/user_api.AccountLoginRequest" } } ], @@ -798,7 +744,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.PhoneLoginRequest" + "$ref": "#/definitions/user_api.PhoneLoginRequest" } } ], @@ -825,7 +771,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.ResetPasswordRequest" + "$ref": "#/definitions/user_api.ResetPasswordRequest" } } ], @@ -848,62 +794,258 @@ "summary": "创建websocket服务", "responses": {} } + }, + "/auth/comment/cancel_like": { + "post": { + "description": "取消点赞评论", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "评论" + ], + "summary": "取消点赞评论", + "parameters": [ + { + "description": "取消点赞请求", + "name": "comment_like_request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/comment_api.CommentLikeRequest" + } + } + ], + "responses": {} + } + }, + "/auth/comment/like": { + "post": { + "description": "点赞评论", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "评论" + ], + "summary": "点赞评论", + "parameters": [ + { + "description": "点赞请求", + "name": "comment_like_request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/comment_api.CommentLikeRequest" + } + } + ], + "responses": {} + } + }, + "/auth/comment/list": { + "post": { + "description": "获取评论列表", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "评论" + ], + "summary": "获取评论列表", + "parameters": [ + { + "description": "评论列表请求", + "name": "comment_list_request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/comment_api.CommentListRequest" + } + } + ], + "responses": {} + } + }, + "/auth/comment/submit": { + "post": { + "description": "提交评论", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "评论" + ], + "summary": "提交评论", + "parameters": [ + { + "description": "评论请求", + "name": "comment_request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/comment_api.CommentRequest" + } + } + ], + "responses": {} + } + }, + "/auth/reply/list": { + "post": { + "description": "获取回复列表", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "评论" + ], + "summary": "获取回复列表", + "parameters": [ + { + "description": "回复列表请求", + "name": "reply_list_request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/comment_api.ReplyListRequest" + } + } + ], + "responses": {} + } + }, + "/auth/reply/reply/submit": { + "post": { + "description": "提交回复的回复", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "评论" + ], + "summary": "提交回复的回复", + "parameters": [ + { + "description": "回复回复请求", + "name": "reply_reply_request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/comment_api.ReplyReplyRequest" + } + } + ], + "responses": {} + } + }, + "/auth/reply/submit": { + "post": { + "description": "提交回复", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "评论" + ], + "summary": "提交回复", + "parameters": [ + { + "description": "回复评论请求", + "name": "reply_comment_request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/comment_api.ReplyCommentRequest" + } + } + ], + "responses": {} + } } }, "definitions": { - "dto.AccountLoginRequest": { + "comment_api.CommentLikeRequest": { "type": "object", + "required": [ + "comment_id", + "topic_id", + "user_id" + ], "properties": { - "account": { + "comment_id": { + "type": "integer" + }, + "topic_id": { "type": "string" }, - "auto_login": { - "type": "boolean" - }, - "password": { + "user_id": { "type": "string" } } }, - "dto.AddPermissionRequestDto": { + "comment_api.CommentListRequest": { "type": "object", + "required": [ + "topic_id", + "user_id" + ], "properties": { - "permissions": { - "type": "array", - "items": { - "$ref": "#/definitions/model.ScaAuthPermission" - } - } - } - }, - "dto.AddPermissionToRoleRequestDto": { - "type": "object", - "properties": { - "method": { + "is_hot": { + "type": "boolean", + "default": true + }, + "page": { + "type": "integer", + "default": 1 + }, + "size": { + "type": "integer", + "default": 5 + }, + "topic_id": { "type": "string" }, - "permission": { - "type": "string" - }, - "role_key": { + "user_id": { "type": "string" } } }, - "dto.AddRoleToUserRequestDto": { + "comment_api.CommentRequest": { "type": "object", + "required": [ + "author", + "content", + "key", + "point", + "topic_id", + "user_id" + ], "properties": { - "role_key": { + "author": { "type": "string" }, - "uid": { - "type": "string" - } - } - }, - "dto.CommentRequest": { - "type": "object", - "properties": { "content": { "type": "string" }, @@ -913,6 +1055,15 @@ "type": "string" } }, + "key": { + "type": "string" + }, + "point": { + "type": "array", + "items": { + "type": "integer" + } + }, "topic_id": { "type": "string" }, @@ -921,23 +1072,22 @@ } } }, - "dto.PhoneLoginRequest": { + "comment_api.ReplyCommentRequest": { "type": "object", + "required": [ + "author", + "content", + "key", + "point", + "reply_id", + "reply_user", + "topic_id", + "user_id" + ], "properties": { - "auto_login": { - "type": "boolean" - }, - "captcha": { + "author": { "type": "string" }, - "phone": { - "type": "string" - } - } - }, - "dto.ReplyCommentRequest": { - "type": "object", - "properties": { "content": { "type": "string" }, @@ -947,9 +1097,18 @@ "type": "string" } }, - "reply_id": { + "key": { "type": "string" }, + "point": { + "type": "array", + "items": { + "type": "integer" + } + }, + "reply_id": { + "type": "integer" + }, "reply_user": { "type": "string" }, @@ -961,30 +1120,81 @@ } } }, - "dto.ResetPasswordRequest": { + "comment_api.ReplyListRequest": { "type": "object", + "required": [ + "comment_id", + "topic_id", + "user_id" + ], "properties": { - "captcha": { + "comment_id": { + "type": "integer" + }, + "page": { + "type": "integer", + "default": 1 + }, + "size": { + "type": "integer", + "default": 5 + }, + "topic_id": { "type": "string" }, - "password": { - "type": "string" - }, - "phone": { - "type": "string" - }, - "repassword": { + "user_id": { "type": "string" } } }, - "dto.RoleRequestDto": { + "comment_api.ReplyReplyRequest": { "type": "object", + "required": [ + "author", + "content", + "key", + "point", + "reply_id", + "reply_to", + "reply_user", + "topic_id", + "user_id" + ], "properties": { - "role_key": { + "author": { "type": "string" }, - "role_name": { + "content": { + "type": "string" + }, + "images": { + "type": "array", + "items": { + "type": "string" + } + }, + "key": { + "type": "string" + }, + "point": { + "type": "array", + "items": { + "type": "integer" + } + }, + "reply_id": { + "type": "integer" + }, + "reply_to": { + "type": "integer" + }, + "reply_user": { + "type": "string" + }, + "topic_id": { + "type": "string" + }, + "user_id": { "type": "string" } } @@ -1056,6 +1266,130 @@ "type": "string" } } + }, + "permission_api.AddPermissionRequest": { + "type": "object", + "properties": { + "permissions": { + "type": "array", + "items": { + "$ref": "#/definitions/model.ScaAuthPermission" + } + } + } + }, + "permission_api.AddPermissionToRoleRequest": { + "type": "object", + "properties": { + "method": { + "type": "string" + }, + "permission": { + "type": "string" + }, + "role_key": { + "type": "string" + } + } + }, + "role_api.AddRoleToUserRequest": { + "type": "object", + "required": [ + "role_key", + "uid" + ], + "properties": { + "role_key": { + "type": "string" + }, + "uid": { + "type": "string" + } + } + }, + "role_api.RoleRequest": { + "type": "object", + "required": [ + "role_key", + "role_name" + ], + "properties": { + "role_key": { + "type": "string" + }, + "role_name": { + "type": "string" + } + } + }, + "user_api.AccountLoginRequest": { + "type": "object", + "required": [ + "account", + "angle", + "auto_login", + "key", + "password" + ], + "properties": { + "account": { + "type": "string" + }, + "angle": { + "type": "integer" + }, + "auto_login": { + "type": "boolean" + }, + "key": { + "type": "string" + }, + "password": { + "type": "string" + } + } + }, + "user_api.PhoneLoginRequest": { + "type": "object", + "required": [ + "auto_login", + "captcha", + "phone" + ], + "properties": { + "auto_login": { + "type": "boolean" + }, + "captcha": { + "type": "string" + }, + "phone": { + "type": "string" + } + } + }, + "user_api.ResetPasswordRequest": { + "type": "object", + "required": [ + "captcha", + "password", + "phone", + "repassword" + ], + "properties": { + "captcha": { + "type": "string" + }, + "password": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "repassword": { + "type": "string" + } + } } } } \ No newline at end of file diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 5c113c5..9ae7dc4 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -1,92 +1,153 @@ definitions: - dto.AccountLoginRequest: + comment_api.CommentLikeRequest: properties: - account: + comment_id: + type: integer + topic_id: type: string - auto_login: + user_id: + type: string + required: + - comment_id + - topic_id + - user_id + type: object + comment_api.CommentListRequest: + properties: + is_hot: + default: true type: boolean - password: + page: + default: 1 + type: integer + size: + default: 5 + type: integer + topic_id: type: string + user_id: + type: string + required: + - topic_id + - user_id type: object - dto.AddPermissionRequestDto: + comment_api.CommentRequest: properties: - permissions: - items: - $ref: '#/definitions/model.ScaAuthPermission' - type: array - type: object - dto.AddPermissionToRoleRequestDto: - properties: - method: + author: type: string - permission: - type: string - role_key: - type: string - type: object - dto.AddRoleToUserRequestDto: - properties: - role_key: - type: string - uid: - type: string - type: object - dto.CommentRequest: - properties: content: type: string images: items: type: string type: array + key: + type: string + point: + items: + type: integer + type: array topic_id: type: string user_id: type: string + required: + - author + - content + - key + - point + - topic_id + - user_id type: object - dto.PhoneLoginRequest: + comment_api.ReplyCommentRequest: properties: - auto_login: - type: boolean - captcha: + author: type: string - phone: - type: string - type: object - dto.ReplyCommentRequest: - properties: content: type: string images: items: type: string type: array - reply_id: + key: type: string + point: + items: + type: integer + type: array + reply_id: + type: integer reply_user: type: string topic_id: type: string user_id: type: string + required: + - author + - content + - key + - point + - reply_id + - reply_user + - topic_id + - user_id type: object - dto.ResetPasswordRequest: + comment_api.ReplyListRequest: properties: - captcha: + comment_id: + type: integer + page: + default: 1 + type: integer + size: + default: 5 + type: integer + topic_id: type: string - password: - type: string - phone: - type: string - repassword: + user_id: type: string + required: + - comment_id + - topic_id + - user_id type: object - dto.RoleRequestDto: + comment_api.ReplyReplyRequest: properties: - role_key: + author: type: string - role_name: + content: type: string + images: + items: + type: string + type: array + key: + type: string + point: + items: + type: integer + type: array + reply_id: + type: integer + reply_to: + type: integer + reply_user: + type: string + topic_id: + type: string + user_id: + type: string + required: + - author + - content + - key + - point + - reply_id + - reply_to + - reply_user + - topic_id + - user_id type: object model.ScaAuthPermission: properties: @@ -138,6 +199,90 @@ definitions: description: 更新时间 type: string type: object + permission_api.AddPermissionRequest: + properties: + permissions: + items: + $ref: '#/definitions/model.ScaAuthPermission' + type: array + type: object + permission_api.AddPermissionToRoleRequest: + properties: + method: + type: string + permission: + type: string + role_key: + type: string + type: object + role_api.AddRoleToUserRequest: + properties: + role_key: + type: string + uid: + type: string + required: + - role_key + - uid + type: object + role_api.RoleRequest: + properties: + role_key: + type: string + role_name: + type: string + required: + - role_key + - role_name + type: object + user_api.AccountLoginRequest: + properties: + account: + type: string + angle: + type: integer + auto_login: + type: boolean + key: + type: string + password: + type: string + required: + - account + - angle + - auto_login + - key + - password + type: object + user_api.PhoneLoginRequest: + properties: + auto_login: + type: boolean + captcha: + type: string + phone: + type: string + required: + - auto_login + - captcha + - phone + type: object + user_api.ResetPasswordRequest: + properties: + captcha: + type: string + password: + type: string + phone: + type: string + repassword: + type: string + required: + - captcha + - password + - phone + - repassword + type: object info: contact: {} paths: @@ -152,7 +297,7 @@ paths: name: permissions required: true schema: - $ref: '#/definitions/dto.AddPermissionRequestDto' + $ref: '#/definitions/permission_api.AddPermissionRequest' produces: - application/json responses: {} @@ -170,7 +315,7 @@ paths: name: permissions required: true schema: - $ref: '#/definitions/dto.AddPermissionToRoleRequestDto' + $ref: '#/definitions/permission_api.AddPermissionToRoleRequest' produces: - application/json responses: {} @@ -188,7 +333,7 @@ paths: name: addRoleToUserRequestDto required: true schema: - $ref: '#/definitions/dto.AddRoleToUserRequestDto' + $ref: '#/definitions/role_api.AddRoleToUserRequest' produces: - application/json responses: {} @@ -206,7 +351,7 @@ paths: name: roleRequestDto required: true schema: - $ref: '#/definitions/dto.RoleRequestDto' + $ref: '#/definitions/role_api.RoleRequest' produces: - application/json responses: {} @@ -330,17 +475,6 @@ paths: summary: 生成旋转验证码 tags: - 旋转验证码 - /api/captcha/shape/check: - get: - description: 生成点击形状基础验证码 - responses: - "200": - description: OK - schema: - type: string - summary: 生成点击形状基础验证码 - tags: - - 点击形状验证码 /api/captcha/shape/get: get: description: 生成点击形状验证码 @@ -354,7 +488,7 @@ paths: - 点击形状验证码 /api/captcha/shape/slide/check: get: - description: 验证点击形状验证码 + description: 验证滑动验证码 parameters: - description: 点击坐标 in: query @@ -371,20 +505,31 @@ paths: description: OK schema: type: string - summary: 验证点击形状验证码 + summary: 验证滑动验证码 tags: - - 点击形状验证码 + - 验证滑动验证码 /api/captcha/shape/slide/region/get: get: - description: 生成点击形状验证码 + description: 生成滑动区域形状验证码 responses: "200": description: OK schema: type: string - summary: 生成点击形状验证码 + summary: 生成滑动区域形状验证码 tags: - - 点击形状验证码 + - 生成滑动区域形状验证码 + /api/captcha/slide/generate: + get: + description: 滑块基础验证码 + responses: + "200": + description: OK + schema: + type: string + summary: 滑块基础验证码 + tags: + - 滑块基础验证码 /api/captcha/text/check: get: description: 验证基础文字验证码 @@ -424,42 +569,6 @@ paths: summary: 生成基础文字验证码 tags: - 基础文字验证码 - /api/comment/reply: - post: - consumes: - - application/json - description: 提交回复 - parameters: - - description: 回复评论请求 - in: body - name: reply_comment_request - required: true - schema: - $ref: '#/definitions/dto.ReplyCommentRequest' - produces: - - application/json - responses: {} - summary: 提交回复 - tags: - - 评论 - /api/comment/submit: - post: - consumes: - - application/json - description: 提交评论 - parameters: - - description: 评论请求 - in: body - name: comment_request - required: true - schema: - $ref: '#/definitions/dto.CommentRequest' - produces: - - application/json - responses: {} - summary: 提交评论 - tags: - - 评论 /api/oauth/callback_notify: post: description: 微信回调 @@ -594,7 +703,7 @@ paths: tags: - 短信验证码 /api/sms/smsbao/send: - get: + post: description: 短信宝发送短信验证码 parameters: - description: 手机号 @@ -609,7 +718,7 @@ paths: tags: - 短信验证码 /api/sms/test/send: - get: + post: description: 发送测试短信验证码 parameters: - description: 手机号 @@ -647,7 +756,7 @@ paths: name: user required: true schema: - $ref: '#/definitions/dto.AccountLoginRequest' + $ref: '#/definitions/user_api.AccountLoginRequest' responses: "200": description: OK @@ -664,7 +773,7 @@ paths: name: user required: true schema: - $ref: '#/definitions/dto.PhoneLoginRequest' + $ref: '#/definitions/user_api.PhoneLoginRequest' responses: "200": description: OK @@ -681,7 +790,7 @@ paths: name: user required: true schema: - $ref: '#/definitions/dto.ResetPasswordRequest' + $ref: '#/definitions/user_api.ResetPasswordRequest' responses: "200": description: OK @@ -697,4 +806,130 @@ paths: summary: 创建websocket服务 tags: - websocket + /auth/comment/cancel_like: + post: + consumes: + - application/json + description: 取消点赞评论 + parameters: + - description: 取消点赞请求 + in: body + name: comment_like_request + required: true + schema: + $ref: '#/definitions/comment_api.CommentLikeRequest' + produces: + - application/json + responses: {} + summary: 取消点赞评论 + tags: + - 评论 + /auth/comment/like: + post: + consumes: + - application/json + description: 点赞评论 + parameters: + - description: 点赞请求 + in: body + name: comment_like_request + required: true + schema: + $ref: '#/definitions/comment_api.CommentLikeRequest' + produces: + - application/json + responses: {} + summary: 点赞评论 + tags: + - 评论 + /auth/comment/list: + post: + consumes: + - application/json + description: 获取评论列表 + parameters: + - description: 评论列表请求 + in: body + name: comment_list_request + required: true + schema: + $ref: '#/definitions/comment_api.CommentListRequest' + produces: + - application/json + responses: {} + summary: 获取评论列表 + tags: + - 评论 + /auth/comment/submit: + post: + consumes: + - application/json + description: 提交评论 + parameters: + - description: 评论请求 + in: body + name: comment_request + required: true + schema: + $ref: '#/definitions/comment_api.CommentRequest' + produces: + - application/json + responses: {} + summary: 提交评论 + tags: + - 评论 + /auth/reply/list: + post: + consumes: + - application/json + description: 获取回复列表 + parameters: + - description: 回复列表请求 + in: body + name: reply_list_request + required: true + schema: + $ref: '#/definitions/comment_api.ReplyListRequest' + produces: + - application/json + responses: {} + summary: 获取回复列表 + tags: + - 评论 + /auth/reply/reply/submit: + post: + consumes: + - application/json + description: 提交回复的回复 + parameters: + - description: 回复回复请求 + in: body + name: reply_reply_request + required: true + schema: + $ref: '#/definitions/comment_api.ReplyReplyRequest' + produces: + - application/json + responses: {} + summary: 提交回复的回复 + tags: + - 评论 + /auth/reply/submit: + post: + consumes: + - application/json + description: 提交回复 + parameters: + - description: 回复评论请求 + in: body + name: reply_comment_request + required: true + schema: + $ref: '#/definitions/comment_api.ReplyCommentRequest' + produces: + - application/json + responses: {} + summary: 提交回复 + tags: + - 评论 swagger: "2.0" diff --git a/go.mod b/go.mod index d09814b..dc7414b 100644 --- a/go.mod +++ b/go.mod @@ -94,6 +94,7 @@ require ( github.com/montanaflynn/stats v0.7.1 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect github.com/nicksnyder/go-i18n/v2 v2.4.0 // indirect + github.com/nsqio/go-nsq v1.1.0 // indirect github.com/patrickmn/go-cache v2.1.0+incompatible // indirect github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/pkg/errors v0.9.1 // indirect diff --git a/go.sum b/go.sum index baba9ca..c4bf4ad 100644 --- a/go.sum +++ b/go.sum @@ -127,6 +127,7 @@ github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF0 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= @@ -216,6 +217,8 @@ github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdh github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/nicksnyder/go-i18n/v2 v2.4.0 h1:3IcvPOAvnCKwNm0TB0dLDTuawWEj+ax/RERNC+diLMM= github.com/nicksnyder/go-i18n/v2 v2.4.0/go.mod h1:nxYSZE9M0bf3Y70gPQjN9ha7XNHX7gMc814+6wVyEI4= +github.com/nsqio/go-nsq v1.1.0 h1:PQg+xxiUjA7V+TLdXw7nVrJ5Jbl3sN86EhGCQj4+FYE= +github.com/nsqio/go-nsq v1.1.0/go.mod h1:vKq36oyeVXgsS5Q8YEO7WghqidAVXQlcFxzQbQTuDEY= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= diff --git a/middleware/i18n.go b/middleware/i18n.go index a6de233..d5f0a5d 100644 --- a/middleware/i18n.go +++ b/middleware/i18n.go @@ -10,7 +10,7 @@ import ( func I18n() gin.HandlerFunc { return ginI18n.Localize( ginI18n.WithBundle(&ginI18n.BundleCfg{ - RootPath: "i18n/language/", + RootPath: "resource/language/", AcceptLanguage: []language.Tag{language.Chinese, language.English}, DefaultLanguage: language.Chinese, UnmarshalFunc: toml.Unmarshal, diff --git a/ip2region/ip2region.xdb b/resource/ip2region/ip2region.xdb similarity index 100% rename from ip2region/ip2region.xdb rename to resource/ip2region/ip2region.xdb diff --git a/i18n/language/en.toml b/resource/language/en.toml similarity index 100% rename from i18n/language/en.toml rename to resource/language/en.toml diff --git a/i18n/language/zh.toml b/resource/language/zh.toml similarity index 100% rename from i18n/language/zh.toml rename to resource/language/zh.toml diff --git a/utils/session.go b/utils/session.go index f5aac09..70855c2 100644 --- a/utils/session.go +++ b/utils/session.go @@ -3,7 +3,6 @@ package utils import ( "encoding/json" "github.com/gin-gonic/gin" - "schisandra-cloud-album/api/user_api/dto" "schisandra-cloud-album/global" ) @@ -29,22 +28,22 @@ func SetSession(c *gin.Context, key string, data interface{}) error { } // GetSession gets session data with key -func GetSession(c *gin.Context, key string) dto.ResponseData { +func GetSession(c *gin.Context, key string) interface{} { session, err := global.Session.Get(c.Request, key) if err != nil { global.LOG.Error("GetSession failed: ", err) - return dto.ResponseData{} + return nil } jsonData, ok := session.Values[key] if !ok { global.LOG.Error("GetSession failed: ", "key not found") - return dto.ResponseData{} + return nil } - var data dto.ResponseData + var data interface{} err = json.Unmarshal(jsonData.([]byte), &data) if err != nil { global.LOG.Error("GetSession failed: ", err) - return dto.ResponseData{} + return nil } return data }