⚡ update qq/gitee/github oauth2 login
This commit is contained in:
14
api/api.go
14
api/api.go
@@ -3,6 +3,8 @@ package api
|
|||||||
import (
|
import (
|
||||||
"schisandra-cloud-album/api/captcha_api"
|
"schisandra-cloud-album/api/captcha_api"
|
||||||
"schisandra-cloud-album/api/oauth_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/sms_api"
|
||||||
"schisandra-cloud-album/api/user_api"
|
"schisandra-cloud-album/api/user_api"
|
||||||
"schisandra-cloud-album/api/websocket_api"
|
"schisandra-cloud-album/api/websocket_api"
|
||||||
@@ -10,11 +12,13 @@ import (
|
|||||||
|
|
||||||
// Apis 统一导出的api
|
// Apis 统一导出的api
|
||||||
type Apis struct {
|
type Apis struct {
|
||||||
UserApi user_api.UserAPI
|
UserApi user_api.UserAPI
|
||||||
CaptchaApi captcha_api.CaptchaAPI
|
CaptchaApi captcha_api.CaptchaAPI
|
||||||
SmsApi sms_api.SmsAPI
|
SmsApi sms_api.SmsAPI
|
||||||
OAuthApi oauth_api.OAuthAPI
|
OAuthApi oauth_api.OAuthAPI
|
||||||
WebsocketApi websocket_api.WebsocketAPI
|
WebsocketApi websocket_api.WebsocketAPI
|
||||||
|
RoleApi role_api.RoleAPI
|
||||||
|
PermissionApi permission_api.PermissionAPI
|
||||||
}
|
}
|
||||||
|
|
||||||
// Api new函数实例化,实例化完成后会返回结构体地指针类型
|
// Api new函数实例化,实例化完成后会返回结构体地指针类型
|
||||||
|
@@ -142,100 +142,112 @@ func (OAuthAPI) GiteeCallback(c *gin.Context) {
|
|||||||
result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c)
|
result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 通过 code, 获取 token
|
|
||||||
var tokenAuthUrl = GetGiteeTokenAuthUrl(code)
|
|
||||||
var token *Token
|
|
||||||
if token, err = GetGiteeToken(tokenAuthUrl); err != nil {
|
|
||||||
global.LOG.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 通过token,获取用户信息
|
// 异步获取 token
|
||||||
var userInfo map[string]interface{}
|
var tokenChan = make(chan *Token)
|
||||||
if userInfo, err = GetGiteeUserInfo(token); err != nil {
|
var errChan = make(chan error)
|
||||||
global.LOG.Error(err)
|
go func() {
|
||||||
return
|
var tokenAuthUrl = GetGiteeTokenAuthUrl(code)
|
||||||
}
|
token, err := GetGiteeToken(tokenAuthUrl)
|
||||||
|
if err != nil {
|
||||||
|
errChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tokenChan <- token
|
||||||
|
}()
|
||||||
|
|
||||||
userInfoBytes, err := json.Marshal(userInfo)
|
// 异步获取用户信息
|
||||||
if err != nil {
|
var userInfoChan = make(chan map[string]interface{})
|
||||||
global.LOG.Error(err)
|
go func() {
|
||||||
return
|
token := <-tokenChan
|
||||||
}
|
if token == nil {
|
||||||
var giteeUser GiteeUser
|
errChan <- errors.New("failed to get token")
|
||||||
err = json.Unmarshal(userInfoBytes, &giteeUser)
|
return
|
||||||
if err != nil {
|
}
|
||||||
global.LOG.Error(err)
|
userInfo, err := GetGiteeUserInfo(token)
|
||||||
return
|
if err != nil {
|
||||||
}
|
errChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
userInfoChan <- userInfo
|
||||||
|
}()
|
||||||
|
|
||||||
Id := strconv.Itoa(giteeUser.ID)
|
// 等待结果
|
||||||
userSocial, err := userSocialService.QueryUserSocialByUUID(Id, enum.OAuthSourceGitee)
|
select {
|
||||||
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
|
case err = <-errChan:
|
||||||
// 第一次登录,创建用户
|
global.LOG.Error(err)
|
||||||
uid := idgen.NextId()
|
return
|
||||||
uidStr := strconv.FormatInt(uid, 10)
|
case userInfo := <-userInfoChan:
|
||||||
user := model.ScaAuthUser{
|
userInfoBytes, err := json.Marshal(userInfo)
|
||||||
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 {
|
if err != nil {
|
||||||
global.LOG.Error(err)
|
global.LOG.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
gitee := enum.OAuthSourceGitee
|
var giteeUser GiteeUser
|
||||||
userSocial = model.ScaAuthUserSocial{
|
err = json.Unmarshal(userInfoBytes, &giteeUser)
|
||||||
UserID: &addUser.ID,
|
|
||||||
UUID: &Id,
|
|
||||||
Source: &gitee,
|
|
||||||
}
|
|
||||||
err = userSocialService.AddUserSocial(userSocial)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.LOG.Error(err)
|
global.LOG.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
userRole := model.ScaAuthUserRole{
|
|
||||||
UserID: uidStr,
|
Id := strconv.Itoa(giteeUser.ID)
|
||||||
RoleID: enum.User,
|
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)
|
return
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
@@ -148,99 +148,116 @@ func (OAuthAPI) Callback(c *gin.Context) {
|
|||||||
result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c)
|
result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 通过 code, 获取 token
|
|
||||||
var tokenAuthUrl = GetTokenAuthUrl(code)
|
|
||||||
var token *Token
|
|
||||||
if token, err = GetToken(tokenAuthUrl); err != nil {
|
|
||||||
global.LOG.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 通过token,获取用户信息
|
// 使用channel来接收异步操作的结果
|
||||||
var userInfo map[string]interface{}
|
tokenChan := make(chan *Token)
|
||||||
if userInfo, err = GetUserInfo(token); err != nil {
|
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)
|
global.LOG.Error(err)
|
||||||
return
|
return
|
||||||
}
|
case userInfo := <-userInfoChan:
|
||||||
//json 转 struct
|
if userInfo == nil {
|
||||||
userInfoBytes, err := json.Marshal(userInfo)
|
global.LOG.Error(<-errChan)
|
||||||
if err != nil {
|
return
|
||||||
global.LOG.Error(err)
|
}
|
||||||
|
// 继续处理用户信息
|
||||||
|
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
|
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
|
|
||||||
}
|
}
|
||||||
|
@@ -2,10 +2,13 @@ package oauth_api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"net/http"
|
||||||
"schisandra-cloud-album/api/user_api/dto"
|
"schisandra-cloud-album/api/user_api/dto"
|
||||||
"schisandra-cloud-album/common/constant"
|
"schisandra-cloud-album/common/constant"
|
||||||
"schisandra-cloud-album/common/redis"
|
"schisandra-cloud-album/common/redis"
|
||||||
"schisandra-cloud-album/model"
|
"schisandra-cloud-album/global"
|
||||||
"schisandra-cloud-album/service"
|
"schisandra-cloud-album/service"
|
||||||
"schisandra-cloud-album/utils"
|
"schisandra-cloud-album/utils"
|
||||||
"time"
|
"time"
|
||||||
@@ -14,11 +17,7 @@ import (
|
|||||||
type OAuthAPI struct{}
|
type OAuthAPI struct{}
|
||||||
|
|
||||||
var userService = service.Service.UserService
|
var userService = service.Service.UserService
|
||||||
var userRoleService = service.Service.UserRoleService
|
|
||||||
var userSocialService = service.Service.UserSocialService
|
var userSocialService = service.Service.UserSocialService
|
||||||
var rolePermissionService = service.Service.RolePermissionService
|
|
||||||
var permissionServiceService = service.Service.PermissionService
|
|
||||||
var roleService = service.Service.RoleService
|
|
||||||
|
|
||||||
type Token struct {
|
type Token struct {
|
||||||
AccessToken string `json:"access_token"`
|
AccessToken string `json:"access_token"`
|
||||||
@@ -31,50 +30,82 @@ var script = `
|
|||||||
</script>
|
</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 处理用户登录
|
// HandelUserLogin 处理用户登录
|
||||||
func HandelUserLogin(user model.ScaAuthUser) (bool, map[string]interface{}) {
|
func HandelUserLogin(userId string) (bool, map[string]interface{}) {
|
||||||
ids, err := userRoleService.GetUserRoleIdsByUserId(user.ID)
|
// 使用goroutine生成accessToken
|
||||||
if err != nil {
|
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
|
return false, nil
|
||||||
}
|
}
|
||||||
permissionIds := rolePermissionService.QueryPermissionIdsByRoleId(ids)
|
select {
|
||||||
permissions, err := permissionServiceService.GetPermissionsByIds(permissionIds)
|
case refreshToken = <-refreshTokenChan:
|
||||||
if err != nil {
|
case expiresAt = <-expiresAtChan:
|
||||||
return false, nil
|
|
||||||
}
|
}
|
||||||
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{
|
data := dto.ResponseData{
|
||||||
AccessToken: accessToken,
|
AccessToken: accessToken,
|
||||||
RefreshToken: refreshToken,
|
RefreshToken: refreshToken,
|
||||||
ExpiresAt: expiresAt,
|
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
|
return false, nil
|
||||||
}
|
}
|
||||||
responseData := map[string]interface{}{
|
responseData := map[string]interface{}{
|
||||||
|
@@ -173,23 +173,61 @@ func (OAuthAPI) QQCallback(c *gin.Context) {
|
|||||||
result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c)
|
result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 通过 code, 获取 token
|
// 通过 code, 获取 token
|
||||||
var tokenAuthUrl = GetQQTokenAuthUrl(code)
|
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
|
var token *QQToken
|
||||||
if token, err = GetQQToken(tokenAuthUrl); err != nil {
|
select {
|
||||||
|
case token = <-tokenChan:
|
||||||
|
case err = <-errChan:
|
||||||
global.LOG.Error(err)
|
global.LOG.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 通过 token,获取 openid
|
// 通过 token,获取 openid
|
||||||
authQQme, err := GetQQUserOpenID(token)
|
openIDChan := make(chan *AuthQQme)
|
||||||
if err != nil {
|
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)
|
global.LOG.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 通过token,获取用户信息
|
// 通过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{}
|
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)
|
global.LOG.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -205,8 +243,20 @@ func (OAuthAPI) QQCallback(c *gin.Context) {
|
|||||||
global.LOG.Error(err)
|
global.LOG.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
userSocial, err := userSocialService.QueryUserSocialByOpenID(authQQme.OpenID, enum.OAuthSourceQQ)
|
userSocial, err := userSocialService.QueryUserSocialByOpenID(authQQme.OpenID, enum.OAuthSourceQQ)
|
||||||
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
|
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()
|
uid := idgen.NextId()
|
||||||
uidStr := strconv.FormatInt(uid, 10)
|
uidStr := strconv.FormatInt(uid, 10)
|
||||||
@@ -221,59 +271,36 @@ func (OAuthAPI) QQCallback(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
addUser, err := userService.AddUser(user)
|
addUser, err := userService.AddUser(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
global.LOG.Error(err)
|
global.LOG.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
qq := enum.OAuthSourceQQ
|
qq := enum.OAuthSourceQQ
|
||||||
userSocial = model.ScaAuthUserSocial{
|
userSocial = model.ScaAuthUserSocial{
|
||||||
UserID: &addUser.ID,
|
UserID: &uidStr,
|
||||||
OpenID: &authQQme.OpenID,
|
OpenID: &authQQme.OpenID,
|
||||||
Source: &qq,
|
Source: &qq,
|
||||||
}
|
}
|
||||||
err = userSocialService.AddUserSocial(userSocial)
|
err = userSocialService.AddUserSocial(userSocial)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
global.LOG.Error(err)
|
global.LOG.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
userRole := model.ScaAuthUserRole{
|
_, err = global.Casbin.AddRoleForUser(uidStr, enum.User)
|
||||||
UserID: uidStr,
|
|
||||||
RoleID: enum.User,
|
|
||||||
}
|
|
||||||
err = userRoleService.AddUserRole(userRole)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
global.LOG.Error(err)
|
global.LOG.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
res, data := HandelUserLogin(addUser)
|
if err := tx.Commit().Error; err != nil {
|
||||||
if !res {
|
tx.Rollback()
|
||||||
return
|
|
||||||
}
|
|
||||||
tokenData, err := json.Marshal(data)
|
|
||||||
if err != nil {
|
|
||||||
global.LOG.Error(err)
|
global.LOG.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
formattedScript := fmt.Sprintf(script, tokenData, global.CONFIG.System.Web)
|
HandleLoginResponse(c, *addUser.UID)
|
||||||
c.Data(http.StatusOK, "text/html; charset=utf-8", []byte(formattedScript))
|
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
user, err := userService.QueryUserById(userSocial.UserID)
|
HandleLoginResponse(c, *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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -26,9 +26,12 @@ import (
|
|||||||
"schisandra-cloud-album/utils"
|
"schisandra-cloud-album/utils"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var mu sync.Mutex
|
||||||
|
|
||||||
// GenerateClientId 生成客户端ID
|
// GenerateClientId 生成客户端ID
|
||||||
// @Summary 生成客户端ID
|
// @Summary 生成客户端ID
|
||||||
// @Description 生成客户端ID
|
// @Description 生成客户端ID
|
||||||
@@ -44,6 +47,9 @@ func (OAuthAPI) GenerateClientId(c *gin.Context) {
|
|||||||
if ip == "" {
|
if ip == "" {
|
||||||
ip = c.ClientIP()
|
ip = c.ClientIP()
|
||||||
}
|
}
|
||||||
|
// 加锁
|
||||||
|
mu.Lock()
|
||||||
|
defer mu.Unlock()
|
||||||
|
|
||||||
// 从Redis获取客户端ID
|
// 从Redis获取客户端ID
|
||||||
clientId := redis.Get(constant.UserLoginClientRedisKey + ip).Val()
|
clientId := redis.Get(constant.UserLoginClientRedisKey + ip).Val()
|
||||||
@@ -70,10 +76,7 @@ func (OAuthAPI) GenerateClientId(c *gin.Context) {
|
|||||||
// @Router /api/oauth/callback_notify [POST]
|
// @Router /api/oauth/callback_notify [POST]
|
||||||
func (OAuthAPI) CallbackNotify(c *gin.Context) {
|
func (OAuthAPI) CallbackNotify(c *gin.Context) {
|
||||||
rs, err := global.Wechat.Server.Notify(c.Request, func(event contract.EventInterface) interface{} {
|
rs, err := global.Wechat.Server.Notify(c.Request, func(event contract.EventInterface) interface{} {
|
||||||
fmt.Dump("event", event)
|
|
||||||
|
|
||||||
switch event.GetMsgType() {
|
switch event.GetMsgType() {
|
||||||
|
|
||||||
case models2.CALLBACK_MSG_TYPE_EVENT:
|
case models2.CALLBACK_MSG_TYPE_EVENT:
|
||||||
switch event.GetEvent() {
|
switch event.GetEvent() {
|
||||||
case models.CALLBACK_EVENT_SUBSCRIBE:
|
case models.CALLBACK_EVENT_SUBSCRIBE:
|
||||||
@@ -122,7 +125,6 @@ func (OAuthAPI) CallbackNotify(c *gin.Context) {
|
|||||||
println(err.Error())
|
println(err.Error())
|
||||||
return "error"
|
return "error"
|
||||||
}
|
}
|
||||||
fmt.Dump(msg)
|
|
||||||
}
|
}
|
||||||
return messages.NewText("ok")
|
return messages.NewText("ok")
|
||||||
|
|
||||||
@@ -177,6 +179,7 @@ func (OAuthAPI) GetTempQrCode(c *gin.Context) {
|
|||||||
data := response.ResponseQRCodeCreate{}
|
data := response.ResponseQRCodeCreate{}
|
||||||
err := json.Unmarshal([]byte(qrcode), &data)
|
err := json.Unmarshal([]byte(qrcode), &data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
global.LOG.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
result.OK(ginI18n.MustGetMessage(c, "QRCodeGetSuccess"), data.Url, c)
|
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)
|
data, err := global.Wechat.QRCode.Temporary(c.Request.Context(), clientId, 30*24*3600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
global.LOG.Error(err)
|
||||||
result.FailWithMessage(ginI18n.MustGetMessage(c, "QRCodeGetFailed"), c)
|
result.FailWithMessage(ginI18n.MustGetMessage(c, "QRCodeGetFailed"), c)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
serializedData, err := json.Marshal(data)
|
serializedData, err := json.Marshal(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
global.LOG.Error(err)
|
||||||
result.FailWithMessage(ginI18n.MustGetMessage(c, "QRCodeGetFailed"), c)
|
result.FailWithMessage(ginI18n.MustGetMessage(c, "QRCodeGetFailed"), c)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
wrong := redis.Set(constant.UserLoginQrcodeRedisKey+ip+":"+clientId, serializedData, time.Hour*24*30).Err()
|
wrong := redis.Set(constant.UserLoginQrcodeRedisKey+ip+":"+clientId, serializedData, time.Hour*24*30).Err()
|
||||||
|
|
||||||
if wrong != nil {
|
if wrong != nil {
|
||||||
|
global.LOG.Error(wrong)
|
||||||
result.FailWithMessage(ginI18n.MustGetMessage(c, "QRCodeGetFailed"), c)
|
result.FailWithMessage(ginI18n.MustGetMessage(c, "QRCodeGetFailed"), c)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -208,45 +214,98 @@ func wechatLoginHandler(openId string, clientId string) bool {
|
|||||||
}
|
}
|
||||||
authUserSocial, err := userSocialService.QueryUserSocialByOpenID(openId, enum.OAuthSourceWechat)
|
authUserSocial, err := userSocialService.QueryUserSocialByOpenID(openId, enum.OAuthSourceWechat)
|
||||||
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
|
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
|
tx := global.DB.Begin()
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
uid := idgen.NextId()
|
uid := idgen.NextId()
|
||||||
uidStr := strconv.FormatInt(uid, 10)
|
uidStr := strconv.FormatInt(uid, 10)
|
||||||
createUser := model.ScaAuthUser{
|
createUser := model.ScaAuthUser{
|
||||||
UID: &uidStr,
|
UID: &uidStr,
|
||||||
Username: &openId,
|
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
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
wechat := enum.OAuthSourceWechat
|
wechat := enum.OAuthSourceWechat
|
||||||
userSocial := model.ScaAuthUserSocial{
|
userSocial := model.ScaAuthUserSocial{
|
||||||
UserID: &addUser.ID,
|
UserID: &uidStr,
|
||||||
OpenID: &openId,
|
OpenID: &openId,
|
||||||
Source: &wechat,
|
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
|
resChan := make(chan bool, 1)
|
||||||
}
|
go func() {
|
||||||
res := handelUserLogin(addUser, clientId)
|
res := handelUserLogin(*addUser.UID, clientId)
|
||||||
if !res {
|
resChan <- res
|
||||||
return false
|
}()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case res := <-resChan:
|
||||||
|
if !res {
|
||||||
|
tx.Rollback()
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
tx.Commit()
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
user, err := userService.QueryUserById(authUserSocial.UserID)
|
res := handelUserLogin(*authUserSocial.UserID, clientId)
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
res := handelUserLogin(user, clientId)
|
|
||||||
if !res {
|
if !res {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -255,70 +314,47 @@ func wechatLoginHandler(openId string, clientId string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handelUserLogin 处理用户登录
|
// handelUserLogin 处理用户登录
|
||||||
func handelUserLogin(user model.ScaAuthUser, clientId string) bool {
|
func handelUserLogin(userId string, clientId string) bool {
|
||||||
ids, err := userRoleService.GetUserRoleIdsByUserId(user.ID)
|
resultChan := make(chan bool, 1)
|
||||||
if err != nil {
|
|
||||||
return false
|
go func() {
|
||||||
}
|
accessToken, err := utils.GenerateAccessToken(utils.AccessJWTPayload{UserID: &userId})
|
||||||
permissionIds := rolePermissionService.QueryPermissionIdsByRoleId(ids)
|
if err != nil {
|
||||||
permissions, err := permissionServiceService.GetPermissionsByIds(permissionIds)
|
resultChan <- false
|
||||||
if err != nil {
|
return
|
||||||
return false
|
}
|
||||||
}
|
refreshToken, expiresAt := utils.GenerateRefreshToken(utils.RefreshJWTPayload{UserID: &userId}, time.Hour*24*7)
|
||||||
serializedPermissions, err := json.Marshal(permissions)
|
data := dto.ResponseData{
|
||||||
if err != nil {
|
AccessToken: accessToken,
|
||||||
return false
|
RefreshToken: refreshToken,
|
||||||
}
|
ExpiresAt: expiresAt,
|
||||||
wrong := redis.Set(constant.UserAuthPermissionRedisKey+*user.UID, serializedPermissions, 0).Err()
|
UID: &userId,
|
||||||
if wrong != nil {
|
}
|
||||||
return false
|
fail := redis.Set(constant.UserLoginTokenRedisKey+userId, data, time.Hour*24*7).Err()
|
||||||
}
|
if fail != nil {
|
||||||
roleList, err := roleService.GetRoleListByIds(ids)
|
resultChan <- false
|
||||||
if err != nil {
|
return
|
||||||
return false
|
}
|
||||||
}
|
responseData := map[string]interface{}{
|
||||||
serializedRoleList, err := json.Marshal(roleList)
|
"code": 0,
|
||||||
if err != nil {
|
"message": "success",
|
||||||
return false
|
"data": data,
|
||||||
}
|
"success": true,
|
||||||
er := redis.Set(constant.UserAuthRoleRedisKey+*user.UID, serializedRoleList, 0).Err()
|
}
|
||||||
if er != nil {
|
tokenData, err := json.Marshal(responseData)
|
||||||
return false
|
if err != nil {
|
||||||
}
|
resultChan <- false
|
||||||
accessToken, err := utils.GenerateAccessToken(utils.AccessJWTPayload{UserID: user.UID, RoleID: ids})
|
return
|
||||||
if err != nil {
|
}
|
||||||
return false
|
// gws方式发送消息
|
||||||
}
|
err = websocket_api.Handler.SendMessageToClient(clientId, tokenData)
|
||||||
refreshToken, expiresAt := utils.GenerateRefreshToken(utils.RefreshJWTPayload{UserID: user.UID, RoleID: ids}, time.Hour*24*7)
|
if err != nil {
|
||||||
data := dto.ResponseData{
|
global.LOG.Error(err)
|
||||||
AccessToken: accessToken,
|
resultChan <- false
|
||||||
RefreshToken: refreshToken,
|
return
|
||||||
ExpiresAt: expiresAt,
|
}
|
||||||
UID: user.UID,
|
resultChan <- true
|
||||||
}
|
}()
|
||||||
fail := redis.Set(constant.UserLoginTokenRedisKey+*user.UID, data, time.Hour*24*7).Err()
|
|
||||||
if fail != nil {
|
return <-resultChan
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
11
api/permission_api/dto/request_dto.go
Normal file
11
api/permission_api/dto/request_dto.go
Normal file
@@ -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"`
|
||||||
|
}
|
3
api/permission_api/permission.go
Normal file
3
api/permission_api/permission.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
package permission_api
|
||||||
|
|
||||||
|
type PermissionAPI struct{}
|
36
api/permission_api/permission_api.go
Normal file
36
api/permission_api/permission_api.go
Normal file
@@ -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
|
||||||
|
}
|
11
api/role_api/dto/request_dto.go
Normal file
11
api/role_api/dto/request_dto.go
Normal file
@@ -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"`
|
||||||
|
}
|
@@ -1 +1,64 @@
|
|||||||
package role_api
|
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)
|
||||||
|
}
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
package user_api
|
package user_api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
ginI18n "github.com/gin-contrib/i18n"
|
ginI18n "github.com/gin-contrib/i18n"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/yitter/idgenerator-go/idgen"
|
"github.com/yitter/idgenerator-go/idgen"
|
||||||
@@ -20,10 +19,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var userService = service.Service.UserService
|
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
|
// GetUserList
|
||||||
// @Summary 获取所有用户列表
|
// @Summary 获取所有用户列表
|
||||||
@@ -146,12 +141,8 @@ func (UserAPI) AddUser(c *gin.Context) {
|
|||||||
result.FailWithMessage(ginI18n.MustGetMessage(c, "AddUserError"), c)
|
result.FailWithMessage(ginI18n.MustGetMessage(c, "AddUserError"), c)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
userRole := model.ScaAuthUserRole{
|
_, err = global.Casbin.AddRoleForUser(uidStr, enum.User)
|
||||||
UserID: uidStr,
|
if err != nil {
|
||||||
RoleID: enum.User,
|
|
||||||
}
|
|
||||||
e := userRoleService.AddUserRole(userRole)
|
|
||||||
if e != nil {
|
|
||||||
result.FailWithMessage(ginI18n.MustGetMessage(c, "AddUserRoleError"), c)
|
result.FailWithMessage(ginI18n.MustGetMessage(c, "AddUserRoleError"), c)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -258,11 +249,30 @@ func (UserAPI) PhoneLogin(c *gin.Context) {
|
|||||||
return
|
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)
|
code := redis.Get(constant.UserLoginSmsRedisKey + phone)
|
||||||
if code == nil {
|
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)
|
result.FailWithMessage(ginI18n.MustGetMessage(c, "CaptchaExpired"), c)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
@@ -277,35 +287,29 @@ func (UserAPI) PhoneLogin(c *gin.Context) {
|
|||||||
result.FailWithMessage(ginI18n.MustGetMessage(c, "RegisterUserError"), c)
|
result.FailWithMessage(ginI18n.MustGetMessage(c, "RegisterUserError"), c)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
userRole := model.ScaAuthUserRole{
|
|
||||||
UserID: uidStr,
|
_, err = global.Casbin.AddRoleForUser(uidStr, enum.User)
|
||||||
RoleID: enum.User,
|
if err != nil {
|
||||||
}
|
result.FailWithMessage(ginI18n.MustGetMessage(c, "RegisterUserError"), c)
|
||||||
e := userRoleService.AddUserRole(userRole)
|
|
||||||
if e != nil {
|
|
||||||
result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
handelUserLogin(addUser, request.AutoLogin, c)
|
handelUserLogin(addUser, request.AutoLogin, c)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
code := redis.Get(constant.UserLoginSmsRedisKey + phone)
|
if code == "" {
|
||||||
if code == nil {
|
|
||||||
result.FailWithMessage(ginI18n.MustGetMessage(c, "CaptchaExpired"), c)
|
result.FailWithMessage(ginI18n.MustGetMessage(c, "CaptchaExpired"), c)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
if captcha != code.Val() {
|
if captcha != code {
|
||||||
result.FailWithMessage(ginI18n.MustGetMessage(c, "CaptchaError"), c)
|
result.FailWithMessage(ginI18n.MustGetMessage(c, "CaptchaError"), c)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
handelUserLogin(user, request.AutoLogin, c)
|
handelUserLogin(*user, request.AutoLogin, c)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RefreshHandler 刷新token
|
// RefreshHandler 刷新token
|
||||||
@@ -333,7 +337,7 @@ func (UserAPI) RefreshHandler(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if isUpd {
|
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 {
|
if err != nil {
|
||||||
result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginExpired"), c)
|
result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginExpired"), c)
|
||||||
return
|
return
|
||||||
@@ -362,42 +366,7 @@ func (UserAPI) RefreshHandler(c *gin.Context) {
|
|||||||
|
|
||||||
// handelUserLogin 处理用户登录
|
// handelUserLogin 处理用户登录
|
||||||
func handelUserLogin(user model.ScaAuthUser, autoLogin bool, c *gin.Context) {
|
func handelUserLogin(user model.ScaAuthUser, autoLogin bool, c *gin.Context) {
|
||||||
ids, err := userRoleService.GetUserRoleIdsByUserId(user.ID)
|
accessToken, err := utils.GenerateAccessToken(utils.AccessJWTPayload{UserID: user.UID})
|
||||||
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})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c)
|
result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c)
|
||||||
return
|
return
|
||||||
@@ -408,7 +377,7 @@ func handelUserLogin(user model.ScaAuthUser, autoLogin bool, c *gin.Context) {
|
|||||||
} else {
|
} else {
|
||||||
days = time.Hour * 24 * 1
|
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{
|
data := dto.ResponseData{
|
||||||
AccessToken: accessToken,
|
AccessToken: accessToken,
|
||||||
RefreshToken: refreshToken,
|
RefreshToken: refreshToken,
|
||||||
|
@@ -12,8 +12,6 @@ func MakeMigration() {
|
|||||||
&model.ScaAuthUser{},
|
&model.ScaAuthUser{},
|
||||||
&model.ScaAuthPermission{},
|
&model.ScaAuthPermission{},
|
||||||
&model.ScaAuthRole{},
|
&model.ScaAuthRole{},
|
||||||
&model.ScaAuthRolePermission{},
|
|
||||||
&model.ScaAuthUserRole{},
|
|
||||||
&model.ScaAuthUserDevice{},
|
&model.ScaAuthUserDevice{},
|
||||||
&model.ScaAuthUserSocial{},
|
&model.ScaAuthUserSocial{},
|
||||||
)
|
)
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
package enum
|
package enum
|
||||||
|
|
||||||
var (
|
var (
|
||||||
SuperAdmin int64 = 1
|
Root string = "root"
|
||||||
Admin int64 = 2
|
Admin string = "admin"
|
||||||
User int64 = 3
|
User string = "user"
|
||||||
)
|
)
|
||||||
|
10
config/conf_casbin.go
Normal file
10
config/conf_casbin.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
type Casbin struct {
|
||||||
|
// 权限模型文件路径
|
||||||
|
ModelPath string `yaml:"model-path"`
|
||||||
|
// 数据库前缀
|
||||||
|
TablePrefix string `yaml:"table-prefix"`
|
||||||
|
// 数据库表明
|
||||||
|
TableName string `yaml:"table-name"`
|
||||||
|
}
|
@@ -2,9 +2,9 @@ package config
|
|||||||
|
|
||||||
// Logger 配置
|
// Logger 配置
|
||||||
type Logger struct {
|
type Logger struct {
|
||||||
Level string `yaml:"level"` // 日志级别
|
Level string `yaml:"level"` // 日志级别
|
||||||
Prefix string `yaml:"prefix"` // 日志前缀
|
Prefix string `yaml:"prefix"` // 日志前缀
|
||||||
Director string `yaml:"director"` // 日志文件存放目录
|
Director string `yaml:"director"` // 日志文件存放目录
|
||||||
ShowLine bool `yaml:"show-line"` // 是否显示文件行号
|
ShowLine bool `yaml:"show-line"` // 是否显示文件行号
|
||||||
LogInConsole string `yaml:"log-in-console"` // 是否在控制台打印日志
|
LogName string `yaml:"log-name"` // 日志文件名
|
||||||
}
|
}
|
||||||
|
@@ -8,6 +8,7 @@ type System struct {
|
|||||||
Port string `yaml:"port"` //端口号
|
Port string `yaml:"port"` //端口号
|
||||||
Env string `yaml:"env"` //环境
|
Env string `yaml:"env"` //环境
|
||||||
Web string `yaml:"web"` //web地址
|
Web string `yaml:"web"` //web地址
|
||||||
|
Ip string `yaml:"ip"` //ip地址
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *System) Addr() string {
|
func (s *System) Addr() string {
|
||||||
|
@@ -11,4 +11,5 @@ type Config struct {
|
|||||||
Wechat Wechat `yaml:"wechat"`
|
Wechat Wechat `yaml:"wechat"`
|
||||||
OAuth OAuth `yaml:"oauth"`
|
OAuth OAuth `yaml:"oauth"`
|
||||||
Swagger Swagger `yaml:"swagger"`
|
Swagger Swagger `yaml:"swagger"`
|
||||||
|
Casbin Casbin `yaml:"casbin"`
|
||||||
}
|
}
|
||||||
|
@@ -11,7 +11,6 @@ import (
|
|||||||
"github.com/wenlng/go-captcha/v2/click"
|
"github.com/wenlng/go-captcha/v2/click"
|
||||||
"github.com/wenlng/go-captcha/v2/rotate"
|
"github.com/wenlng/go-captcha/v2/rotate"
|
||||||
"github.com/wenlng/go-captcha/v2/slide"
|
"github.com/wenlng/go-captcha/v2/slide"
|
||||||
"log"
|
|
||||||
"schisandra-cloud-album/global"
|
"schisandra-cloud-album/global"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -47,13 +46,13 @@ func initTextCaptcha() {
|
|||||||
// fonts
|
// fonts
|
||||||
fonts, err := fzshengsksjw.GetFont()
|
fonts, err := fzshengsksjw.GetFont()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln(err)
|
global.LOG.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// background images
|
// background images
|
||||||
imgs, err := images.GetImages()
|
imgs, err := images.GetImages()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln(err)
|
global.LOG.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// thumb images
|
// thumb images
|
||||||
@@ -119,13 +118,13 @@ func initClickShapeCaptcha() {
|
|||||||
// click.WithUseShapeOriginalColor(false) -> Random rewriting of graphic colors
|
// click.WithUseShapeOriginalColor(false) -> Random rewriting of graphic colors
|
||||||
shapeMaps, err := shapes.GetShapes()
|
shapeMaps, err := shapes.GetShapes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln(err)
|
global.LOG.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// background images
|
// background images
|
||||||
imgs, err := images.GetImages()
|
imgs, err := images.GetImages()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln(err)
|
global.LOG.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// set resources
|
// set resources
|
||||||
@@ -146,12 +145,12 @@ func initsSlideCaptcha() {
|
|||||||
// background images
|
// background images
|
||||||
imgs, err := images.GetImages()
|
imgs, err := images.GetImages()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln(err)
|
global.LOG.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
graphs, err := tiles.GetTiles()
|
graphs, err := tiles.GetTiles()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln(err)
|
global.LOG.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var newGraphs = make([]*slide.GraphImage, 0, len(graphs))
|
var newGraphs = make([]*slide.GraphImage, 0, len(graphs))
|
||||||
@@ -182,7 +181,7 @@ func initRotateCaptcha() {
|
|||||||
// background images
|
// background images
|
||||||
imgs, err := images.GetImages()
|
imgs, err := images.GetImages()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln(err)
|
global.LOG.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// set resources
|
// set resources
|
||||||
@@ -203,12 +202,12 @@ func initSlideRegionCaptcha() {
|
|||||||
// background image
|
// background image
|
||||||
imgs, err := images.GetImages()
|
imgs, err := images.GetImages()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln(err)
|
global.LOG.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
graphs, err := tiles.GetTiles()
|
graphs, err := tiles.GetTiles()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln(err)
|
global.LOG.Fatalln(err)
|
||||||
}
|
}
|
||||||
var newGraphs = make([]*slide.GraphImage, 0, len(graphs))
|
var newGraphs = make([]*slide.GraphImage, 0, len(graphs))
|
||||||
for i := 0; i < len(graphs); i++ {
|
for i := 0; i < len(graphs); i++ {
|
||||||
|
@@ -14,13 +14,22 @@ var (
|
|||||||
|
|
||||||
func InitCasbin() {
|
func InitCasbin() {
|
||||||
once.Do(func() {
|
once.Do(func() {
|
||||||
adapter, _ := gormadapter.NewAdapterByDBUseTableName(global.DB, "sca_sys_", "casbin_rule")
|
adapter, err := gormadapter.NewAdapterByDBUseTableName(global.DB, global.CONFIG.Casbin.TablePrefix, global.CONFIG.Casbin.TableName)
|
||||||
m, err := model.NewModelFromFile("config/rbac_model.pml")
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.LOG.Error(err.Error())
|
global.LOG.Error(err.Error())
|
||||||
panic(err)
|
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)
|
e.SetExpireTime(60 * 60)
|
||||||
err = e.LoadPolicy()
|
err = e.LoadPolicy()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
11
core/gorm.go
11
core/gorm.go
@@ -34,8 +34,9 @@ func MySQlConnect() *gorm.DB {
|
|||||||
|
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
logfile, _ := os.OpenFile("/tmp/logs/mysql.log", os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666)
|
||||||
mysqlLogger = logger.New(
|
mysqlLogger = logger.New(
|
||||||
log.New(os.Stdout, "\r\n", log.LstdFlags),
|
log.New(logfile, "\r\n", log.LstdFlags),
|
||||||
logger.Config{
|
logger.Config{
|
||||||
SlowThreshold: time.Second, //慢sql日志
|
SlowThreshold: time.Second, //慢sql日志
|
||||||
LogLevel: logger.Error, //级别
|
LogLevel: logger.Error, //级别
|
||||||
@@ -46,12 +47,16 @@ func MySQlConnect() *gorm.DB {
|
|||||||
}
|
}
|
||||||
|
|
||||||
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
|
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
|
||||||
Logger: mysqlLogger,
|
Logger: mysqlLogger,
|
||||||
|
PrepareStmt: true,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.LOG.Fatalf(fmt.Sprintf("[%s] MySQL 连接失败", dsn))
|
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.SetMaxIdleConns(global.CONFIG.MySQL.MaxIdleConnes)
|
||||||
sqlDB.SetMaxOpenConns(global.CONFIG.MySQL.MaxOpenConnes)
|
sqlDB.SetMaxOpenConns(global.CONFIG.MySQL.MaxOpenConnes)
|
||||||
sqlDB.SetConnMaxLifetime(time.Hour * 4) //连接最大复用时间
|
sqlDB.SetConnMaxLifetime(time.Hour * 4) //连接最大复用时间
|
||||||
|
@@ -1,80 +1,24 @@
|
|||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"schisandra-cloud-album/global"
|
"schisandra-cloud-album/global"
|
||||||
|
"schisandra-cloud-album/middleware"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
func InitLogger() {
|
||||||
red = 31
|
// 按照日期格式化输出
|
||||||
yellow = 33
|
mylog := middleware.NewDateLog(&middleware.DateLogConfig{
|
||||||
blue = 34
|
Date: time.Now().Format("2006-01-02"),
|
||||||
gray = 37
|
Path: global.CONFIG.Logger.Director,
|
||||||
)
|
Name: global.CONFIG.Logger.LogName,
|
||||||
|
})
|
||||||
type LogFormatter struct{}
|
log := mylog.Init()
|
||||||
|
|
||||||
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{}) //设置日志格式
|
|
||||||
level, err := logrus.ParseLevel(global.CONFIG.Logger.Level)
|
level, err := logrus.ParseLevel(global.CONFIG.Logger.Level)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
level = logrus.InfoLevel
|
level = logrus.InfoLevel
|
||||||
}
|
}
|
||||||
newLog.SetLevel(level) //设置日志级别
|
log.SetLevel(level) //设置日志级别
|
||||||
global.LOG = newLog
|
global.LOG = log
|
||||||
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) //设置日志级别
|
|
||||||
}
|
}
|
||||||
|
@@ -13,10 +13,10 @@ func InitWechat() {
|
|||||||
Secret: global.CONFIG.Wechat.AppSecret,
|
Secret: global.CONFIG.Wechat.AppSecret,
|
||||||
Token: global.CONFIG.Wechat.Token,
|
Token: global.CONFIG.Wechat.Token,
|
||||||
AESKey: global.CONFIG.Wechat.AESKey,
|
AESKey: global.CONFIG.Wechat.AESKey,
|
||||||
//Log: officialAccount.Log{
|
Log: officialAccount.Log{
|
||||||
// Level: "debug",
|
Level: "error",
|
||||||
// File: "./wechat.log",
|
File: "./wechat.log",
|
||||||
//},
|
},
|
||||||
ResponseType: os.Getenv("response_type"),
|
ResponseType: os.Getenv("response_type"),
|
||||||
HttpDebug: true,
|
HttpDebug: true,
|
||||||
Debug: true,
|
Debug: true,
|
||||||
@@ -27,6 +27,7 @@ func InitWechat() {
|
|||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
global.LOG.Error(err.Error())
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
global.Wechat = OfficialAccountApp
|
global.Wechat = OfficialAccountApp
|
||||||
|
76
docs/docs.go
76
docs/docs.go
@@ -15,6 +15,60 @@ const docTemplate = `{
|
|||||||
"host": "{{.Host}}",
|
"host": "{{.Host}}",
|
||||||
"basePath": "{{.BasePath}}",
|
"basePath": "{{.BasePath}}",
|
||||||
"paths": {
|
"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": {
|
"/api/auth/user/List": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [
|
"tags": [
|
||||||
@@ -735,6 +789,17 @@ const docTemplate = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"dto.AddRoleToUserRequestDto": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"role_key": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"uid": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"dto.AddUserRequest": {
|
"dto.AddUserRequest": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -779,6 +844,17 @@ const docTemplate = `{
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"dto.RoleRequestDto": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"role_key": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"role_name": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}`
|
}`
|
||||||
|
@@ -4,6 +4,60 @@
|
|||||||
"contact": {}
|
"contact": {}
|
||||||
},
|
},
|
||||||
"paths": {
|
"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": {
|
"/api/auth/user/List": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [
|
"tags": [
|
||||||
@@ -724,6 +778,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"dto.AddRoleToUserRequestDto": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"role_key": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"uid": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"dto.AddUserRequest": {
|
"dto.AddUserRequest": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -768,6 +833,17 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"dto.RoleRequestDto": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"role_key": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"role_name": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -8,6 +8,13 @@ definitions:
|
|||||||
password:
|
password:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
|
dto.AddRoleToUserRequestDto:
|
||||||
|
properties:
|
||||||
|
role_key:
|
||||||
|
type: string
|
||||||
|
uid:
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
dto.AddUserRequest:
|
dto.AddUserRequest:
|
||||||
properties:
|
properties:
|
||||||
password:
|
password:
|
||||||
@@ -37,9 +44,52 @@ definitions:
|
|||||||
repassword:
|
repassword:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
|
dto.RoleRequestDto:
|
||||||
|
properties:
|
||||||
|
role_key:
|
||||||
|
type: string
|
||||||
|
role_name:
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
info:
|
info:
|
||||||
contact: {}
|
contact: {}
|
||||||
paths:
|
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:
|
/api/auth/user/List:
|
||||||
get:
|
get:
|
||||||
responses:
|
responses:
|
||||||
|
8
go.mod
8
go.mod
@@ -6,12 +6,16 @@ require (
|
|||||||
github.com/ArtisanCloud/PowerLibs/v3 v3.2.5
|
github.com/ArtisanCloud/PowerLibs/v3 v3.2.5
|
||||||
github.com/ArtisanCloud/PowerWeChat/v3 v3.2.38
|
github.com/ArtisanCloud/PowerWeChat/v3 v3.2.38
|
||||||
github.com/BurntSushi/toml v1.3.2
|
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/cors v1.7.2
|
||||||
github.com/gin-contrib/i18n v1.1.3
|
github.com/gin-contrib/i18n v1.1.3
|
||||||
github.com/gin-gonic/gin v1.10.0
|
github.com/gin-gonic/gin v1.10.0
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.1
|
github.com/golang-jwt/jwt/v5 v5.2.1
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
|
||||||
github.com/gorilla/websocket v1.5.3
|
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/pkg6/go-sms v0.1.2
|
||||||
github.com/redis/go-redis/v9 v9.6.1
|
github.com/redis/go-redis/v9 v9.6.1
|
||||||
github.com/satori/go.uuid v1.2.0
|
github.com/satori/go.uuid v1.2.0
|
||||||
@@ -37,8 +41,6 @@ require (
|
|||||||
github.com/KyleBanks/depth v1.2.1 // indirect
|
github.com/KyleBanks/depth v1.2.1 // indirect
|
||||||
github.com/bytedance/sonic v1.12.0 // indirect
|
github.com/bytedance/sonic v1.12.0 // indirect
|
||||||
github.com/bytedance/sonic/loader v0.2.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/casbin/govaluate v1.2.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/clbanning/mxj/v2 v2.7.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/jinzhu/now v1.1.5 // indirect
|
||||||
github.com/josharian/intern v1.0.0 // indirect
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // 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/compress v1.17.5 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
|
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
|
||||||
github.com/leodido/go-urn v1.4.0 // 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/mailru/easyjson v0.7.7 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/microsoft/go-mssqldb v1.6.0 // indirect
|
github.com/microsoft/go-mssqldb v1.6.0 // indirect
|
||||||
|
22
go.sum
22
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.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.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.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/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/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.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.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/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/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/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.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/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 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
|
||||||
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
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-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 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
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/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 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
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/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 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
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=
|
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/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 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
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/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 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
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 h1:6x+wW3EHtoGFNeCtZP1OVZ1IHrpZZzDaEjQGg1lUJqU=
|
||||||
github.com/lxzan/gws v1.8.5/go.mod h1:FcGeRMB7HwGuTvMLR24ku0Zx0p6RXqeKASeMc4VYgi4=
|
github.com/lxzan/gws v1.8.5/go.mod h1:FcGeRMB7HwGuTvMLR24ku0Zx0p6RXqeKASeMc4VYgi4=
|
||||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
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.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 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
|
||||||
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
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 h1:mM3gYdVwEPFrlg/Dvr2DNVEgYFG7L42l+dGc67NNNpc=
|
||||||
github.com/microsoft/go-mssqldb v1.6.0/go.mod h1:00mDtPbeQCRGC1HwOOR5K/gr30P1NcEG0vx6Kbv2aJU=
|
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=
|
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/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 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
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/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 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
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-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 h1:VstopitMQi3hZP0fzvnsLmzXZdQGc4bEcgu24cp+d4M=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230126093431-47fa9a501578/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
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 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 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
|
||||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
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.6/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
|
||||||
gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
|
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/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 h1:8ptbNJTDbEmhdr62uReG5BGkdQyeasu/FZHxI0IMGnM=
|
||||||
gorm.io/driver/postgres v1.5.7/go.mod h1:3e019WlBaYI5o5LIdNV+LyxCMNtLOQETBXL2h4chKpA=
|
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 h1:zKYbzRCpBrT1bNijRnxLDJWPjVfImGEn0lSnUY5gZ+c=
|
||||||
gorm.io/driver/sqlite v1.5.0/go.mod h1:kDMDfntV9u/vuMmz8APHtHF0b4nyBB7sfCieC6G8k8I=
|
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 h1:rjupPS4PVw+rjJkfvr8jn2lJ8BMhT4UW5FwuJY0P3Z0=
|
||||||
gorm.io/driver/sqlserver v1.5.3/go.mod h1:B+CZ0/7oFJ6tAlefsKoyxdgDCXJKSgwS2bMOQZT0I00=
|
gorm.io/driver/sqlserver v1.5.3/go.mod h1:B+CZ0/7oFJ6tAlefsKoyxdgDCXJKSgwS2bMOQZT0I00=
|
||||||
gorm.io/gen v0.3.26 h1:sFf1j7vNStimPRRAtH4zz5NiHM+1dr6eA9aaRdplyhY=
|
gorm.io/gen v0.3.26 h1:sFf1j7vNStimPRRAtH4zz5NiHM+1dr6eA9aaRdplyhY=
|
||||||
|
1
main.go
1
main.go
@@ -8,6 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
// 初始化配置
|
// 初始化配置
|
||||||
core.InitConfig() // 读取配置文件
|
core.InitConfig() // 读取配置文件
|
||||||
core.InitLogger() // 初始化日志
|
core.InitLogger() // 初始化日志
|
||||||
|
157
middleware/logger_date.go
Normal file
157
middleware/logger_date.go
Normal file
@@ -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
|
||||||
|
}
|
116
middleware/logger_level.go
Normal file
116
middleware/logger_level.go
Normal file
@@ -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
|
||||||
|
}
|
@@ -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
|
|
||||||
}
|
|
@@ -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
|
|
||||||
}
|
|
@@ -9,7 +9,7 @@ const TableNameScaAuthUserSocial = "sca_auth_user_social"
|
|||||||
// ScaAuthUserSocial 社会用户信息表
|
// ScaAuthUserSocial 社会用户信息表
|
||||||
type ScaAuthUserSocial struct {
|
type ScaAuthUserSocial struct {
|
||||||
ID int64 `gorm:"column:id;type:bigint(20);primaryKey;comment:主键ID" json:"id"` // 主键ID
|
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
|
UUID *string `gorm:"column:uuid;type:varchar(255);comment:第三方系统的唯一ID" json:"uuid"` // 第三方系统的唯一ID
|
||||||
Source *string `gorm:"column:source;type:varchar(255);comment:第三方用户来源" json:"source"` // 第三方用户来源
|
Source *string `gorm:"column:source;type:varchar(255);comment:第三方用户来源" json:"source"` // 第三方用户来源
|
||||||
AccessToken *string `gorm:"column:access_token;type:varchar(255);comment:用户的授权令牌" json:"access_token"` // 用户的授权令牌
|
AccessToken *string `gorm:"column:access_token;type:varchar(255);comment:用户的授权令牌" json:"access_token"` // 用户的授权令牌
|
||||||
|
@@ -14,8 +14,8 @@ func OauthRouter(router *gin.RouterGroup) {
|
|||||||
{
|
{
|
||||||
wechatRouter.GET("/generate_client_id", oauth.GenerateClientId)
|
wechatRouter.GET("/generate_client_id", oauth.GenerateClientId)
|
||||||
wechatRouter.GET("/get_temp_qrcode", oauth.GetTempQrCode)
|
wechatRouter.GET("/get_temp_qrcode", oauth.GetTempQrCode)
|
||||||
wechatRouter.GET("/callback", oauth.CallbackVerify)
|
//wechatRouter.GET("/callback", oauth.CallbackVerify)
|
||||||
//wechatRouter.POST("/callback", oauth.CallbackNotify)
|
wechatRouter.POST("/callback", oauth.CallbackNotify)
|
||||||
}
|
}
|
||||||
githubRouter := group.Group("/github")
|
githubRouter := group.Group("/github")
|
||||||
{
|
{
|
||||||
|
16
router/modules/role_router.go
Normal file
16
router/modules/role_router.go
Normal file
@@ -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)
|
||||||
|
}
|
@@ -12,14 +12,21 @@ import (
|
|||||||
func InitRouter() *gin.Engine {
|
func InitRouter() *gin.Engine {
|
||||||
gin.SetMode(global.CONFIG.System.Env)
|
gin.SetMode(global.CONFIG.System.Env)
|
||||||
router := gin.Default()
|
router := gin.Default()
|
||||||
err := router.SetTrustedProxies([]string{"127.0.0.1"})
|
err := router.SetTrustedProxies([]string{global.CONFIG.System.Ip})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.LOG.Error(err)
|
global.LOG.Error(err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
router.Use(middleware.RateLimitMiddleware(time.Millisecond*100, 20)) // 限流中间件
|
||||||
publicGroup := router.Group("api")
|
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())
|
publicGroup.Use(middleware.I18n())
|
||||||
|
|
||||||
@@ -29,5 +36,6 @@ func InitRouter() *gin.Engine {
|
|||||||
modules.SmsRouter(publicGroup) // 注册短信验证码路由
|
modules.SmsRouter(publicGroup) // 注册短信验证码路由
|
||||||
modules.OauthRouter(publicGroup) // 注册oauth路由
|
modules.OauthRouter(publicGroup) // 注册oauth路由
|
||||||
modules.WebsocketRouter(publicGroup) // 注册websocket路由
|
modules.WebsocketRouter(publicGroup) // 注册websocket路由
|
||||||
|
modules.RoleRouter(publicGroup) // 注册角色路由
|
||||||
return router
|
return router
|
||||||
}
|
}
|
||||||
|
@@ -13,3 +13,11 @@ func (PermissionService) GetPermissionsByIds(ids []int64) ([]model.ScaAuthPermis
|
|||||||
}
|
}
|
||||||
return permissions, nil
|
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
|
||||||
|
}
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
package role_permission_service
|
|
||||||
|
|
||||||
type RolePermissionService struct{}
|
|
@@ -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
|
|
||||||
}
|
|
@@ -13,3 +13,11 @@ func (RoleService) GetRoleListByIds(id []*int64) ([]model.ScaAuthRole, error) {
|
|||||||
}
|
}
|
||||||
return roles, nil
|
return roles, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddRole 新增角色
|
||||||
|
func (RoleService) AddRole(role model.ScaAuthRole) error {
|
||||||
|
if err := global.DB.Create(&role).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@@ -2,21 +2,17 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"schisandra-cloud-album/service/permission_service"
|
"schisandra-cloud-album/service/permission_service"
|
||||||
"schisandra-cloud-album/service/role_permission_service"
|
|
||||||
"schisandra-cloud-album/service/role_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_service"
|
||||||
"schisandra-cloud-album/service/user_social_service"
|
"schisandra-cloud-album/service/user_social_service"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Services 统一导出的service
|
// Services 统一导出的service
|
||||||
type Services struct {
|
type Services struct {
|
||||||
UserService user_service.UserService
|
UserService user_service.UserService
|
||||||
RoleService role_service.RoleService
|
RoleService role_service.RoleService
|
||||||
UserRoleService user_role_service.UserRoleService
|
PermissionService permission_service.PermissionService
|
||||||
RolePermissionService role_permission_service.RolePermissionService
|
UserSocialService user_social_service.UserSocialService
|
||||||
PermissionService permission_service.PermissionService
|
|
||||||
UserSocialService user_social_service.UserSocialService
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Service new函数实例化,实例化完成后会返回结构体地指针类型
|
// Service new函数实例化,实例化完成后会返回结构体地指针类型
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
package user_role_service
|
|
||||||
|
|
||||||
type UserRoleService struct{}
|
|
@@ -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
|
|
||||||
}
|
|
10
utils/jwt.go
10
utils/jwt.go
@@ -9,14 +9,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type RefreshJWTPayload struct {
|
type RefreshJWTPayload struct {
|
||||||
UserID *string `json:"user_id"`
|
UserID *string `json:"user_id"`
|
||||||
RoleID []*int64 `json:"role_id"`
|
Type *string `json:"type" default:"refresh"`
|
||||||
Type *string `json:"type" default:"refresh"`
|
|
||||||
}
|
}
|
||||||
type AccessJWTPayload struct {
|
type AccessJWTPayload struct {
|
||||||
UserID *string `json:"user_id"`
|
UserID *string `json:"user_id"`
|
||||||
RoleID []*int64 `json:"role_id"`
|
Type *string `json:"type" default:"access"`
|
||||||
Type *string `json:"type" default:"access"`
|
|
||||||
}
|
}
|
||||||
type AccessJWTClaims struct {
|
type AccessJWTClaims struct {
|
||||||
AccessJWTPayload
|
AccessJWTPayload
|
||||||
|
Reference in New Issue
Block a user