From 933093582228bd286e8dd5cf8a1c4c35cf37ec9c Mon Sep 17 00:00:00 2001 From: landaiqing <3517283258@qq.com> Date: Sat, 24 Aug 2024 16:31:40 +0800 Subject: [PATCH] :zap: update qq/gitee/github oauth2 login --- api/api.go | 14 +- api/oauth_api/gitee_api.go | 178 +++++++------- api/oauth_api/github_api.go | 197 ++++++++-------- api/oauth_api/oauth.go | 111 +++++---- api/oauth_api/qq_api.go | 99 +++++--- api/oauth_api/wechat_api.go | 218 ++++++++++-------- api/permission_api/dto/request_dto.go | 11 + api/permission_api/permission.go | 3 + api/permission_api/permission_api.go | 36 +++ api/role_api/dto/request_dto.go | 11 + api/role_api/role_api.go | 63 +++++ api/user_api/user_api.go | 99 +++----- cmd/db/db.go | 2 - common/enum/role.go | 6 +- config/conf_casbin.go | 10 + config/conf_logger.go | 10 +- config/conf_system.go | 1 + config/config.go | 1 + core/captcha.go | 19 +- core/casbin.go | 15 +- core/gorm.go | 11 +- core/logrus.go | 80 +------ core/wechat.go | 9 +- docs/docs.go | 76 ++++++ docs/swagger.json | 76 ++++++ docs/swagger.yaml | 50 ++++ go.mod | 8 +- go.sum | 22 +- main.go | 1 + middleware/logger_date.go | 157 +++++++++++++ middleware/logger_level.go | 116 ++++++++++ model/sca_auth_role_permission.go | 24 -- model/sca_auth_user_role.go | 24 -- model/sca_auth_user_social.go | 2 +- router/modules/oauth_router.go | 4 +- router/modules/role_router.go | 16 ++ router/router.go | 12 +- .../permission_service/permission_service.go | 8 + .../role_permission.go | 3 - .../role_permission_service.go | 17 -- service/role_service/role_service.go | 8 + service/service.go | 12 +- service/user_role_service/user_role.go | 3 - .../user_role_service/user_role_service.go | 32 --- utils/jwt.go | 10 +- 45 files changed, 1243 insertions(+), 642 deletions(-) create mode 100644 api/permission_api/dto/request_dto.go create mode 100644 api/permission_api/permission.go create mode 100644 api/permission_api/permission_api.go create mode 100644 api/role_api/dto/request_dto.go create mode 100644 config/conf_casbin.go create mode 100644 middleware/logger_date.go create mode 100644 middleware/logger_level.go delete mode 100644 model/sca_auth_role_permission.go delete mode 100644 model/sca_auth_user_role.go create mode 100644 router/modules/role_router.go delete mode 100644 service/role_permission_service/role_permission.go delete mode 100644 service/role_permission_service/role_permission_service.go delete mode 100644 service/user_role_service/user_role.go delete mode 100644 service/user_role_service/user_role_service.go diff --git a/api/api.go b/api/api.go index 846fa99..1ea784e 100644 --- a/api/api.go +++ b/api/api.go @@ -3,6 +3,8 @@ package api import ( "schisandra-cloud-album/api/captcha_api" "schisandra-cloud-album/api/oauth_api" + "schisandra-cloud-album/api/permission_api" + "schisandra-cloud-album/api/role_api" "schisandra-cloud-album/api/sms_api" "schisandra-cloud-album/api/user_api" "schisandra-cloud-album/api/websocket_api" @@ -10,11 +12,13 @@ import ( // Apis 统一导出的api type Apis struct { - UserApi user_api.UserAPI - CaptchaApi captcha_api.CaptchaAPI - SmsApi sms_api.SmsAPI - OAuthApi oauth_api.OAuthAPI - WebsocketApi websocket_api.WebsocketAPI + UserApi user_api.UserAPI + CaptchaApi captcha_api.CaptchaAPI + SmsApi sms_api.SmsAPI + OAuthApi oauth_api.OAuthAPI + WebsocketApi websocket_api.WebsocketAPI + RoleApi role_api.RoleAPI + PermissionApi permission_api.PermissionAPI } // Api new函数实例化,实例化完成后会返回结构体地指针类型 diff --git a/api/oauth_api/gitee_api.go b/api/oauth_api/gitee_api.go index 9a4fafd..3e05123 100644 --- a/api/oauth_api/gitee_api.go +++ b/api/oauth_api/gitee_api.go @@ -142,100 +142,112 @@ func (OAuthAPI) GiteeCallback(c *gin.Context) { result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) return } - // 通过 code, 获取 token - var tokenAuthUrl = GetGiteeTokenAuthUrl(code) - var token *Token - if token, err = GetGiteeToken(tokenAuthUrl); err != nil { - global.LOG.Error(err) - return - } - // 通过token,获取用户信息 - var userInfo map[string]interface{} - if userInfo, err = GetGiteeUserInfo(token); err != nil { - global.LOG.Error(err) - return - } + // 异步获取 token + var tokenChan = make(chan *Token) + var errChan = make(chan error) + go func() { + var tokenAuthUrl = GetGiteeTokenAuthUrl(code) + token, err := GetGiteeToken(tokenAuthUrl) + if err != nil { + errChan <- err + return + } + tokenChan <- token + }() - userInfoBytes, err := json.Marshal(userInfo) - if err != nil { - global.LOG.Error(err) - return - } - var giteeUser GiteeUser - err = json.Unmarshal(userInfoBytes, &giteeUser) - if err != nil { - global.LOG.Error(err) - return - } + // 异步获取用户信息 + var userInfoChan = make(chan map[string]interface{}) + go func() { + token := <-tokenChan + if token == nil { + errChan <- errors.New("failed to get token") + return + } + userInfo, err := GetGiteeUserInfo(token) + if err != nil { + errChan <- err + return + } + userInfoChan <- userInfo + }() - Id := strconv.Itoa(giteeUser.ID) - userSocial, err := userSocialService.QueryUserSocialByUUID(Id, enum.OAuthSourceGitee) - if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { - // 第一次登录,创建用户 - uid := idgen.NextId() - uidStr := strconv.FormatInt(uid, 10) - user := model.ScaAuthUser{ - UID: &uidStr, - Username: &giteeUser.Login, - Nickname: &giteeUser.Name, - Avatar: &giteeUser.AvatarURL, - Blog: &giteeUser.Blog, - Email: &giteeUser.Email, - } - addUser, err := userService.AddUser(user) + // 等待结果 + select { + case err = <-errChan: + global.LOG.Error(err) + return + case userInfo := <-userInfoChan: + userInfoBytes, err := json.Marshal(userInfo) if err != nil { global.LOG.Error(err) return } - gitee := enum.OAuthSourceGitee - userSocial = model.ScaAuthUserSocial{ - UserID: &addUser.ID, - UUID: &Id, - Source: &gitee, - } - err = userSocialService.AddUserSocial(userSocial) + var giteeUser GiteeUser + err = json.Unmarshal(userInfoBytes, &giteeUser) if err != nil { global.LOG.Error(err) return } - userRole := model.ScaAuthUserRole{ - UserID: uidStr, - RoleID: enum.User, + + Id := strconv.Itoa(giteeUser.ID) + userSocial, err := userSocialService.QueryUserSocialByUUID(Id, enum.OAuthSourceGitee) + if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { + db := global.DB + tx := db.Begin() // 开始事务 + if tx.Error != nil { + global.LOG.Error(tx.Error) + return + } + defer func() { + if r := recover(); r != nil { + tx.Rollback() + } + }() + // 第一次登录,创建用户 + uid := idgen.NextId() + uidStr := strconv.FormatInt(uid, 10) + user := model.ScaAuthUser{ + UID: &uidStr, + Username: &giteeUser.Login, + Nickname: &giteeUser.Name, + Avatar: &giteeUser.AvatarURL, + Blog: &giteeUser.Blog, + Email: &giteeUser.Email, + } + addUser, err := userService.AddUser(user) + if err != nil { + tx.Rollback() + global.LOG.Error(err) + return + } + gitee := enum.OAuthSourceGitee + userSocial = model.ScaAuthUserSocial{ + UserID: &uidStr, + UUID: &Id, + Source: &gitee, + } + err = userSocialService.AddUserSocial(userSocial) + if err != nil { + tx.Rollback() + global.LOG.Error(err) + return + } + _, err = global.Casbin.AddRoleForUser(uidStr, enum.User) + if err != nil { + tx.Rollback() + global.LOG.Error(err) + return + } + if err := tx.Commit().Error; err != nil { + tx.Rollback() + global.LOG.Error(err) + return + } + HandleLoginResponse(c, *addUser.UID) + } else { + HandleLoginResponse(c, *userSocial.UserID) } - err = userRoleService.AddUserRole(userRole) - if err != nil { - global.LOG.Error(err) - return - } - res, data := HandelUserLogin(addUser) - if !res { - return - } - tokenData, err := json.Marshal(data) - if err != nil { - global.LOG.Error(err) - return - } - formattedScript := fmt.Sprintf(script, tokenData, global.CONFIG.System.Web) - c.Data(http.StatusOK, "text/html; charset=utf-8", []byte(formattedScript)) - } else { - user, err := userService.QueryUserById(userSocial.UserID) - if err != nil { - global.LOG.Error(err) - return - } - res, data := HandelUserLogin(user) - if !res { - return - } - tokenData, err := json.Marshal(data) - if err != nil { - global.LOG.Error(err) - return - } - formattedScript := fmt.Sprintf(script, tokenData, global.CONFIG.System.Web) - c.Data(http.StatusOK, "text/html; charset=utf-8", []byte(formattedScript)) + return } - return } diff --git a/api/oauth_api/github_api.go b/api/oauth_api/github_api.go index 18183bf..789ce2d 100644 --- a/api/oauth_api/github_api.go +++ b/api/oauth_api/github_api.go @@ -148,99 +148,116 @@ func (OAuthAPI) Callback(c *gin.Context) { result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) return } - // 通过 code, 获取 token - var tokenAuthUrl = GetTokenAuthUrl(code) - var token *Token - if token, err = GetToken(tokenAuthUrl); err != nil { - global.LOG.Error(err) - return - } - // 通过token,获取用户信息 - var userInfo map[string]interface{} - if userInfo, err = GetUserInfo(token); err != nil { + // 使用channel来接收异步操作的结果 + tokenChan := make(chan *Token) + userInfoChan := make(chan map[string]interface{}) + errChan := make(chan error) + + // 异步获取token + go func() { + var tokenAuthUrl = GetTokenAuthUrl(code) + token, err := GetToken(tokenAuthUrl) + if err != nil { + errChan <- err + return + } + tokenChan <- token + }() + + // 异步获取用户信息 + go func() { + token := <-tokenChan + if token == nil { + return + } + userInfo, err := GetUserInfo(token) + if err != nil { + errChan <- err + return + } + userInfoChan <- userInfo + }() + + select { + case err = <-errChan: global.LOG.Error(err) return - } - //json 转 struct - userInfoBytes, err := json.Marshal(userInfo) - if err != nil { - global.LOG.Error(err) + case userInfo := <-userInfoChan: + if userInfo == nil { + global.LOG.Error(<-errChan) + return + } + // 继续处理用户信息 + userInfoBytes, err := json.Marshal(<-userInfoChan) + if err != nil { + global.LOG.Error(err) + return + } + var gitHubUser GitHubUser + err = json.Unmarshal(userInfoBytes, &gitHubUser) + if err != nil { + global.LOG.Error(err) + return + } + Id := strconv.Itoa(gitHubUser.ID) + userSocial, err := userSocialService.QueryUserSocialByUUID(Id, enum.OAuthSourceGithub) + if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { + db := global.DB + tx := db.Begin() // 开始事务 + if tx.Error != nil { + global.LOG.Error(tx.Error) + return + } + defer func() { + if r := recover(); r != nil { + tx.Rollback() + } + }() + // 第一次登录,创建用户 + uid := idgen.NextId() + uidStr := strconv.FormatInt(uid, 10) + user := model.ScaAuthUser{ + UID: &uidStr, + Username: &gitHubUser.Login, + Nickname: &gitHubUser.Name, + Avatar: &gitHubUser.AvatarURL, + Blog: &gitHubUser.Blog, + Email: &gitHubUser.Email, + } + addUser, err := userService.AddUser(user) + if err != nil { + tx.Rollback() + global.LOG.Error(err) + return + } + github := enum.OAuthSourceGithub + userSocial = model.ScaAuthUserSocial{ + UserID: &uidStr, + UUID: &Id, + Source: &github, + } + err = userSocialService.AddUserSocial(userSocial) + if err != nil { + tx.Rollback() + global.LOG.Error(err) + return + } + _, err = global.Casbin.AddRoleForUser(uidStr, enum.User) + if err != nil { + tx.Rollback() + global.LOG.Error(err) + return + } + if err := tx.Commit().Error; err != nil { + tx.Rollback() + global.LOG.Error(err) + return + } + HandleLoginResponse(c, *addUser.UID) + } else { + HandleLoginResponse(c, *userSocial.UserID) + } return } - var gitHubUser GitHubUser - err = json.Unmarshal(userInfoBytes, &gitHubUser) - if err != nil { - global.LOG.Error(err) - return - } - Id := strconv.Itoa(gitHubUser.ID) - userSocial, err := userSocialService.QueryUserSocialByUUID(Id, enum.OAuthSourceGithub) - if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { - // 第一次登录,创建用户 - uid := idgen.NextId() - uidStr := strconv.FormatInt(uid, 10) - user := model.ScaAuthUser{ - UID: &uidStr, - Username: &gitHubUser.Login, - Nickname: &gitHubUser.Name, - Avatar: &gitHubUser.AvatarURL, - Blog: &gitHubUser.Blog, - Email: &gitHubUser.Email, - } - addUser, err := userService.AddUser(user) - if err != nil { - global.LOG.Error(err) - return - } - github := enum.OAuthSourceGithub - userSocial = model.ScaAuthUserSocial{ - UserID: &addUser.ID, - UUID: &Id, - Source: &github, - } - err = userSocialService.AddUserSocial(userSocial) - if err != nil { - global.LOG.Error(err) - return - } - userRole := model.ScaAuthUserRole{ - UserID: uidStr, - RoleID: enum.User, - } - err = userRoleService.AddUserRole(userRole) - if err != nil { - global.LOG.Error(err) - return - } - res, data := HandelUserLogin(addUser) - if !res { - return - } - tokenData, err := json.Marshal(data) - if err != nil { - global.LOG.Error(err) - return - } - formattedScript := fmt.Sprintf(script, tokenData, global.CONFIG.System.Web) - c.Data(http.StatusOK, "text/html; charset=utf-8", []byte(formattedScript)) - } else { - user, err := userService.QueryUserById(userSocial.UserID) - if err != nil { - global.LOG.Error(err) - return - } - res, data := HandelUserLogin(user) - if !res { - return - } - tokenData, err := json.Marshal(data) - if err != nil { - global.LOG.Error(err) - return - } - formattedScript := fmt.Sprintf(script, tokenData, global.CONFIG.System.Web) - c.Data(http.StatusOK, "text/html; charset=utf-8", []byte(formattedScript)) - } - return } diff --git a/api/oauth_api/oauth.go b/api/oauth_api/oauth.go index 5b21d14..9f9c131 100644 --- a/api/oauth_api/oauth.go +++ b/api/oauth_api/oauth.go @@ -2,10 +2,13 @@ package oauth_api import ( "encoding/json" + "fmt" + "github.com/gin-gonic/gin" + "net/http" "schisandra-cloud-album/api/user_api/dto" "schisandra-cloud-album/common/constant" "schisandra-cloud-album/common/redis" - "schisandra-cloud-album/model" + "schisandra-cloud-album/global" "schisandra-cloud-album/service" "schisandra-cloud-album/utils" "time" @@ -14,11 +17,7 @@ import ( type OAuthAPI struct{} var userService = service.Service.UserService -var userRoleService = service.Service.UserRoleService var userSocialService = service.Service.UserSocialService -var rolePermissionService = service.Service.RolePermissionService -var permissionServiceService = service.Service.PermissionService -var roleService = service.Service.RoleService type Token struct { AccessToken string `json:"access_token"` @@ -31,50 +30,82 @@ var script = ` ` +func HandleLoginResponse(c *gin.Context, uid string) { + res, data := HandelUserLogin(uid) + if !res { + return + } + tokenData, err := json.Marshal(data) + if err != nil { + global.LOG.Error(err) + return + } + formattedScript := fmt.Sprintf(script, tokenData, global.CONFIG.System.Web) + c.Data(http.StatusOK, "text/html; charset=utf-8", []byte(formattedScript)) + return +} + // HandelUserLogin 处理用户登录 -func HandelUserLogin(user model.ScaAuthUser) (bool, map[string]interface{}) { - ids, err := userRoleService.GetUserRoleIdsByUserId(user.ID) - if err != nil { +func HandelUserLogin(userId string) (bool, map[string]interface{}) { + // 使用goroutine生成accessToken + accessTokenChan := make(chan string) + errChan := make(chan error) + go func() { + accessToken, err := utils.GenerateAccessToken(utils.AccessJWTPayload{UserID: &userId}) + if err != nil { + errChan <- err + return + } + accessTokenChan <- accessToken + }() + + // 使用goroutine生成refreshToken + refreshTokenChan := make(chan string) + expiresAtChan := make(chan int64) + go func() { + refreshToken, expiresAt := utils.GenerateRefreshToken(utils.RefreshJWTPayload{UserID: &userId}, time.Hour*24*7) + refreshTokenChan <- refreshToken + expiresAtChan <- expiresAt + }() + + // 等待accessToken和refreshToken生成完成 + var accessToken string + var refreshToken string + var expiresAt int64 + var err error + select { + case accessToken = <-accessTokenChan: + case err = <-errChan: + global.LOG.Error(err) return false, nil } - permissionIds := rolePermissionService.QueryPermissionIdsByRoleId(ids) - permissions, err := permissionServiceService.GetPermissionsByIds(permissionIds) - if err != nil { - return false, nil + select { + case refreshToken = <-refreshTokenChan: + case expiresAt = <-expiresAtChan: } - serializedPermissions, err := json.Marshal(permissions) - if err != nil { - return false, nil - } - wrong := redis.Set(constant.UserAuthPermissionRedisKey+*user.UID, serializedPermissions, 0).Err() - if wrong != nil { - return false, nil - } - roleList, err := roleService.GetRoleListByIds(ids) - if err != nil { - return false, nil - } - serializedRoleList, err := json.Marshal(roleList) - if err != nil { - return false, nil - } - er := redis.Set(constant.UserAuthRoleRedisKey+*user.UID, serializedRoleList, 0).Err() - if er != nil { - return false, nil - } - accessToken, err := utils.GenerateAccessToken(utils.AccessJWTPayload{UserID: user.UID, RoleID: ids}) - if err != nil { - return false, nil - } - refreshToken, expiresAt := utils.GenerateRefreshToken(utils.RefreshJWTPayload{UserID: user.UID, RoleID: ids}, time.Hour*24*7) + data := dto.ResponseData{ AccessToken: accessToken, RefreshToken: refreshToken, ExpiresAt: expiresAt, - UID: user.UID, + UID: &userId, } - fail := redis.Set(constant.UserLoginTokenRedisKey+*user.UID, data, time.Hour*24*7).Err() - if fail != nil { + + // 使用goroutine将数据存入redis + redisErrChan := make(chan error) + go func() { + fail := redis.Set(constant.UserLoginTokenRedisKey+userId, data, time.Hour*24*7).Err() + if fail != nil { + redisErrChan <- fail + return + } + redisErrChan <- nil + }() + + // 等待redis操作完成 + redisErr := <-redisErrChan + if redisErr != nil { + global.LOG.Error(redisErr) return false, nil } responseData := map[string]interface{}{ diff --git a/api/oauth_api/qq_api.go b/api/oauth_api/qq_api.go index 18862d8..92605e1 100644 --- a/api/oauth_api/qq_api.go +++ b/api/oauth_api/qq_api.go @@ -173,23 +173,61 @@ func (OAuthAPI) QQCallback(c *gin.Context) { result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) return } + // 通过 code, 获取 token var tokenAuthUrl = GetQQTokenAuthUrl(code) + tokenChan := make(chan *QQToken) + errChan := make(chan error) + go func() { + token, err := GetQQToken(tokenAuthUrl) + if err != nil { + errChan <- err + return + } + tokenChan <- token + }() var token *QQToken - if token, err = GetQQToken(tokenAuthUrl); err != nil { + select { + case token = <-tokenChan: + case err = <-errChan: global.LOG.Error(err) return } + // 通过 token,获取 openid - authQQme, err := GetQQUserOpenID(token) - if err != nil { + openIDChan := make(chan *AuthQQme) + errChan = make(chan error) + go func() { + authQQme, err := GetQQUserOpenID(token) + if err != nil { + errChan <- err + return + } + openIDChan <- authQQme + }() + var authQQme *AuthQQme + select { + case authQQme = <-openIDChan: + case err = <-errChan: global.LOG.Error(err) return } // 通过token,获取用户信息 + userInfoChan := make(chan map[string]interface{}) + errChan = make(chan error) + go func() { + userInfo, err := GetQQUserUserInfo(token, authQQme.OpenID) + if err != nil { + errChan <- err + return + } + userInfoChan <- userInfo + }() var userInfo map[string]interface{} - if userInfo, err = GetQQUserUserInfo(token, authQQme.OpenID); err != nil { + select { + case userInfo = <-userInfoChan: + case err = <-errChan: global.LOG.Error(err) return } @@ -205,8 +243,20 @@ func (OAuthAPI) QQCallback(c *gin.Context) { global.LOG.Error(err) return } + userSocial, err := userSocialService.QueryUserSocialByOpenID(authQQme.OpenID, enum.OAuthSourceQQ) if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { + db := global.DB + tx := db.Begin() // 开始事务 + if tx.Error != nil { + global.LOG.Error(tx.Error) + return + } + defer func() { + if r := recover(); r != nil { + tx.Rollback() + } + }() // 第一次登录,创建用户 uid := idgen.NextId() uidStr := strconv.FormatInt(uid, 10) @@ -221,59 +271,36 @@ func (OAuthAPI) QQCallback(c *gin.Context) { } addUser, err := userService.AddUser(user) if err != nil { + tx.Rollback() global.LOG.Error(err) return } qq := enum.OAuthSourceQQ userSocial = model.ScaAuthUserSocial{ - UserID: &addUser.ID, + UserID: &uidStr, OpenID: &authQQme.OpenID, Source: &qq, } err = userSocialService.AddUserSocial(userSocial) if err != nil { + tx.Rollback() global.LOG.Error(err) return } - userRole := model.ScaAuthUserRole{ - UserID: uidStr, - RoleID: enum.User, - } - err = userRoleService.AddUserRole(userRole) + _, err = global.Casbin.AddRoleForUser(uidStr, enum.User) if err != nil { + tx.Rollback() global.LOG.Error(err) return } - res, data := HandelUserLogin(addUser) - if !res { - return - } - tokenData, err := json.Marshal(data) - if err != nil { + if err := tx.Commit().Error; err != nil { + tx.Rollback() global.LOG.Error(err) return } - formattedScript := fmt.Sprintf(script, tokenData, global.CONFIG.System.Web) - c.Data(http.StatusOK, "text/html; charset=utf-8", []byte(formattedScript)) + HandleLoginResponse(c, *addUser.UID) return } else { - user, err := userService.QueryUserById(userSocial.UserID) - if err != nil { - global.LOG.Error(err) - return - } - res, data := HandelUserLogin(user) - if !res { - return - } - tokenData, err := json.Marshal(data) - if err != nil { - global.LOG.Error(err) - return - } - formattedScript := fmt.Sprintf(script, tokenData, global.CONFIG.System.Web) - c.Data(http.StatusOK, "text/html; charset=utf-8", []byte(formattedScript)) - return + HandleLoginResponse(c, *userSocial.UserID) } - } diff --git a/api/oauth_api/wechat_api.go b/api/oauth_api/wechat_api.go index 56ebc6a..0f0dae9 100644 --- a/api/oauth_api/wechat_api.go +++ b/api/oauth_api/wechat_api.go @@ -26,9 +26,12 @@ import ( "schisandra-cloud-album/utils" "strconv" "strings" + "sync" "time" ) +var mu sync.Mutex + // GenerateClientId 生成客户端ID // @Summary 生成客户端ID // @Description 生成客户端ID @@ -44,6 +47,9 @@ func (OAuthAPI) GenerateClientId(c *gin.Context) { if ip == "" { ip = c.ClientIP() } + // 加锁 + mu.Lock() + defer mu.Unlock() // 从Redis获取客户端ID clientId := redis.Get(constant.UserLoginClientRedisKey + ip).Val() @@ -70,10 +76,7 @@ func (OAuthAPI) GenerateClientId(c *gin.Context) { // @Router /api/oauth/callback_notify [POST] func (OAuthAPI) CallbackNotify(c *gin.Context) { rs, err := global.Wechat.Server.Notify(c.Request, func(event contract.EventInterface) interface{} { - fmt.Dump("event", event) - switch event.GetMsgType() { - case models2.CALLBACK_MSG_TYPE_EVENT: switch event.GetEvent() { case models.CALLBACK_EVENT_SUBSCRIBE: @@ -122,7 +125,6 @@ func (OAuthAPI) CallbackNotify(c *gin.Context) { println(err.Error()) return "error" } - fmt.Dump(msg) } return messages.NewText("ok") @@ -177,6 +179,7 @@ func (OAuthAPI) GetTempQrCode(c *gin.Context) { data := response.ResponseQRCodeCreate{} err := json.Unmarshal([]byte(qrcode), &data) if err != nil { + global.LOG.Error(err) return } result.OK(ginI18n.MustGetMessage(c, "QRCodeGetSuccess"), data.Url, c) @@ -184,17 +187,20 @@ func (OAuthAPI) GetTempQrCode(c *gin.Context) { } data, err := global.Wechat.QRCode.Temporary(c.Request.Context(), clientId, 30*24*3600) if err != nil { + global.LOG.Error(err) result.FailWithMessage(ginI18n.MustGetMessage(c, "QRCodeGetFailed"), c) return } serializedData, err := json.Marshal(data) if err != nil { + global.LOG.Error(err) result.FailWithMessage(ginI18n.MustGetMessage(c, "QRCodeGetFailed"), c) return } wrong := redis.Set(constant.UserLoginQrcodeRedisKey+ip+":"+clientId, serializedData, time.Hour*24*30).Err() if wrong != nil { + global.LOG.Error(wrong) result.FailWithMessage(ginI18n.MustGetMessage(c, "QRCodeGetFailed"), c) return } @@ -208,45 +214,98 @@ func wechatLoginHandler(openId string, clientId string) bool { } authUserSocial, err := userSocialService.QueryUserSocialByOpenID(openId, enum.OAuthSourceWechat) if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { + tx := global.DB.Begin() + defer func() { + if r := recover(); r != nil { + tx.Rollback() + } + }() + uid := idgen.NextId() uidStr := strconv.FormatInt(uid, 10) createUser := model.ScaAuthUser{ UID: &uidStr, Username: &openId, } - addUser, err := userService.AddUser(createUser) - if err != nil { + + // 异步添加用户 + addUserChan := make(chan *model.ScaAuthUser, 1) + errChan := make(chan error, 1) + go func() { + addUser, err := userService.AddUser(createUser) + if err != nil { + errChan <- err + return + } + addUserChan <- &addUser + }() + + var addUser *model.ScaAuthUser + select { + case addUser = <-addUserChan: + case err := <-errChan: + tx.Rollback() + global.LOG.Error(err) return false } + wechat := enum.OAuthSourceWechat userSocial := model.ScaAuthUserSocial{ - UserID: &addUser.ID, + UserID: &uidStr, OpenID: &openId, Source: &wechat, } - wrong := userSocialService.AddUserSocial(userSocial) - if wrong != nil { - return false + + // 异步添加用户社交信息 + wrongChan := make(chan error, 1) + go func() { + wrong := userSocialService.AddUserSocial(userSocial) + wrongChan <- wrong + }() + + select { + case wrong := <-wrongChan: + if wrong != nil { + tx.Rollback() + global.LOG.Error(wrong) + return false + } } - userRole := model.ScaAuthUserRole{ - UserID: uidStr, - RoleID: enum.User, + + // 异步添加角色 + roleErrChan := make(chan error, 1) + go func() { + _, err := global.Casbin.AddRoleForUser(uidStr, enum.User) + roleErrChan <- err + }() + + select { + case err := <-roleErrChan: + if err != nil { + tx.Rollback() + global.LOG.Error(err) + return false + } } - e := userRoleService.AddUserRole(userRole) - if e != nil { - return false - } - res := handelUserLogin(addUser, clientId) - if !res { - return false + + // 异步处理用户登录 + resChan := make(chan bool, 1) + go func() { + res := handelUserLogin(*addUser.UID, clientId) + resChan <- res + }() + + select { + case res := <-resChan: + if !res { + tx.Rollback() + return false + } } + tx.Commit() return true } else { - user, err := userService.QueryUserById(authUserSocial.UserID) - if err != nil { - return false - } - res := handelUserLogin(user, clientId) + res := handelUserLogin(*authUserSocial.UserID, clientId) if !res { return false } @@ -255,70 +314,47 @@ func wechatLoginHandler(openId string, clientId string) bool { } // handelUserLogin 处理用户登录 -func handelUserLogin(user model.ScaAuthUser, clientId string) bool { - ids, err := userRoleService.GetUserRoleIdsByUserId(user.ID) - if err != nil { - return false - } - permissionIds := rolePermissionService.QueryPermissionIdsByRoleId(ids) - permissions, err := permissionServiceService.GetPermissionsByIds(permissionIds) - if err != nil { - return false - } - serializedPermissions, err := json.Marshal(permissions) - if err != nil { - return false - } - wrong := redis.Set(constant.UserAuthPermissionRedisKey+*user.UID, serializedPermissions, 0).Err() - if wrong != nil { - return false - } - roleList, err := roleService.GetRoleListByIds(ids) - if err != nil { - return false - } - serializedRoleList, err := json.Marshal(roleList) - if err != nil { - return false - } - er := redis.Set(constant.UserAuthRoleRedisKey+*user.UID, serializedRoleList, 0).Err() - if er != nil { - return false - } - accessToken, err := utils.GenerateAccessToken(utils.AccessJWTPayload{UserID: user.UID, RoleID: ids}) - if err != nil { - return false - } - refreshToken, expiresAt := utils.GenerateRefreshToken(utils.RefreshJWTPayload{UserID: user.UID, RoleID: ids}, time.Hour*24*7) - data := dto.ResponseData{ - AccessToken: accessToken, - RefreshToken: refreshToken, - ExpiresAt: expiresAt, - UID: user.UID, - } - fail := redis.Set(constant.UserLoginTokenRedisKey+*user.UID, data, time.Hour*24*7).Err() - if fail != nil { - return false - } - responseData := map[string]interface{}{ - "code": 0, - "message": "success", - "data": data, - "success": true, - } - tokenData, err := json.Marshal(responseData) - if err != nil { - return false - } - // gws方式发送消息 - err = websocket_api.Handler.SendMessageToClient(clientId, tokenData) - if err != nil { - return false - } - // gorilla websocket方式发送消息 - //res := websocket_api.SendMessageData(clientId, responseData) - //if !res { - // return false - //} - return true +func handelUserLogin(userId string, clientId string) bool { + resultChan := make(chan bool, 1) + + go func() { + accessToken, err := utils.GenerateAccessToken(utils.AccessJWTPayload{UserID: &userId}) + if err != nil { + resultChan <- false + return + } + refreshToken, expiresAt := utils.GenerateRefreshToken(utils.RefreshJWTPayload{UserID: &userId}, time.Hour*24*7) + data := dto.ResponseData{ + AccessToken: accessToken, + RefreshToken: refreshToken, + ExpiresAt: expiresAt, + UID: &userId, + } + fail := redis.Set(constant.UserLoginTokenRedisKey+userId, data, time.Hour*24*7).Err() + if fail != nil { + resultChan <- false + return + } + responseData := map[string]interface{}{ + "code": 0, + "message": "success", + "data": data, + "success": true, + } + tokenData, err := json.Marshal(responseData) + if err != nil { + resultChan <- false + return + } + // gws方式发送消息 + err = websocket_api.Handler.SendMessageToClient(clientId, tokenData) + if err != nil { + global.LOG.Error(err) + resultChan <- false + return + } + resultChan <- true + }() + + return <-resultChan } diff --git a/api/permission_api/dto/request_dto.go b/api/permission_api/dto/request_dto.go new file mode 100644 index 0000000..4a2397b --- /dev/null +++ b/api/permission_api/dto/request_dto.go @@ -0,0 +1,11 @@ +package dto + +import "schisandra-cloud-album/model" + +type AddPermissionRequestDto struct { + Permissions []model.ScaAuthPermission `json:"permissions"` +} +type AddPermissionToRoleRequestDto struct { + RoleKey string `json:"role_key"` + Permissions []model.ScaAuthPermission `json:"permissions"` +} diff --git a/api/permission_api/permission.go b/api/permission_api/permission.go new file mode 100644 index 0000000..6677581 --- /dev/null +++ b/api/permission_api/permission.go @@ -0,0 +1,3 @@ +package permission_api + +type PermissionAPI struct{} diff --git a/api/permission_api/permission_api.go b/api/permission_api/permission_api.go new file mode 100644 index 0000000..78a8fba --- /dev/null +++ b/api/permission_api/permission_api.go @@ -0,0 +1,36 @@ +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" +) + +var permissionService = service.Service.PermissionService + +// AddPermissions 批量添加权限 +// @Summary 批量添加权限 +// @Description 批量添加权限 +// @Tags 权限管理 +// @Accept json +// @Produce json +// @Param permissions body dto.AddPermissionRequestDto true "权限列表" +// @Router /api/auth/permission/add [post] +func (PermissionAPI) AddPermissions(c *gin.Context) { + addPermissionRequestDto := dto.AddPermissionRequestDto{} + err := c.ShouldBindJSON(&addPermissionRequestDto) + if err != nil { + return + } + err = permissionService.CreatePermissions(addPermissionRequestDto.Permissions) + if err != nil { + global.LOG.Error(err) + result.FailWithMessage(ginI18n.MustGetMessage(c, "CreatedFailed"), c) + return + } + result.OkWithMessage(ginI18n.MustGetMessage(c, "CreatedSuccess"), c) + return +} diff --git a/api/role_api/dto/request_dto.go b/api/role_api/dto/request_dto.go new file mode 100644 index 0000000..13be17c --- /dev/null +++ b/api/role_api/dto/request_dto.go @@ -0,0 +1,11 @@ +package dto + +type RoleRequestDto struct { + RoleName string `json:"role_name"` + RoleKey string `json:"role_key"` +} + +type AddRoleToUserRequestDto struct { + Uid string `json:"uid"` + RoleKey string `json:"role_key"` +} diff --git a/api/role_api/role_api.go b/api/role_api/role_api.go index e3c92dd..64d6706 100644 --- a/api/role_api/role_api.go +++ b/api/role_api/role_api.go @@ -1 +1,64 @@ 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" + "schisandra-cloud-album/service" +) + +var roleService = service.Service.RoleService + +// CreateRole 创建角色 +// @Summary 创建角色 +// @Description 创建角色 +// @Tags 角色 +// @Accept json +// @Produce json +// @Param roleRequestDto body dto.RoleRequestDto true "角色信息" +// @Router /api/auth/role/create [post] +func (RoleAPI) CreateRole(c *gin.Context) { + roleRequestDto := dto.RoleRequestDto{} + err := c.ShouldBindJSON(&roleRequestDto) + if err != nil { + result.FailWithMessage(ginI18n.MustGetMessage(c, "CreatedFailed"), c) + return + } + role := model.ScaAuthRole{ + RoleName: roleRequestDto.RoleName, + RoleKey: roleRequestDto.RoleKey, + } + err = roleService.AddRole(role) + if err != nil { + global.LOG.Error(err) + result.FailWithMessage(ginI18n.MustGetMessage(c, "CreatedFailed"), c) + return + } + result.OkWithMessage(ginI18n.MustGetMessage(c, "CreatedSuccess"), c) +} + +// AddRoleToUser 给指定用户添加角色 +// @Summary 给指定用户添加角色 +// @Description 给指定用户添加角色 +// @Tags 角色 +// @Accept json +// @Produce json +// @Param addRoleToUserRequestDto body dto.AddRoleToUserRequestDto true "给指定用户添加角色" +// @Router /api/auth/role/add_role_to_user [post] +func (RoleAPI) AddRoleToUser(c *gin.Context) { + addRoleToUserRequestDto := dto.AddRoleToUserRequestDto{} + err := c.ShouldBindJSON(&addRoleToUserRequestDto) + if err != nil { + global.LOG.Error(err) + return + } + user, err := global.Casbin.AddRoleForUser(addRoleToUserRequestDto.Uid, addRoleToUserRequestDto.RoleKey) + if err != nil { + global.LOG.Error(err) + return + } + result.OkWithData(user, c) +} diff --git a/api/user_api/user_api.go b/api/user_api/user_api.go index 2b16309..2b7de9b 100644 --- a/api/user_api/user_api.go +++ b/api/user_api/user_api.go @@ -1,7 +1,6 @@ package user_api import ( - "encoding/json" ginI18n "github.com/gin-contrib/i18n" "github.com/gin-gonic/gin" "github.com/yitter/idgenerator-go/idgen" @@ -20,10 +19,6 @@ import ( ) var userService = service.Service.UserService -var userRoleService = service.Service.UserRoleService -var rolePermissionService = service.Service.RolePermissionService -var permissionServiceService = service.Service.PermissionService -var roleService = service.Service.RoleService // GetUserList // @Summary 获取所有用户列表 @@ -146,12 +141,8 @@ func (UserAPI) AddUser(c *gin.Context) { result.FailWithMessage(ginI18n.MustGetMessage(c, "AddUserError"), c) return } - userRole := model.ScaAuthUserRole{ - UserID: uidStr, - RoleID: enum.User, - } - e := userRoleService.AddUserRole(userRole) - if e != nil { + _, err = global.Casbin.AddRoleForUser(uidStr, enum.User) + if err != nil { result.FailWithMessage(ginI18n.MustGetMessage(c, "AddUserRoleError"), c) return } @@ -258,11 +249,30 @@ func (UserAPI) PhoneLogin(c *gin.Context) { return } - user := userService.QueryUserByPhone(phone) - if reflect.DeepEqual(user, model.ScaAuthUser{}) { - // 未注册 + // 异步查询用户信息 + userChan := make(chan *model.ScaAuthUser) + go func() { + user := userService.QueryUserByPhone(phone) + userChan <- &user + }() + + // 异步获取验证码 + codeChan := make(chan string) + go func() { code := redis.Get(constant.UserLoginSmsRedisKey + phone) if code == nil { + codeChan <- "" + } else { + codeChan <- code.Val() + } + }() + + user := <-userChan + code := <-codeChan + + if reflect.DeepEqual(user, model.ScaAuthUser{}) { + // 未注册 + if code == "" { result.FailWithMessage(ginI18n.MustGetMessage(c, "CaptchaExpired"), c) return } else { @@ -277,35 +287,29 @@ func (UserAPI) PhoneLogin(c *gin.Context) { result.FailWithMessage(ginI18n.MustGetMessage(c, "RegisterUserError"), c) return } - userRole := model.ScaAuthUserRole{ - UserID: uidStr, - RoleID: enum.User, - } - e := userRoleService.AddUserRole(userRole) - if e != nil { - result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) + + _, err = global.Casbin.AddRoleForUser(uidStr, enum.User) + if err != nil { + result.FailWithMessage(ginI18n.MustGetMessage(c, "RegisterUserError"), c) return } handelUserLogin(addUser, request.AutoLogin, c) return } } else { - code := redis.Get(constant.UserLoginSmsRedisKey + phone) - if code == nil { + if code == "" { result.FailWithMessage(ginI18n.MustGetMessage(c, "CaptchaExpired"), c) return } else { - if captcha != code.Val() { + if captcha != code { result.FailWithMessage(ginI18n.MustGetMessage(c, "CaptchaError"), c) return } else { - handelUserLogin(user, request.AutoLogin, c) + handelUserLogin(*user, request.AutoLogin, c) return } } - } - } // RefreshHandler 刷新token @@ -333,7 +337,7 @@ func (UserAPI) RefreshHandler(c *gin.Context) { return } if isUpd { - accessTokenString, err := utils.GenerateAccessToken(utils.AccessJWTPayload{UserID: parseRefreshToken.UserID, RoleID: parseRefreshToken.RoleID}) + accessTokenString, err := utils.GenerateAccessToken(utils.AccessJWTPayload{UserID: parseRefreshToken.UserID}) if err != nil { result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginExpired"), c) return @@ -362,42 +366,7 @@ func (UserAPI) RefreshHandler(c *gin.Context) { // handelUserLogin 处理用户登录 func handelUserLogin(user model.ScaAuthUser, autoLogin bool, c *gin.Context) { - ids, err := userRoleService.GetUserRoleIdsByUserId(user.ID) - if err != nil { - result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) - return - } - permissionIds := rolePermissionService.QueryPermissionIdsByRoleId(ids) - permissions, err := permissionServiceService.GetPermissionsByIds(permissionIds) - if err != nil { - result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) - return - } - serializedPermissions, err := json.Marshal(permissions) - if err != nil { - result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) - return - } - wrong := redis.Set(constant.UserAuthPermissionRedisKey+*user.UID, serializedPermissions, 0).Err() - if wrong != nil { - result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) - return - } - roleList, err := roleService.GetRoleListByIds(ids) - if err != nil { - return - } - serializedRoleList, err := json.Marshal(roleList) - if err != nil { - result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) - return - } - er := redis.Set(constant.UserAuthRoleRedisKey+*user.UID, serializedRoleList, 0).Err() - if er != nil { - result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) - return - } - accessToken, err := utils.GenerateAccessToken(utils.AccessJWTPayload{UserID: user.UID, RoleID: ids}) + accessToken, err := utils.GenerateAccessToken(utils.AccessJWTPayload{UserID: user.UID}) if err != nil { result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) return @@ -408,7 +377,7 @@ func handelUserLogin(user model.ScaAuthUser, autoLogin bool, c *gin.Context) { } else { days = time.Hour * 24 * 1 } - refreshToken, expiresAt := utils.GenerateRefreshToken(utils.RefreshJWTPayload{UserID: user.UID, RoleID: ids}, days) + refreshToken, expiresAt := utils.GenerateRefreshToken(utils.RefreshJWTPayload{UserID: user.UID}, days) data := dto.ResponseData{ AccessToken: accessToken, RefreshToken: refreshToken, diff --git a/cmd/db/db.go b/cmd/db/db.go index 7495ff1..98775b4 100644 --- a/cmd/db/db.go +++ b/cmd/db/db.go @@ -12,8 +12,6 @@ func MakeMigration() { &model.ScaAuthUser{}, &model.ScaAuthPermission{}, &model.ScaAuthRole{}, - &model.ScaAuthRolePermission{}, - &model.ScaAuthUserRole{}, &model.ScaAuthUserDevice{}, &model.ScaAuthUserSocial{}, ) diff --git a/common/enum/role.go b/common/enum/role.go index ee0ef24..9464eb3 100644 --- a/common/enum/role.go +++ b/common/enum/role.go @@ -1,7 +1,7 @@ package enum var ( - SuperAdmin int64 = 1 - Admin int64 = 2 - User int64 = 3 + Root string = "root" + Admin string = "admin" + User string = "user" ) diff --git a/config/conf_casbin.go b/config/conf_casbin.go new file mode 100644 index 0000000..cc62c07 --- /dev/null +++ b/config/conf_casbin.go @@ -0,0 +1,10 @@ +package config + +type Casbin struct { + // 权限模型文件路径 + ModelPath string `yaml:"model-path"` + // 数据库前缀 + TablePrefix string `yaml:"table-prefix"` + // 数据库表明 + TableName string `yaml:"table-name"` +} diff --git a/config/conf_logger.go b/config/conf_logger.go index 284950c..de4aada 100644 --- a/config/conf_logger.go +++ b/config/conf_logger.go @@ -2,9 +2,9 @@ package config // Logger 配置 type Logger struct { - Level string `yaml:"level"` // 日志级别 - Prefix string `yaml:"prefix"` // 日志前缀 - Director string `yaml:"director"` // 日志文件存放目录 - ShowLine bool `yaml:"show-line"` // 是否显示文件行号 - LogInConsole string `yaml:"log-in-console"` // 是否在控制台打印日志 + Level string `yaml:"level"` // 日志级别 + Prefix string `yaml:"prefix"` // 日志前缀 + Director string `yaml:"director"` // 日志文件存放目录 + ShowLine bool `yaml:"show-line"` // 是否显示文件行号 + LogName string `yaml:"log-name"` // 日志文件名 } diff --git a/config/conf_system.go b/config/conf_system.go index 8fae538..c0346d5 100644 --- a/config/conf_system.go +++ b/config/conf_system.go @@ -8,6 +8,7 @@ type System struct { Port string `yaml:"port"` //端口号 Env string `yaml:"env"` //环境 Web string `yaml:"web"` //web地址 + Ip string `yaml:"ip"` //ip地址 } func (s *System) Addr() string { diff --git a/config/config.go b/config/config.go index f8abe11..06c0eea 100644 --- a/config/config.go +++ b/config/config.go @@ -11,4 +11,5 @@ type Config struct { Wechat Wechat `yaml:"wechat"` OAuth OAuth `yaml:"oauth"` Swagger Swagger `yaml:"swagger"` + Casbin Casbin `yaml:"casbin"` } diff --git a/core/captcha.go b/core/captcha.go index 969d236..005067b 100644 --- a/core/captcha.go +++ b/core/captcha.go @@ -11,7 +11,6 @@ import ( "github.com/wenlng/go-captcha/v2/click" "github.com/wenlng/go-captcha/v2/rotate" "github.com/wenlng/go-captcha/v2/slide" - "log" "schisandra-cloud-album/global" ) @@ -47,13 +46,13 @@ func initTextCaptcha() { // fonts fonts, err := fzshengsksjw.GetFont() if err != nil { - log.Fatalln(err) + global.LOG.Fatalln(err) } // background images imgs, err := images.GetImages() if err != nil { - log.Fatalln(err) + global.LOG.Fatalln(err) } // thumb images @@ -119,13 +118,13 @@ func initClickShapeCaptcha() { // click.WithUseShapeOriginalColor(false) -> Random rewriting of graphic colors shapeMaps, err := shapes.GetShapes() if err != nil { - log.Fatalln(err) + global.LOG.Fatalln(err) } // background images imgs, err := images.GetImages() if err != nil { - log.Fatalln(err) + global.LOG.Fatalln(err) } // set resources @@ -146,12 +145,12 @@ func initsSlideCaptcha() { // background images imgs, err := images.GetImages() if err != nil { - log.Fatalln(err) + global.LOG.Fatalln(err) } graphs, err := tiles.GetTiles() if err != nil { - log.Fatalln(err) + global.LOG.Fatalln(err) } var newGraphs = make([]*slide.GraphImage, 0, len(graphs)) @@ -182,7 +181,7 @@ func initRotateCaptcha() { // background images imgs, err := images.GetImages() if err != nil { - log.Fatalln(err) + global.LOG.Fatalln(err) } // set resources @@ -203,12 +202,12 @@ func initSlideRegionCaptcha() { // background image imgs, err := images.GetImages() if err != nil { - log.Fatalln(err) + global.LOG.Fatalln(err) } graphs, err := tiles.GetTiles() if err != nil { - log.Fatalln(err) + global.LOG.Fatalln(err) } var newGraphs = make([]*slide.GraphImage, 0, len(graphs)) for i := 0; i < len(graphs); i++ { diff --git a/core/casbin.go b/core/casbin.go index 7989c6b..ccf053f 100644 --- a/core/casbin.go +++ b/core/casbin.go @@ -14,13 +14,22 @@ var ( func InitCasbin() { once.Do(func() { - adapter, _ := gormadapter.NewAdapterByDBUseTableName(global.DB, "sca_sys_", "casbin_rule") - m, err := model.NewModelFromFile("config/rbac_model.pml") + adapter, err := gormadapter.NewAdapterByDBUseTableName(global.DB, global.CONFIG.Casbin.TablePrefix, global.CONFIG.Casbin.TableName) if err != nil { global.LOG.Error(err.Error()) panic(err) } - e, _ := casbin.NewCachedEnforcer(m, adapter) + m, err := model.NewModelFromFile(global.CONFIG.Casbin.ModelPath) + if err != nil { + global.LOG.Error(err.Error()) + panic(err) + } + e, err := casbin.NewCachedEnforcer(m, adapter) + if err != nil { + global.LOG.Error(err.Error()) + panic(err) + } + e.EnableCache(true) e.SetExpireTime(60 * 60) err = e.LoadPolicy() if err != nil { diff --git a/core/gorm.go b/core/gorm.go index 72908b2..5fd96a9 100644 --- a/core/gorm.go +++ b/core/gorm.go @@ -34,8 +34,9 @@ func MySQlConnect() *gorm.DB { }) } else { + logfile, _ := os.OpenFile("/tmp/logs/mysql.log", os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666) mysqlLogger = logger.New( - log.New(os.Stdout, "\r\n", log.LstdFlags), + log.New(logfile, "\r\n", log.LstdFlags), logger.Config{ SlowThreshold: time.Second, //慢sql日志 LogLevel: logger.Error, //级别 @@ -46,12 +47,16 @@ func MySQlConnect() *gorm.DB { } db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{ - Logger: mysqlLogger, + Logger: mysqlLogger, + PrepareStmt: true, }) if err != nil { global.LOG.Fatalf(fmt.Sprintf("[%s] MySQL 连接失败", dsn)) } - sqlDB, _ := db.DB() + sqlDB, err := db.DB() + if err != nil { + global.LOG.Fatalf(fmt.Sprintf("[%s] MySQL 获取DB失败", dsn)) + } sqlDB.SetMaxIdleConns(global.CONFIG.MySQL.MaxIdleConnes) sqlDB.SetMaxOpenConns(global.CONFIG.MySQL.MaxOpenConnes) sqlDB.SetConnMaxLifetime(time.Hour * 4) //连接最大复用时间 diff --git a/core/logrus.go b/core/logrus.go index 60480c2..af89764 100644 --- a/core/logrus.go +++ b/core/logrus.go @@ -1,80 +1,24 @@ package core import ( - "bytes" - "fmt" "github.com/sirupsen/logrus" - "os" - "path" "schisandra-cloud-album/global" + "schisandra-cloud-album/middleware" + "time" ) -const ( - red = 31 - yellow = 33 - blue = 34 - gray = 37 -) - -type LogFormatter struct{} - -func (f *LogFormatter) Format(entry *logrus.Entry) ([]byte, error) { - //根据不同的level显示不同的颜色 - var levelColor int - switch entry.Level { - case logrus.DebugLevel, logrus.TraceLevel: - levelColor = gray - case logrus.WarnLevel: - levelColor = yellow - case logrus.ErrorLevel, logrus.FatalLevel, logrus.PanicLevel: - levelColor = red - default: - levelColor = blue - } - var b *bytes.Buffer - if entry.Buffer != nil { - b = entry.Buffer - } else { - b = &bytes.Buffer{} - } - log := global.CONFIG.Logger - // 自定义日期格式 - timestamp := entry.Time.Format("2006-01-02 15:04:05") - if entry.HasCaller() { - //自定义文件路径 - funcVal := entry.Caller.Function - fileVal := fmt.Sprintf("%s:%d", path.Base(entry.Caller.File), entry.Caller.Line) - //自定义输出格式 - fmt.Fprintf(b, "%s[%s] \x1b[%dm[%s]\x1b[0m %s %s : %s\n", log.Prefix, timestamp, levelColor, entry.Level, fileVal, funcVal, entry.Message) - } else { - fmt.Fprintf(b, "%s[%s] \x1b[%dm[%s]\x1b[0m : %s\n", log.Prefix, timestamp, levelColor, entry.Level, entry.Message) - } - return b.Bytes(), nil -} - -func InitLogger() *logrus.Logger { - newLog := logrus.New() - newLog.SetOutput(os.Stdout) //设置输出类型 - newLog.SetReportCaller(global.CONFIG.Logger.ShowLine) //设置是否显示函数名和行号 - newLog.SetFormatter(&LogFormatter{}) //设置日志格式 +func InitLogger() { + // 按照日期格式化输出 + mylog := middleware.NewDateLog(&middleware.DateLogConfig{ + Date: time.Now().Format("2006-01-02"), + Path: global.CONFIG.Logger.Director, + Name: global.CONFIG.Logger.LogName, + }) + log := mylog.Init() level, err := logrus.ParseLevel(global.CONFIG.Logger.Level) if err != nil { level = logrus.InfoLevel } - newLog.SetLevel(level) //设置日志级别 - global.LOG = newLog - initDefaultLogger() - return newLog -} - -func initDefaultLogger() { - //全局日志 - logrus.SetOutput(os.Stdout) //设置输出类型 - logrus.SetReportCaller(global.CONFIG.Logger.ShowLine) //设置是否显示函数名和行号 - logrus.SetFormatter(&LogFormatter{}) //设置日志格式 - level, err := logrus.ParseLevel(global.CONFIG.Logger.Level) - if err != nil { - level = logrus.InfoLevel - } - logrus.SetLevel(level) //设置日志级别 + log.SetLevel(level) //设置日志级别 + global.LOG = log } diff --git a/core/wechat.go b/core/wechat.go index cae531d..7599742 100644 --- a/core/wechat.go +++ b/core/wechat.go @@ -13,10 +13,10 @@ func InitWechat() { Secret: global.CONFIG.Wechat.AppSecret, Token: global.CONFIG.Wechat.Token, AESKey: global.CONFIG.Wechat.AESKey, - //Log: officialAccount.Log{ - // Level: "debug", - // File: "./wechat.log", - //}, + Log: officialAccount.Log{ + Level: "error", + File: "./wechat.log", + }, ResponseType: os.Getenv("response_type"), HttpDebug: true, Debug: true, @@ -27,6 +27,7 @@ func InitWechat() { }), }) if err != nil { + global.LOG.Error(err.Error()) panic(err) } global.Wechat = OfficialAccountApp diff --git a/docs/docs.go b/docs/docs.go index e744526..3541296 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -15,6 +15,60 @@ const docTemplate = `{ "host": "{{.Host}}", "basePath": "{{.BasePath}}", "paths": { + "/api/auth/role/add_role_to_user": { + "post": { + "description": "给指定用户添加角色", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "角色" + ], + "summary": "给指定用户添加角色", + "parameters": [ + { + "description": "给指定用户添加角色", + "name": "addRoleToUserRequestDto", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.AddRoleToUserRequestDto" + } + } + ], + "responses": {} + } + }, + "/api/auth/role/create": { + "post": { + "description": "创建角色", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "角色" + ], + "summary": "创建角色", + "parameters": [ + { + "description": "角色信息", + "name": "roleRequestDto", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.RoleRequestDto" + } + } + ], + "responses": {} + } + }, "/api/auth/user/List": { "get": { "tags": [ @@ -735,6 +789,17 @@ const docTemplate = `{ } } }, + "dto.AddRoleToUserRequestDto": { + "type": "object", + "properties": { + "role_key": { + "type": "string" + }, + "uid": { + "type": "string" + } + } + }, "dto.AddUserRequest": { "type": "object", "properties": { @@ -779,6 +844,17 @@ const docTemplate = `{ "type": "string" } } + }, + "dto.RoleRequestDto": { + "type": "object", + "properties": { + "role_key": { + "type": "string" + }, + "role_name": { + "type": "string" + } + } } } }` diff --git a/docs/swagger.json b/docs/swagger.json index 0c483c2..86545e6 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -4,6 +4,60 @@ "contact": {} }, "paths": { + "/api/auth/role/add_role_to_user": { + "post": { + "description": "给指定用户添加角色", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "角色" + ], + "summary": "给指定用户添加角色", + "parameters": [ + { + "description": "给指定用户添加角色", + "name": "addRoleToUserRequestDto", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.AddRoleToUserRequestDto" + } + } + ], + "responses": {} + } + }, + "/api/auth/role/create": { + "post": { + "description": "创建角色", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "角色" + ], + "summary": "创建角色", + "parameters": [ + { + "description": "角色信息", + "name": "roleRequestDto", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.RoleRequestDto" + } + } + ], + "responses": {} + } + }, "/api/auth/user/List": { "get": { "tags": [ @@ -724,6 +778,17 @@ } } }, + "dto.AddRoleToUserRequestDto": { + "type": "object", + "properties": { + "role_key": { + "type": "string" + }, + "uid": { + "type": "string" + } + } + }, "dto.AddUserRequest": { "type": "object", "properties": { @@ -768,6 +833,17 @@ "type": "string" } } + }, + "dto.RoleRequestDto": { + "type": "object", + "properties": { + "role_key": { + "type": "string" + }, + "role_name": { + "type": "string" + } + } } } } \ No newline at end of file diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 24992c3..73ba8c5 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -8,6 +8,13 @@ definitions: password: type: string type: object + dto.AddRoleToUserRequestDto: + properties: + role_key: + type: string + uid: + type: string + type: object dto.AddUserRequest: properties: password: @@ -37,9 +44,52 @@ definitions: repassword: type: string type: object + dto.RoleRequestDto: + properties: + role_key: + type: string + role_name: + type: string + type: object info: contact: {} paths: + /api/auth/role/add_role_to_user: + post: + consumes: + - application/json + description: 给指定用户添加角色 + parameters: + - description: 给指定用户添加角色 + in: body + name: addRoleToUserRequestDto + required: true + schema: + $ref: '#/definitions/dto.AddRoleToUserRequestDto' + produces: + - application/json + responses: {} + summary: 给指定用户添加角色 + tags: + - 角色 + /api/auth/role/create: + post: + consumes: + - application/json + description: 创建角色 + parameters: + - description: 角色信息 + in: body + name: roleRequestDto + required: true + schema: + $ref: '#/definitions/dto.RoleRequestDto' + produces: + - application/json + responses: {} + summary: 创建角色 + tags: + - 角色 /api/auth/user/List: get: responses: diff --git a/go.mod b/go.mod index b423722..b558046 100644 --- a/go.mod +++ b/go.mod @@ -6,12 +6,16 @@ require ( github.com/ArtisanCloud/PowerLibs/v3 v3.2.5 github.com/ArtisanCloud/PowerWeChat/v3 v3.2.38 github.com/BurntSushi/toml v1.3.2 + github.com/casbin/casbin/v2 v2.98.0 + github.com/casbin/gorm-adapter/v3 v3.28.0 github.com/gin-contrib/cors v1.7.2 github.com/gin-contrib/i18n v1.1.3 github.com/gin-gonic/gin v1.10.0 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 github.com/gorilla/websocket v1.5.3 + github.com/juju/ratelimit v1.0.2 + github.com/lxzan/gws v1.8.5 github.com/pkg6/go-sms v0.1.2 github.com/redis/go-redis/v9 v9.6.1 github.com/satori/go.uuid v1.2.0 @@ -37,8 +41,6 @@ require ( github.com/KyleBanks/depth v1.2.1 // indirect github.com/bytedance/sonic v1.12.0 // indirect github.com/bytedance/sonic/loader v0.2.0 // indirect - github.com/casbin/casbin/v2 v2.98.0 // indirect - github.com/casbin/gorm-adapter/v3 v3.28.0 // indirect github.com/casbin/govaluate v1.2.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect @@ -71,11 +73,9 @@ require ( github.com/jinzhu/now v1.1.5 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/juju/ratelimit v1.0.2 // indirect github.com/klauspost/compress v1.17.5 // indirect github.com/klauspost/cpuid/v2 v2.2.8 // indirect github.com/leodido/go-urn v1.4.0 // indirect - github.com/lxzan/gws v1.8.5 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/microsoft/go-mssqldb v1.6.0 // indirect diff --git a/go.sum b/go.sum index e354648..1dd845a 100644 --- a/go.sum +++ b/go.sum @@ -9,14 +9,20 @@ github.com/ArtisanCloud/PowerWeChat/v3 v3.2.38/go.mod h1:9CbKc6nODhoM8TVjoXqujrA github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0/go.mod h1:ON4tFdPTwRcgWEaVDrN3584Ef+b7GgSJaXxe5fW9t4M= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.1/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.1 h1:/iHxaJhsFr0+xVFfbMr5vxz848jyiWuIEDhYq3y5odY= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.1/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U= github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.0 h1:yfJe15aSwEQ6Oo6J+gdfdulPNoZ3TEhmbhLIoxZcA+U= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.0/go.mod h1:Q28U+75mpCaSCDowNEmhIo/rmgdkqmkmzI7N6TGR4UY= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0 h1:T028gtTPiYt/RMUfs8nVsAL7FDQrfLlrm/NnRG/zcC4= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0/go.mod h1:cw4zVQgBby0Z5f2v0itn6se2dDP17nTjbZFXW5uPyHA= github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= +github.com/AzureAD/microsoft-authentication-library-for-go v1.1.0 h1:HCc0+LpPfpCKs6LGGLAhwBARt9632unrVcI6i8s/8os= github.com/AzureAD/microsoft-authentication-library-for-go v1.1.0/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= @@ -105,10 +111,13 @@ github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= 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/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= +github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= @@ -151,9 +160,12 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= +github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lxzan/gws v1.8.5 h1:6x+wW3EHtoGFNeCtZP1OVZ1IHrpZZzDaEjQGg1lUJqU= github.com/lxzan/gws v1.8.5/go.mod h1:FcGeRMB7HwGuTvMLR24ku0Zx0p6RXqeKASeMc4VYgi4= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= @@ -163,8 +175,6 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= -github.com/microsoft/go-mssqldb v0.17.0 h1:Fto83dMZPnYv1Zwx5vHHxpNraeEaUlQ/hhHLgZiaenE= -github.com/microsoft/go-mssqldb v0.17.0/go.mod h1:OkoNGhGEs8EZqchVTtochlXruEhEOaO4S0d2sB5aeGQ= github.com/microsoft/go-mssqldb v1.6.0 h1:mM3gYdVwEPFrlg/Dvr2DNVEgYFG7L42l+dGc67NNNpc= github.com/microsoft/go-mssqldb v1.6.0/go.mod h1:00mDtPbeQCRGC1HwOOR5K/gr30P1NcEG0vx6Kbv2aJU= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -180,6 +190,7 @@ github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaR github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -194,9 +205,8 @@ github.com/redis/go-redis/v9 v9.6.1/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJ github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20230126093431-47fa9a501578 h1:VstopitMQi3hZP0fzvnsLmzXZdQGc4bEcgu24cp+d4M= github.com/remyoudompheng/bigfft v0.0.0-20230126093431-47fa9a501578/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= @@ -337,14 +347,10 @@ gorm.io/datatypes v1.2.1/go.mod h1:hYK6OTb/1x+m96PgoZZq10UXJ6RvEBb9kRDQ2yyhzGs= gorm.io/driver/mysql v1.5.6/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM= gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo= gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM= -gorm.io/driver/postgres v1.5.0 h1:u2FXTy14l45qc3UeCJ7QaAXZmZfDDv0YrthvmRq1l0U= -gorm.io/driver/postgres v1.5.0/go.mod h1:FUZXzO+5Uqg5zzwzv4KK49R8lvGIyscBOqYrtI1Ce9A= gorm.io/driver/postgres v1.5.7 h1:8ptbNJTDbEmhdr62uReG5BGkdQyeasu/FZHxI0IMGnM= gorm.io/driver/postgres v1.5.7/go.mod h1:3e019WlBaYI5o5LIdNV+LyxCMNtLOQETBXL2h4chKpA= gorm.io/driver/sqlite v1.5.0 h1:zKYbzRCpBrT1bNijRnxLDJWPjVfImGEn0lSnUY5gZ+c= gorm.io/driver/sqlite v1.5.0/go.mod h1:kDMDfntV9u/vuMmz8APHtHF0b4nyBB7sfCieC6G8k8I= -gorm.io/driver/sqlserver v1.4.1 h1:t4r4r6Jam5E6ejqP7N82qAJIJAht27EGT41HyPfXRw0= -gorm.io/driver/sqlserver v1.4.1/go.mod h1:DJ4P+MeZbc5rvY58PnmN1Lnyvb5gw5NPzGshHDnJLig= gorm.io/driver/sqlserver v1.5.3 h1:rjupPS4PVw+rjJkfvr8jn2lJ8BMhT4UW5FwuJY0P3Z0= gorm.io/driver/sqlserver v1.5.3/go.mod h1:B+CZ0/7oFJ6tAlefsKoyxdgDCXJKSgwS2bMOQZT0I00= gorm.io/gen v0.3.26 h1:sFf1j7vNStimPRRAtH4zz5NiHM+1dr6eA9aaRdplyhY= diff --git a/main.go b/main.go index e568bd8..871ce14 100644 --- a/main.go +++ b/main.go @@ -8,6 +8,7 @@ import ( ) func main() { + // 初始化配置 core.InitConfig() // 读取配置文件 core.InitLogger() // 初始化日志 diff --git a/middleware/logger_date.go b/middleware/logger_date.go new file mode 100644 index 0000000..7c33fe1 --- /dev/null +++ b/middleware/logger_date.go @@ -0,0 +1,157 @@ +package middleware + +import ( + "bytes" + "fmt" + "io" + "os" + "path/filepath" + "schisandra-cloud-album/global" + "strings" + "time" + + "github.com/sirupsen/logrus" +) + +var ( + ccRed = 1 + ccYellow = 3 + ccBlue = 4 + ccCyan = 6 + ccGray = 7 +) + +type LogConsoleFormatter struct{} + +func (s *LogConsoleFormatter) Format(entry *logrus.Entry) ([]byte, error) { + timestamp := time.Now().Local().Format("2006-01-02 15:04:05") + var color int + switch entry.Level { + + case logrus.ErrorLevel: + color = ccRed + case logrus.WarnLevel: + color = ccYellow + case logrus.InfoLevel: + color = ccBlue + case logrus.DebugLevel: + color = ccCyan + default: + color = ccGray + } + // 设置 buffer 缓冲区 + var b *bytes.Buffer + if entry.Buffer == nil { + b = &bytes.Buffer{} + } else { + b = entry.Buffer + } + fileVal := fmt.Sprintf("%s:%d", filepath.Base(entry.Caller.File), entry.Caller.Line) + fmt.Fprintf(b, "[%s] \033[3%dm[%s]\033[0m [%s] %s %s\n", global.CONFIG.Logger.Prefix, color, entry.Level, timestamp, fileVal, entry.Message) + return b.Bytes(), nil +} + +type LogFileFormatter struct{} + +func (s *LogFileFormatter) Format(entry *logrus.Entry) ([]byte, error) { + timestamp := time.Now().Local().Format("2006-01-02 15:04:05") + var file string + var length int + if entry.Caller != nil { + file = filepath.Base(entry.Caller.File) + length = entry.Caller.Line + } + msg := fmt.Sprintf("[%s] %s [%s:%d] %s\n", strings.ToUpper(entry.Level.String()), timestamp, file, length, entry.Message) + return []byte(msg), nil +} + +type ConsoleHook struct { + formatter logrus.Formatter +} + +func (hook *ConsoleHook) Levels() []logrus.Level { + return logrus.AllLevels +} +func (hook *ConsoleHook) Fire(entry *logrus.Entry) error { + originalFormatter := entry.Logger.Formatter + entry.Logger.Formatter = hook.formatter + defer func() { entry.Logger.Formatter = originalFormatter }() + line, err := entry.Logger.Formatter.Format(entry) + if err != nil { + return err + } + _, err = os.Stdout.Write(line) + return err +} + +type FileHook struct { + formatter logrus.Formatter + file *os.File +} + +func (hook *FileHook) Levels() []logrus.Level { + return logrus.AllLevels +} + +func (hook *FileHook) Fire(entry *logrus.Entry) error { + originalFormatter := entry.Logger.Formatter + entry.Logger.Formatter = hook.formatter + defer func() { entry.Logger.Formatter = originalFormatter }() + line, err := entry.Logger.Formatter.Format(entry) + if err != nil { + return err + } + _, err = hook.file.Write(line) + return err +} + +type DateLogConfig struct { + Date string + Path string + Name string +} + +func NewDateLog(d *DateLogConfig) *DateLogConfig { + return &DateLogConfig{ + Date: d.Date, + Path: d.Path, + Name: d.Name, + } +} + +func (d *DateLogConfig) Init() *logrus.Logger { + // 实例化 logrus + log := logrus.New() + // 设置是否输出文件名和行号信息 + log.SetReportCaller(global.CONFIG.Logger.ShowLine) + // 将 logrus 的默认输出丢弃,确保日志只通过 hooks 输出 + log.SetOutput(io.Discard) + + // 控制台输出的 hook + consoleHook := &ConsoleHook{ + formatter: &LogConsoleFormatter{}, + } + // 添加控制台输出的 hook + log.AddHook(consoleHook) + + // 文件路径 + filename := fmt.Sprintf("%s/%s/%s.log", d.Path, d.Date, d.Name) + // 创建目录 + if err := os.MkdirAll(fmt.Sprintf("%s/%s", d.Path, d.Date), os.ModePerm); err != nil { + log.Fatal(err) + } + // 打开文件,如果文件不存在,则创建文件 + file, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600) + if err != nil { + log.Fatal(err) + } + + // 文件输出的 hook + fileHook := &FileHook{ + formatter: &LogFileFormatter{}, + file: file, + } + // 添加文件输出的 hook + log.AddHook(fileHook) + return log +} diff --git a/middleware/logger_level.go b/middleware/logger_level.go new file mode 100644 index 0000000..b54c61e --- /dev/null +++ b/middleware/logger_level.go @@ -0,0 +1,116 @@ +package middleware + +import ( + "fmt" + "io" + "os" + "path/filepath" + "strings" + "time" + + "github.com/sirupsen/logrus" +) + +const ( + allLog = "all" + errLog = "err" + warnLog = "warn" + infoLog = "info" + debugLog = "debug" +) + +type LevelFormatter struct{} + +func (l *LevelFormatter) Format(entry *logrus.Entry) ([]byte, error) { + timestamp := time.Now().Local().Format("2006-01-02 15:04:05") + var file string + var len int + if entry.Caller != nil { + file = filepath.Base(entry.Caller.File) + len = entry.Caller.Line + } + msg := fmt.Sprintf("[%s] %s [%s:%d] %s\n", strings.ToUpper(entry.Level.String()), timestamp, file, len, entry.Message) + return []byte(msg), nil +} + +type LevelConfig struct { + Date string + Name string + Path string +} + +func NewLevelLog(d *LevelConfig) *LevelConfig { + return &LevelConfig{ + Date: d.Date, + Path: d.Path, + Name: d.Name, + } +} + +func (l *LevelConfig) Init() *logrus.Logger { + log := logrus.New() + log.SetReportCaller(true) + log.SetOutput(io.Discard) + + err := os.MkdirAll(fmt.Sprintf("%s/%s", l.Path, l.Date), os.ModePerm) + if err != nil { + log.Fatal(err) + } + + allFile, _ := os.OpenFile(fmt.Sprintf("%s/%s/%s-%s.log", l.Path, l.Date, l.Name, allLog), os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0600) + errFile, _ := os.OpenFile(fmt.Sprintf("%s/%s/%s-%s.log", l.Path, l.Date, l.Name, errLog), os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0600) + warnFile, _ := os.OpenFile(fmt.Sprintf("%s/%s/%s-%s.log", l.Path, l.Date, l.Name, warnLog), os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0600) + infoFile, _ := os.OpenFile(fmt.Sprintf("%s/%s/%s-%s.log", l.Path, l.Date, l.Name, infoLog), os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0600) + debugFile, _ := os.OpenFile(fmt.Sprintf("%s/%s/%s-%s.log", l.Path, l.Date, l.Name, debugLog), os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0600) + + fileHook := &LevelHook{ + formatter: &LevelFormatter{}, + file: allFile, + errFile: errFile, + warnFile: warnFile, + infoFile: infoFile, + debugFile: debugFile, + } + + log.AddHook(fileHook) + return log +} + +type LevelHook struct { + formatter logrus.Formatter + file *os.File + errFile *os.File + warnFile *os.File + infoFile *os.File + debugFile *os.File +} + +func (l *LevelHook) Levels() []logrus.Level { + return logrus.AllLevels +} + +func (l *LevelHook) Fire(entry *logrus.Entry) error { + originalFormatter := entry.Logger.Formatter + entry.Logger.Formatter = l.formatter + defer func() { entry.Logger.Formatter = originalFormatter }() + line, err := entry.Logger.Formatter.Format(entry) + if err != nil { + return err + } + + _, err = l.file.Write(line) + + switch entry.Level { + case logrus.ErrorLevel: + _, err = l.errFile.Write(line) + case logrus.WarnLevel: + _, err = l.warnFile.Write(line) + case logrus.InfoLevel: + _, err = l.infoFile.Write(line) + case logrus.DebugLevel: + _, err = l.debugFile.Write(line) + default: + panic("unhandled default case") + } + return err +} diff --git a/model/sca_auth_role_permission.go b/model/sca_auth_role_permission.go deleted file mode 100644 index 534b16a..0000000 --- a/model/sca_auth_role_permission.go +++ /dev/null @@ -1,24 +0,0 @@ -package model - -import ( - "time" -) - -const TableNameScaAuthRolePermission = "sca_auth_role_permission" - -// ScaAuthRolePermission 角色-权限映射表 -type ScaAuthRolePermission struct { - ID int64 `gorm:"column:id;type:bigint(20);primaryKey;comment:主键ID" json:"id"` // 主键ID - RoleID int64 `gorm:"column:role_id;type:bigint(20);not null;comment:角色ID" json:"role_id"` // 角色ID - PermissionID int64 `gorm:"column:permission_id;type:bigint(20);not null;comment:权限ID" json:"permission_id"` // 权限ID - CreatedBy *string `gorm:"column:created_by;type:varchar(32);comment:创建人" json:"created_by"` // 创建人 - CreatedTime *time.Time `gorm:"column:created_time;type:datetime;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_time"` // 创建时间 - UpdateBy *string `gorm:"column:update_by;type:varchar(32);comment:更新人" json:"update_by"` // 更新人 - UpdateTime *time.Time `gorm:"column:update_time;type:datetime;default:CURRENT_TIMESTAMP;comment:更新时间" json:"update_time"` // 更新时间 - Deleted *int64 `gorm:"column:deleted;type:int(11);comment:是否删除" json:"deleted"` // 是否删除 -} - -// TableName ScaAuthRolePermission's table name -func (*ScaAuthRolePermission) TableName() string { - return TableNameScaAuthRolePermission -} diff --git a/model/sca_auth_user_role.go b/model/sca_auth_user_role.go deleted file mode 100644 index aab2082..0000000 --- a/model/sca_auth_user_role.go +++ /dev/null @@ -1,24 +0,0 @@ -package model - -import ( - "time" -) - -const TableNameScaAuthUserRole = "sca_auth_user_role" - -// ScaAuthUserRole 用户-角色映射表 -type ScaAuthUserRole struct { - ID int64 `gorm:"column:id;type:bigint(20);primaryKey;comment:主键ID" json:"id"` // 主键ID - UserID string `gorm:"column:user_id;type:varchar(255);not null;comment:用户ID" json:"user_id"` // 用户ID - RoleID int64 `gorm:"column:role_id;type:bigint(20);not null;comment:角色ID" json:"role_id"` // 角色ID - CreatedBy *string `gorm:"column:created_by;type:varchar(32);comment:创建人" json:"created_by"` // 创建人 - CreatedTime *time.Time `gorm:"column:created_time;type:datetime;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_time"` // 创建时间 - UpdateBy *string `gorm:"column:update_by;type:varchar(32);comment:更新人" json:"update_by"` // 更新人 - UpdateTime *time.Time `gorm:"column:update_time;type:datetime;default:CURRENT_TIMESTAMP;comment:更新时间" json:"update_time"` // 更新时间 - Deleted *int64 `gorm:"column:deleted;type:int(11);comment:是否删除" json:"deleted"` // 是否删除 -} - -// TableName ScaAuthUserRole's table name -func (*ScaAuthUserRole) TableName() string { - return TableNameScaAuthUserRole -} diff --git a/model/sca_auth_user_social.go b/model/sca_auth_user_social.go index 5df4943..c33c0a1 100644 --- a/model/sca_auth_user_social.go +++ b/model/sca_auth_user_social.go @@ -9,7 +9,7 @@ const TableNameScaAuthUserSocial = "sca_auth_user_social" // ScaAuthUserSocial 社会用户信息表 type ScaAuthUserSocial struct { ID int64 `gorm:"column:id;type:bigint(20);primaryKey;comment:主键ID" json:"id"` // 主键ID - UserID *int64 `gorm:"column:user_id;type:bigint(20);not null;comment:用户ID" json:"user_id"` // 用户ID + UserID *string `gorm:"column:user_id;type:varchar(255);not null;comment:用户ID" json:"user_id"` // 用户ID UUID *string `gorm:"column:uuid;type:varchar(255);comment:第三方系统的唯一ID" json:"uuid"` // 第三方系统的唯一ID Source *string `gorm:"column:source;type:varchar(255);comment:第三方用户来源" json:"source"` // 第三方用户来源 AccessToken *string `gorm:"column:access_token;type:varchar(255);comment:用户的授权令牌" json:"access_token"` // 用户的授权令牌 diff --git a/router/modules/oauth_router.go b/router/modules/oauth_router.go index a5534b4..7ffc65f 100644 --- a/router/modules/oauth_router.go +++ b/router/modules/oauth_router.go @@ -14,8 +14,8 @@ func OauthRouter(router *gin.RouterGroup) { { wechatRouter.GET("/generate_client_id", oauth.GenerateClientId) wechatRouter.GET("/get_temp_qrcode", oauth.GetTempQrCode) - wechatRouter.GET("/callback", oauth.CallbackVerify) - //wechatRouter.POST("/callback", oauth.CallbackNotify) + //wechatRouter.GET("/callback", oauth.CallbackVerify) + wechatRouter.POST("/callback", oauth.CallbackNotify) } githubRouter := group.Group("/github") { diff --git a/router/modules/role_router.go b/router/modules/role_router.go new file mode 100644 index 0000000..e158b52 --- /dev/null +++ b/router/modules/role_router.go @@ -0,0 +1,16 @@ +package modules + +import ( + "github.com/gin-gonic/gin" + "schisandra-cloud-album/api" + "schisandra-cloud-album/middleware" +) + +var roleApi = api.Api.RoleApi + +func RoleRouter(router *gin.RouterGroup) { + group := router.Group("/auth") + group.Use(middleware.JWTAuthMiddleware()) + group.POST("/role/create", roleApi.CreateRole) + group.POST("/role/add_role_to_user", roleApi.AddRoleToUser) +} diff --git a/router/router.go b/router/router.go index 92deab2..7535445 100644 --- a/router/router.go +++ b/router/router.go @@ -12,14 +12,21 @@ import ( func InitRouter() *gin.Engine { gin.SetMode(global.CONFIG.System.Env) router := gin.Default() - err := router.SetTrustedProxies([]string{"127.0.0.1"}) + err := router.SetTrustedProxies([]string{global.CONFIG.System.Ip}) if err != nil { global.LOG.Error(err) return nil } + router.Use(middleware.RateLimitMiddleware(time.Millisecond*100, 20)) // 限流中间件 publicGroup := router.Group("api") // 跨域设置 - publicGroup.Use(cors.Default()).Use(middleware.RateLimitMiddleware(time.Millisecond*100, 20)) + publicGroup.Use(cors.New(cors.Config{ + AllowOrigins: []string{global.CONFIG.System.Web}, + AllowMethods: []string{"GET", "POST", "PUT", "PATCH", "DELETE", "HEAD"}, + AllowHeaders: []string{"Origin", "Content-Length", "Content-Type", "Authorization", "X-CSRF-Token", "Accept-Language"}, + AllowCredentials: true, + MaxAge: 12 * time.Hour, + })) // 国际化设置 publicGroup.Use(middleware.I18n()) @@ -29,5 +36,6 @@ func InitRouter() *gin.Engine { modules.SmsRouter(publicGroup) // 注册短信验证码路由 modules.OauthRouter(publicGroup) // 注册oauth路由 modules.WebsocketRouter(publicGroup) // 注册websocket路由 + modules.RoleRouter(publicGroup) // 注册角色路由 return router } diff --git a/service/permission_service/permission_service.go b/service/permission_service/permission_service.go index 8bfbee9..097e294 100644 --- a/service/permission_service/permission_service.go +++ b/service/permission_service/permission_service.go @@ -13,3 +13,11 @@ func (PermissionService) GetPermissionsByIds(ids []int64) ([]model.ScaAuthPermis } return permissions, nil } + +// CreatePermissions 批量创建权限 +func (PermissionService) CreatePermissions(permissions []model.ScaAuthPermission) error { + if err := global.DB.Model(&model.ScaAuthPermission{}).CreateInBatches(&permissions, len(permissions)).Error; err != nil { + return err + } + return nil +} diff --git a/service/role_permission_service/role_permission.go b/service/role_permission_service/role_permission.go deleted file mode 100644 index 697fe57..0000000 --- a/service/role_permission_service/role_permission.go +++ /dev/null @@ -1,3 +0,0 @@ -package role_permission_service - -type RolePermissionService struct{} diff --git a/service/role_permission_service/role_permission_service.go b/service/role_permission_service/role_permission_service.go deleted file mode 100644 index e99d277..0000000 --- a/service/role_permission_service/role_permission_service.go +++ /dev/null @@ -1,17 +0,0 @@ -package role_permission_service - -import ( - "schisandra-cloud-album/global" - "schisandra-cloud-album/model" -) - -// QueryPermissionIdsByRoleId 通过角色ID列表查询权限ID列表 -func (RolePermissionService) QueryPermissionIdsByRoleId(roleIds []*int64) []int64 { - var permissionIds []int64 - rolePermission := model.ScaAuthRolePermission{} - if err := global.DB.Model(&rolePermission).Where("role_id IN ?", roleIds).Pluck("permission_id", &permissionIds).Error; err != nil { - global.LOG.Error(err) - return nil - } - return permissionIds -} diff --git a/service/role_service/role_service.go b/service/role_service/role_service.go index 5c041c9..749d7f7 100644 --- a/service/role_service/role_service.go +++ b/service/role_service/role_service.go @@ -13,3 +13,11 @@ func (RoleService) GetRoleListByIds(id []*int64) ([]model.ScaAuthRole, error) { } return roles, nil } + +// AddRole 新增角色 +func (RoleService) AddRole(role model.ScaAuthRole) error { + if err := global.DB.Create(&role).Error; err != nil { + return err + } + return nil +} diff --git a/service/service.go b/service/service.go index 298d737..ad3942a 100644 --- a/service/service.go +++ b/service/service.go @@ -2,21 +2,17 @@ package service import ( "schisandra-cloud-album/service/permission_service" - "schisandra-cloud-album/service/role_permission_service" "schisandra-cloud-album/service/role_service" - "schisandra-cloud-album/service/user_role_service" "schisandra-cloud-album/service/user_service" "schisandra-cloud-album/service/user_social_service" ) // Services 统一导出的service type Services struct { - UserService user_service.UserService - RoleService role_service.RoleService - UserRoleService user_role_service.UserRoleService - RolePermissionService role_permission_service.RolePermissionService - PermissionService permission_service.PermissionService - UserSocialService user_social_service.UserSocialService + UserService user_service.UserService + RoleService role_service.RoleService + PermissionService permission_service.PermissionService + UserSocialService user_social_service.UserSocialService } // Service new函数实例化,实例化完成后会返回结构体地指针类型 diff --git a/service/user_role_service/user_role.go b/service/user_role_service/user_role.go deleted file mode 100644 index 74c9ce8..0000000 --- a/service/user_role_service/user_role.go +++ /dev/null @@ -1,3 +0,0 @@ -package user_role_service - -type UserRoleService struct{} diff --git a/service/user_role_service/user_role_service.go b/service/user_role_service/user_role_service.go deleted file mode 100644 index 96284a8..0000000 --- a/service/user_role_service/user_role_service.go +++ /dev/null @@ -1,32 +0,0 @@ -package user_role_service - -import ( - "schisandra-cloud-album/global" - "schisandra-cloud-album/model" -) - -// GetUserRoleIdsByUserId 通过用户ID获取用户角色ID列表 -func (UserRoleService) GetUserRoleIdsByUserId(userId int64) ([]*int64, error) { - var roleIds []*int64 - if err := global.DB.Table("sca_auth_user_role").Where("user_id = ? and deleted = 0 ", userId).Pluck("role_id", &roleIds).Error; err != nil { - return nil, err - } - return roleIds, nil -} - -// AddUserRole 新增用户角色 -func (UserRoleService) AddUserRole(userRole model.ScaAuthUserRole) error { - if err := global.DB.Create(&userRole).Error; err != nil { - return err - } - return nil -} - -// GetAllUserRoles 返回所有用户的角色列表 -func (UserRoleService) GetAllUserRoles() ([]*model.ScaAuthUserRole, error) { - var userRoles []*model.ScaAuthUserRole - if err := global.DB.Table("sca_auth_user_role").Where("deleted = 0").Find(&userRoles).Error; err != nil { - return nil, err - } - return userRoles, nil -} diff --git a/utils/jwt.go b/utils/jwt.go index 18c8150..b0607ae 100644 --- a/utils/jwt.go +++ b/utils/jwt.go @@ -9,14 +9,12 @@ import ( ) type RefreshJWTPayload struct { - UserID *string `json:"user_id"` - RoleID []*int64 `json:"role_id"` - Type *string `json:"type" default:"refresh"` + UserID *string `json:"user_id"` + Type *string `json:"type" default:"refresh"` } type AccessJWTPayload struct { - UserID *string `json:"user_id"` - RoleID []*int64 `json:"role_id"` - Type *string `json:"type" default:"access"` + UserID *string `json:"user_id"` + Type *string `json:"type" default:"access"` } type AccessJWTClaims struct { AccessJWTPayload