diff --git a/.idea/GOHCache.xml b/.idea/GOHCache.xml
index 5051818..c5082f8 100644
--- a/.idea/GOHCache.xml
+++ b/.idea/GOHCache.xml
@@ -38,6 +38,13 @@
+
+
+
+
+
+
+
@@ -213,6 +220,14 @@
+
+
+
+
+
+
+
+
@@ -276,6 +291,14 @@
+
+
+
+
+
+
+
+
@@ -577,6 +600,13 @@
+
+
+
+
+
+
+
@@ -661,6 +691,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -668,6 +712,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -983,7 +1055,7 @@
-
+
@@ -1008,10 +1080,10 @@
-
+
-
+
@@ -1123,7 +1195,7 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -1170,7 +1255,7 @@
-
+
@@ -1280,7 +1365,7 @@
-
+
@@ -1394,6 +1479,13 @@
+
+
+
+
+
+
+
@@ -1425,14 +1517,35 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -1485,6 +1598,13 @@
+
+
+
+
+
+
+
@@ -1499,6 +1619,13 @@
+
+
+
+
+
+
+
@@ -1676,10 +1803,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -1691,7 +1830,7 @@
-
+
@@ -1705,7 +1844,7 @@
-
+
@@ -1718,7 +1857,7 @@
-
+
@@ -1733,10 +1872,48 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1781,7 +1958,7 @@
-
+
@@ -1805,7 +1982,7 @@
-
+
@@ -1817,7 +1994,7 @@
-
+
@@ -1826,10 +2003,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -1850,6 +2039,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1889,10 +2090,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -1916,7 +2129,7 @@
-
+
@@ -1945,7 +2158,7 @@
-
+
@@ -1957,7 +2170,7 @@
-
+
@@ -2481,13 +2694,6 @@
-
-
-
-
-
-
-
@@ -2518,6 +2724,7 @@
+
@@ -2544,6 +2751,7 @@
+
@@ -2553,6 +2761,7 @@
+
@@ -2613,6 +2822,7 @@
+
@@ -2625,9 +2835,15 @@
+
+
+
+
+
+
-
+
\ No newline at end of file
diff --git a/app/core/api/common/constant/session_key.go b/app/core/api/common/constant/session_key.go
deleted file mode 100644
index 9961167..0000000
--- a/app/core/api/common/constant/session_key.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package constant
-
-const SESSION_KEY = "SESSION"
diff --git a/app/core/api/common/constant/uid_key.go b/app/core/api/common/constant/uid_key.go
new file mode 100644
index 0000000..a574c39
--- /dev/null
+++ b/app/core/api/common/constant/uid_key.go
@@ -0,0 +1,3 @@
+package constant
+
+const UID_HEADER_KEY = "X-UID"
diff --git a/app/core/api/common/jwt/access_token.go b/app/core/api/common/jwt/access_token.go
index f68be8c..2c481cc 100644
--- a/app/core/api/common/jwt/access_token.go
+++ b/app/core/api/common/jwt/access_token.go
@@ -19,7 +19,7 @@ func GenerateAccessToken(secret string, payload AccessJWTPayload) string {
claims := AccessJWTClaims{
AccessJWTPayload: payload,
RegisteredClaims: jwt.RegisteredClaims{
- ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Minute * 30)),
+ ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Minute * 15)),
IssuedAt: jwt.NewNumericDate(time.Now()),
NotBefore: jwt.NewNumericDate(time.Now()),
},
diff --git a/app/core/api/common/jwt/websocket_token.go b/app/core/api/common/jwt/websocket_token.go
new file mode 100644
index 0000000..af2c63c
--- /dev/null
+++ b/app/core/api/common/jwt/websocket_token.go
@@ -0,0 +1,48 @@
+package jwt
+
+import (
+ "time"
+
+ "github.com/golang-jwt/jwt/v5"
+)
+
+type WebsocketJWTPayload struct {
+ UserID string `json:"user_id"`
+ Type string `json:"type"`
+ Expr string `json:"expr"`
+}
+type WebsocketJWTClaims struct {
+ AccessJWTPayload
+ jwt.RegisteredClaims
+}
+
+func GenerateWebsocketToken(secret string, payload AccessJWTPayload) string {
+ claims := AccessJWTClaims{
+ AccessJWTPayload: payload,
+ RegisteredClaims: jwt.RegisteredClaims{
+ ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Minute * 15)),
+ IssuedAt: jwt.NewNumericDate(time.Now()),
+ NotBefore: jwt.NewNumericDate(time.Now()),
+ },
+ }
+ token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
+ accessToken, err := token.SignedString([]byte(secret))
+ if err != nil {
+ return ""
+ }
+ return accessToken
+}
+
+// ParseWebsocketToken parses a JWT token and returns the payload
+func ParseWebsocketToken(secret string, tokenString string) (*AccessJWTPayload, bool) {
+ token, err := jwt.ParseWithClaims(tokenString, &AccessJWTClaims{}, func(token *jwt.Token) (interface{}, error) {
+ return []byte(secret), nil
+ })
+ if err != nil {
+ return nil, false
+ }
+ if claims, ok := token.Claims.(*AccessJWTClaims); ok && token.Valid {
+ return &claims.AccessJWTPayload, true
+ }
+ return nil, false
+}
diff --git a/app/core/api/common/middleware/cors_middleware.go b/app/core/api/common/middleware/cors_middleware.go
index b10579b..7c640fe 100644
--- a/app/core/api/common/middleware/cors_middleware.go
+++ b/app/core/api/common/middleware/cors_middleware.go
@@ -7,7 +7,7 @@ func CORSMiddleware() func(http.Header) {
header.Set("Access-Control-Allow-Origin", "*")
header.Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, PATCH")
header.Set("Access-Control-Expose-Headers", "Content-Length, Content-Type")
- header.Set("Access-Control-Allow-Headers", "Content-Type,Authorization,Accept-Language,Origin,X-Content-Security")
+ header.Set("Access-Control-Allow-Headers", "Content-Type,Authorization,Accept-Language,Origin,X-Content-Security,X-UID")
header.Set("Access-Control-Allow-Credentials", "true")
}
}
diff --git a/app/core/api/common/middleware/unauthorized_callback_middleware.go b/app/core/api/common/middleware/unauthorized_callback_middleware.go
index 61f525f..e9e46fe 100644
--- a/app/core/api/common/middleware/unauthorized_callback_middleware.go
+++ b/app/core/api/common/middleware/unauthorized_callback_middleware.go
@@ -10,7 +10,7 @@ import (
func UnauthorizedCallbackMiddleware() func(w http.ResponseWriter, r *http.Request, err error) {
return func(w http.ResponseWriter, r *http.Request, err error) {
- // httpx.WriteJson(w, http.StatusUnauthorized, response.ErrorWithCodeMessage(http.StatusUnauthorized, "Unauthorized"))
- httpx.OkJsonCtx(r.Context(), w, response.ErrorWithCodeMessage(http.StatusUnauthorized, "Unauthorized"))
+ httpx.OkJsonCtx(r.Context(), w, response.ErrorWithCodeMessage(http.StatusUnauthorized, err.Error()))
+ return
}
}
diff --git a/app/core/api/core.api b/app/core/api/core.api
index f74e337..d90490a 100644
--- a/app/core/api/core.api
+++ b/app/core/api/core.api
@@ -31,8 +31,9 @@ type (
Password string `json:"password"`
Repassword string `json:"repassword"`
}
- UserDeviceRequest {
- AccessToken string `json:"access_token"`
+ WechatOffiaccountLoginRequest {
+ Openid string `json:"openid"`
+ ClientId string `json:"client_id"`
}
// 登录响应参数
LoginResponse {
@@ -170,8 +171,13 @@ service core {
@handler resetPassword
post /reset/password (ResetPasswordRequest) returns (Response)
- @handler getUserDevice
- post /device (UserDeviceRequest) returns (Response)
+ // 微信公众号登录
+ @handler wechatOffiaccountLogin
+ post /wechat/offiaccount/login (WechatOffiaccountLoginRequest) returns (Response)
+
+ // 获取微信公众号二维码
+ @handler getWechatOffiaccountQrcode
+ post /wechat/offiaccount/qrcode (OAuthWechatRequest) returns (Response)
}
@server (
@@ -249,11 +255,12 @@ service core {
@handler qqCallback
get /qq/callback (OAuthCallbackRequest) returns (string)
- @handler wechatCallback
- get /wechat/callback
+ @handler wechatOffiaccountCallback
+ post /wechat/offiaccount/callback
- @handler getWechatQrcode
- get /wechat/qrcode (OAuthWechatRequest) returns (Response)
+ // important!
+ @handler wechatOffiaccountCallbackVerify
+ get /wechat/offiaccount/callback
}
@server (
@@ -301,7 +308,7 @@ service core {
timeout: 10s // 超时时间
maxBytes: 1048576 // 最大请求大小
signature: false // 是否开启签名验证
- middleware: SecurityHeadersMiddleware,CasbinVerifyMiddleware // 注册中间件
+ middleware: SecurityHeadersMiddleware,CasbinVerifyMiddleware,AuthorizationMiddleware // 注册中间件
MaxConns: true // 是否开启最大连接数限制
Recover: true // 是否开启自动恢复
jwt: Auth // 是否开启jwt验证
diff --git a/app/core/api/internal/handler/oauth/wechat_callback_handler.go b/app/core/api/internal/handler/oauth/wechat_offiaccount_callback_handler.go
similarity index 66%
rename from app/core/api/internal/handler/oauth/wechat_callback_handler.go
rename to app/core/api/internal/handler/oauth/wechat_offiaccount_callback_handler.go
index 1cfef15..2288c62 100644
--- a/app/core/api/internal/handler/oauth/wechat_callback_handler.go
+++ b/app/core/api/internal/handler/oauth/wechat_offiaccount_callback_handler.go
@@ -1,20 +1,20 @@
package oauth
import (
+ "github.com/ArtisanCloud/PowerLibs/v3/http/helper"
+ "github.com/zeromicro/go-zero/core/logx"
"net/http"
- "github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/rest/httpx"
-
"schisandra-album-cloud-microservices/app/core/api/common/response"
"schisandra-album-cloud-microservices/app/core/api/internal/logic/oauth"
"schisandra-album-cloud-microservices/app/core/api/internal/svc"
)
-func WechatCallbackHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+func WechatOffiaccountCallbackHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
- l := oauth.NewWechatCallbackLogic(r.Context(), svcCtx)
- err := l.WechatCallback(w, r)
+ l := oauth.NewWechatOffiaccountCallbackLogic(r.Context(), svcCtx)
+ res, err := l.WechatOffiaccountCallback(r)
if err != nil {
logx.Error(err)
httpx.WriteJsonCtx(
@@ -23,7 +23,7 @@ func WechatCallbackHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
http.StatusInternalServerError,
response.ErrorWithI18n(r.Context(), "system.error"))
} else {
- httpx.Ok(w)
+ _ = helper.HttpResponseSend(res, w)
}
}
}
diff --git a/app/core/api/internal/handler/oauth/wechat_offiaccount_callback_verify_handler.go b/app/core/api/internal/handler/oauth/wechat_offiaccount_callback_verify_handler.go
new file mode 100644
index 0000000..3dd40fb
--- /dev/null
+++ b/app/core/api/internal/handler/oauth/wechat_offiaccount_callback_verify_handler.go
@@ -0,0 +1,29 @@
+package oauth
+
+import (
+ "github.com/ArtisanCloud/PowerLibs/v3/http/helper"
+ "github.com/zeromicro/go-zero/core/logx"
+ "net/http"
+
+ "github.com/zeromicro/go-zero/rest/httpx"
+ "schisandra-album-cloud-microservices/app/core/api/common/response"
+ "schisandra-album-cloud-microservices/app/core/api/internal/logic/oauth"
+ "schisandra-album-cloud-microservices/app/core/api/internal/svc"
+)
+
+func WechatOffiaccountCallbackVerifyHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+ l := oauth.NewWechatOffiaccountCallbackVerifyLogic(r.Context(), svcCtx)
+ res, err := l.WechatOffiaccountCallbackVerify(r)
+ if err != nil {
+ logx.Error(err)
+ httpx.WriteJsonCtx(
+ r.Context(),
+ w,
+ http.StatusInternalServerError,
+ response.ErrorWithI18n(r.Context(), "system.error"))
+ } else {
+ _ = helper.HttpResponseSend(res, w)
+ }
+ }
+}
diff --git a/app/core/api/internal/handler/routes.go b/app/core/api/internal/handler/routes.go
index 191820c..16e4fcc 100644
--- a/app/core/api/internal/handler/routes.go
+++ b/app/core/api/internal/handler/routes.go
@@ -61,7 +61,7 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
server.AddRoutes(
rest.WithMiddlewares(
- []rest.Middleware{serverCtx.SecurityHeadersMiddleware, serverCtx.CasbinVerifyMiddleware},
+ []rest.Middleware{serverCtx.SecurityHeadersMiddleware, serverCtx.CasbinVerifyMiddleware, serverCtx.AuthorizationMiddleware},
[]rest.Route{
{
Method: http.MethodPost,
@@ -141,14 +141,14 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Handler: oauth.GetQqOauthUrlHandler(serverCtx),
},
{
- Method: http.MethodGet,
- Path: "/wechat/callback",
- Handler: oauth.WechatCallbackHandler(serverCtx),
+ Method: http.MethodPost,
+ Path: "/wechat/offiaccount/callback",
+ Handler: oauth.WechatOffiaccountCallbackHandler(serverCtx),
},
{
Method: http.MethodGet,
- Path: "/wechat/qrcode",
- Handler: oauth.GetWechatQrcodeHandler(serverCtx),
+ Path: "/wechat/offiaccount/callback",
+ Handler: oauth.WechatOffiaccountCallbackVerifyHandler(serverCtx),
},
}...,
),
@@ -220,11 +220,6 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
rest.WithMiddlewares(
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware},
[]rest.Route{
- {
- Method: http.MethodPost,
- Path: "/device",
- Handler: user.GetUserDeviceHandler(serverCtx),
- },
{
Method: http.MethodPost,
Path: "/login",
@@ -240,6 +235,16 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/reset/password",
Handler: user.ResetPasswordHandler(serverCtx),
},
+ {
+ Method: http.MethodPost,
+ Path: "/wechat/offiaccount/login",
+ Handler: user.WechatOffiaccountLoginHandler(serverCtx),
+ },
+ {
+ Method: http.MethodPost,
+ Path: "/wechat/offiaccount/qrcode",
+ Handler: user.GetWechatOffiaccountQrcodeHandler(serverCtx),
+ },
}...,
),
rest.WithSignature(serverCtx.Config.Signature),
diff --git a/app/core/api/internal/handler/oauth/get_wechat_qrcode_handler.go b/app/core/api/internal/handler/user/get_wechat_offiaccount_qrcode_handler.go
similarity index 77%
rename from app/core/api/internal/handler/oauth/get_wechat_qrcode_handler.go
rename to app/core/api/internal/handler/user/get_wechat_offiaccount_qrcode_handler.go
index 4ffc9a4..235c3c8 100644
--- a/app/core/api/internal/handler/oauth/get_wechat_qrcode_handler.go
+++ b/app/core/api/internal/handler/user/get_wechat_offiaccount_qrcode_handler.go
@@ -1,18 +1,17 @@
-package oauth
+package user
import (
- "net/http"
-
"github.com/zeromicro/go-zero/core/logx"
- "github.com/zeromicro/go-zero/rest/httpx"
+ "net/http"
+ "schisandra-album-cloud-microservices/app/core/api/internal/logic/user"
+ "github.com/zeromicro/go-zero/rest/httpx"
"schisandra-album-cloud-microservices/app/core/api/common/response"
- "schisandra-album-cloud-microservices/app/core/api/internal/logic/oauth"
"schisandra-album-cloud-microservices/app/core/api/internal/svc"
"schisandra-album-cloud-microservices/app/core/api/internal/types"
)
-func GetWechatQrcodeHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+func GetWechatOffiaccountQrcodeHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.OAuthWechatRequest
if err := httpx.Parse(r, &req); err != nil {
@@ -20,8 +19,8 @@ func GetWechatQrcodeHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return
}
- l := oauth.NewGetWechatQrcodeLogic(r.Context(), svcCtx)
- resp, err := l.GetWechatQrcode(r, &req)
+ l := user.NewGetWechatOffiaccountQrcodeLogic(r.Context(), svcCtx)
+ resp, err := l.GetWechatOffiaccountQrcode(r, &req)
if err != nil {
logx.Error(err)
httpx.WriteJsonCtx(
diff --git a/app/core/api/internal/handler/user/get_user_device_handler.go b/app/core/api/internal/handler/user/wechat_offiaccount_login_handler.go
similarity index 76%
rename from app/core/api/internal/handler/user/get_user_device_handler.go
rename to app/core/api/internal/handler/user/wechat_offiaccount_login_handler.go
index 520de3d..9b57063 100644
--- a/app/core/api/internal/handler/user/get_user_device_handler.go
+++ b/app/core/api/internal/handler/user/wechat_offiaccount_login_handler.go
@@ -11,16 +11,16 @@ import (
"schisandra-album-cloud-microservices/app/core/api/internal/types"
)
-func GetUserDeviceHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+func WechatOffiaccountLoginHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
- var req types.UserDeviceRequest
+ var req types.WechatOffiaccountLoginRequest
if err := httpx.Parse(r, &req); err != nil {
httpx.ErrorCtx(r.Context(), w, err)
return
}
- l := user.NewGetUserDeviceLogic(r.Context(), svcCtx)
- resp, err := l.GetUserDevice(r, w, &req)
+ l := user.NewWechatOffiaccountLoginLogic(r.Context(), svcCtx)
+ resp, err := l.WechatOffiaccountLogin(r, &req)
if err != nil {
logx.Error(err)
httpx.WriteJsonCtx(
diff --git a/app/core/api/internal/logic/oauth/gitee_callback_logic.go b/app/core/api/internal/logic/oauth/gitee_callback_logic.go
index cddb1cf..6efb09a 100644
--- a/app/core/api/internal/logic/oauth/gitee_callback_logic.go
+++ b/app/core/api/internal/logic/oauth/gitee_callback_logic.go
@@ -149,7 +149,7 @@ func (l *GiteeCallbackLogic) GiteeCallback(w http.ResponseWriter, r *http.Reques
_ = tx.Rollback()
return "", err
}
- data, err := HandleOauthLoginResponse(addUser, l.svcCtx, r, w, l.ctx)
+ data, err := HandleOauthLoginResponse(addUser, l.svcCtx, r, l.ctx)
if err != nil {
_ = tx.Rollback()
return "", err
@@ -167,7 +167,7 @@ func (l *GiteeCallbackLogic) GiteeCallback(w http.ResponseWriter, r *http.Reques
return "", err
}
- data, err := HandleOauthLoginResponse(authUserInfo, l.svcCtx, r, w, l.ctx)
+ data, err := HandleOauthLoginResponse(authUserInfo, l.svcCtx, r, l.ctx)
if err != nil {
_ = tx.Rollback()
return "", err
@@ -180,13 +180,12 @@ func (l *GiteeCallbackLogic) GiteeCallback(w http.ResponseWriter, r *http.Reques
}
// HandleOauthLoginResponse 处理登录响应
-func HandleOauthLoginResponse(scaAuthUser *model.ScaAuthUser, svcCtx *svc.ServiceContext, r *http.Request, w http.ResponseWriter, ctx context.Context) (string, error) {
- data, err := user.HandleUserLogin(scaAuthUser, svcCtx, true, r, w, ctx)
+func HandleOauthLoginResponse(scaAuthUser *model.ScaAuthUser, svcCtx *svc.ServiceContext, r *http.Request, ctx context.Context) (string, error) {
+ data, err := user.HandleLoginJWT(scaAuthUser, svcCtx, true, r, ctx)
if err != nil {
return "", err
}
- responseData := response.SuccessWithData(data)
- marshalData, err := json.Marshal(responseData)
+ marshalData, err := json.Marshal(response.SuccessWithData(data))
if err != nil {
return "", err
}
diff --git a/app/core/api/internal/logic/oauth/github_callback_logic.go b/app/core/api/internal/logic/oauth/github_callback_logic.go
index 31a512e..89fcf0e 100644
--- a/app/core/api/internal/logic/oauth/github_callback_logic.go
+++ b/app/core/api/internal/logic/oauth/github_callback_logic.go
@@ -149,7 +149,7 @@ func (l *GithubCallbackLogic) GithubCallback(w http.ResponseWriter, r *http.Requ
return "", err
}
- data, err := HandleOauthLoginResponse(addUser, l.svcCtx, r, w, l.ctx)
+ data, err := HandleOauthLoginResponse(addUser, l.svcCtx, r, l.ctx)
if err != nil {
_ = tx.Rollback()
return "", err
@@ -167,7 +167,7 @@ func (l *GithubCallbackLogic) GithubCallback(w http.ResponseWriter, r *http.Requ
return "", err
}
- data, err := HandleOauthLoginResponse(authUserInfo, l.svcCtx, r, w, l.ctx)
+ data, err := HandleOauthLoginResponse(authUserInfo, l.svcCtx, r, l.ctx)
if err != nil {
_ = tx.Rollback()
return "", err
diff --git a/app/core/api/internal/logic/oauth/qq_callback_logic.go b/app/core/api/internal/logic/oauth/qq_callback_logic.go
index 0163434..63fb2ff 100644
--- a/app/core/api/internal/logic/oauth/qq_callback_logic.go
+++ b/app/core/api/internal/logic/oauth/qq_callback_logic.go
@@ -149,7 +149,7 @@ func (l *QqCallbackLogic) QqCallback(w http.ResponseWriter, r *http.Request, req
return "", err
}
- data, err := HandleOauthLoginResponse(addUser, l.svcCtx, r, w, l.ctx)
+ data, err := HandleOauthLoginResponse(addUser, l.svcCtx, r, l.ctx)
if err != nil {
_ = tx.Rollback()
return "", err
@@ -167,7 +167,7 @@ func (l *QqCallbackLogic) QqCallback(w http.ResponseWriter, r *http.Request, req
return "", err
}
- data, err := HandleOauthLoginResponse(authUserInfo, l.svcCtx, r, w, l.ctx)
+ data, err := HandleOauthLoginResponse(authUserInfo, l.svcCtx, r, l.ctx)
if err != nil {
_ = tx.Rollback()
return "", err
diff --git a/app/core/api/internal/logic/oauth/wechat_callback_logic.go b/app/core/api/internal/logic/oauth/wechat_callback_logic.go
deleted file mode 100644
index 91a082f..0000000
--- a/app/core/api/internal/logic/oauth/wechat_callback_logic.go
+++ /dev/null
@@ -1,208 +0,0 @@
-package oauth
-
-import (
- "context"
- "encoding/json"
- "errors"
- "net/http"
- "strconv"
- "strings"
-
- "github.com/ArtisanCloud/PowerLibs/v3/http/helper"
- "github.com/ArtisanCloud/PowerWeChat/v3/src/kernel/contract"
- "github.com/ArtisanCloud/PowerWeChat/v3/src/kernel/messages"
- models2 "github.com/ArtisanCloud/PowerWeChat/v3/src/kernel/models"
- "github.com/ArtisanCloud/PowerWeChat/v3/src/officialAccount/server/handlers/models"
- "github.com/yitter/idgenerator-go/idgen"
- "github.com/zeromicro/go-zero/core/logx"
- "gorm.io/gorm"
-
- "schisandra-album-cloud-microservices/app/core/api/common/constant"
- "schisandra-album-cloud-microservices/app/core/api/common/i18n"
- randomname "schisandra-album-cloud-microservices/app/core/api/common/random_name"
- "schisandra-album-cloud-microservices/app/core/api/common/utils"
- "schisandra-album-cloud-microservices/app/core/api/internal/logic/user"
- "schisandra-album-cloud-microservices/app/core/api/internal/logic/websocket"
- "schisandra-album-cloud-microservices/app/core/api/internal/svc"
- "schisandra-album-cloud-microservices/app/core/api/repository/mysql/model"
-)
-
-type WechatCallbackLogic struct {
- logx.Logger
- ctx context.Context
- svcCtx *svc.ServiceContext
-}
-
-func NewWechatCallbackLogic(ctx context.Context, svcCtx *svc.ServiceContext) *WechatCallbackLogic {
- return &WechatCallbackLogic{
- Logger: logx.WithContext(ctx),
- ctx: ctx,
- svcCtx: svcCtx,
- }
-}
-
-func (l *WechatCallbackLogic) WechatCallback(w http.ResponseWriter, r *http.Request) error {
- _, err := l.svcCtx.WechatPublic.Server.VerifyURL(r)
- if err != nil {
- return err
- }
- rs, err := l.svcCtx.WechatPublic.Server.Notify(r, func(event contract.EventInterface) interface{} {
- switch event.GetMsgType() {
- case models2.CALLBACK_MSG_TYPE_EVENT:
- switch event.GetEvent() {
- case models.CALLBACK_EVENT_SUBSCRIBE:
- msg := models.EventSubscribe{}
- err = event.ReadMessage(&msg)
- if err != nil {
- println(err.Error())
- return err
- }
- key := strings.TrimPrefix(msg.EventKey, "qrscene_")
- err = l.HandlerWechatLogin(msg.FromUserName, key, w, r)
- if err != nil {
- return messages.NewText(i18n.FormatText(l.ctx, "login.loginFailed"))
- }
- return messages.NewText(i18n.FormatText(l.ctx, "login.loginSuccess"))
-
- case models.CALLBACK_EVENT_UNSUBSCRIBE:
- msg := models.EventUnSubscribe{}
- err = event.ReadMessage(&msg)
- if err != nil {
- println(err.Error())
- return err
- }
- return messages.NewText("ok")
-
- case models.CALLBACK_EVENT_SCAN:
- msg := models.EventScan{}
- err = event.ReadMessage(&msg)
- if err != nil {
- println(err.Error())
- return err
- }
- err = l.HandlerWechatLogin(msg.FromUserName, msg.EventKey, w, r)
- if err != nil {
- return messages.NewText(i18n.FormatText(l.ctx, "login.loginFailed"))
- }
- return messages.NewText(i18n.FormatText(l.ctx, "login.loginSuccess"))
-
- }
-
- case models2.CALLBACK_MSG_TYPE_TEXT:
- msg := models.MessageText{}
- err = event.ReadMessage(&msg)
- if err != nil {
- println(err.Error())
- return err
- }
- }
- return messages.NewText("ok")
-
- })
- if err != nil {
- return err
- }
- err = helper.HttpResponseSend(rs, w)
- if err != nil {
- return err
- }
- return nil
-}
-
-// HandlerWechatLogin 处理微信登录
-func (l *WechatCallbackLogic) HandlerWechatLogin(openId string, clientId string, w http.ResponseWriter, r *http.Request) error {
- if openId == "" {
- return errors.New("openId is empty")
- }
- tx := l.svcCtx.DB.Begin()
-
- userSocial := l.svcCtx.DB.ScaAuthUserSocial
- socialUser, err := tx.ScaAuthUserSocial.Where(userSocial.OpenID.Eq(openId), userSocial.Source.Eq(constant.OAuthSourceWechat)).First()
- if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
- return err
- }
-
- if socialUser == nil {
- // 创建用户
- uid := idgen.NextId()
- uidStr := strconv.FormatInt(uid, 10)
- avatar := utils.GenerateAvatar(uidStr)
- name := randomname.GenerateName()
-
- male := constant.Male
- addUser := &model.ScaAuthUser{
- UID: uidStr,
- Avatar: avatar,
- Username: openId,
- Nickname: name,
- Gender: male,
- }
- err = tx.ScaAuthUser.Create(addUser)
- if err != nil {
- _ = tx.Rollback()
- return err
- }
-
- wechatUser := constant.OAuthSourceWechat
- newSocialUser := &model.ScaAuthUserSocial{
- UserID: uidStr,
- OpenID: openId,
- Source: wechatUser,
- }
- err = tx.ScaAuthUserSocial.Create(newSocialUser)
- if err != nil {
- _ = tx.Rollback()
- return err
- }
-
- if res, err := l.svcCtx.CasbinEnforcer.AddRoleForUser(uidStr, constant.User); !res || err != nil {
- _ = tx.Rollback()
- return err
- }
-
- data, err := user.HandleUserLogin(addUser, l.svcCtx, true, r, w, l.ctx)
- if err != nil {
- _ = tx.Rollback()
- return err
- }
- marshal, err := json.Marshal(data)
- if err != nil {
- _ = tx.Rollback()
- return err
- }
- err = websocket.QrcodeWebSocketHandler.SendMessageToClient(clientId, marshal)
- if err != nil {
- _ = tx.Rollback()
- return err
- }
-
- } else {
- authUser := l.svcCtx.DB.ScaAuthUser
-
- authUserInfo, err := tx.ScaAuthUser.Where(authUser.UID.Eq(socialUser.UserID)).First()
- if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
- _ = tx.Rollback()
- return err
- }
-
- data, err := user.HandleUserLogin(authUserInfo, l.svcCtx, true, r, w, l.ctx)
- if err != nil {
- _ = tx.Rollback()
- return err
- }
- marshal, err := json.Marshal(data)
- if err != nil {
- _ = tx.Rollback()
- return err
- }
- err = websocket.QrcodeWebSocketHandler.SendMessageToClient(clientId, marshal)
- if err != nil {
- _ = tx.Rollback()
- return err
- }
- }
- if err = tx.Commit(); err != nil {
- return err
- }
- return nil
-}
diff --git a/app/core/api/internal/logic/oauth/wechat_offiaccount_callback_logic.go b/app/core/api/internal/logic/oauth/wechat_offiaccount_callback_logic.go
new file mode 100644
index 0000000..162f0a5
--- /dev/null
+++ b/app/core/api/internal/logic/oauth/wechat_offiaccount_callback_logic.go
@@ -0,0 +1,112 @@
+package oauth
+
+import (
+ "context"
+ "encoding/json"
+ "github.com/ArtisanCloud/PowerWeChat/v3/src/kernel/contract"
+ "github.com/ArtisanCloud/PowerWeChat/v3/src/kernel/messages"
+ models2 "github.com/ArtisanCloud/PowerWeChat/v3/src/kernel/models"
+ "github.com/ArtisanCloud/PowerWeChat/v3/src/officialAccount/server/handlers/models"
+ "net/http"
+ "schisandra-album-cloud-microservices/app/core/api/common/i18n"
+ "schisandra-album-cloud-microservices/app/core/api/common/response"
+ "schisandra-album-cloud-microservices/app/core/api/internal/logic/websocket"
+ "strings"
+
+ "github.com/zeromicro/go-zero/core/logx"
+ "schisandra-album-cloud-microservices/app/core/api/internal/svc"
+)
+
+type WechatOffiaccountCallbackLogic struct {
+ logx.Logger
+ ctx context.Context
+ svcCtx *svc.ServiceContext
+}
+type MessageData struct {
+ Openid string `json:"openid"`
+ ClientId string `json:"client_id"`
+}
+
+func NewWechatOffiaccountCallbackLogic(ctx context.Context, svcCtx *svc.ServiceContext) *WechatOffiaccountCallbackLogic {
+ return &WechatOffiaccountCallbackLogic{
+ Logger: logx.WithContext(ctx),
+ ctx: ctx,
+ svcCtx: svcCtx,
+ }
+}
+
+func (l *WechatOffiaccountCallbackLogic) WechatOffiaccountCallback(r *http.Request) (*http.Response, error) {
+ rs, err := l.svcCtx.WechatOfficial.Server.Notify(r, func(event contract.EventInterface) interface{} {
+ switch event.GetMsgType() {
+ case models2.CALLBACK_MSG_TYPE_EVENT:
+ switch event.GetEvent() {
+ case models.CALLBACK_EVENT_SUBSCRIBE:
+ msg := models.EventSubscribe{}
+ err := event.ReadMessage(&msg)
+ if err != nil {
+ logx.Error(err.Error())
+ return "error"
+ }
+ key := strings.TrimPrefix(msg.EventKey, "qrscene_")
+ err = l.SendMessage(msg.FromUserName, key)
+ if err != nil {
+ return messages.NewText(i18n.FormatText(l.ctx, "login.loginFailed"))
+ }
+ return messages.NewText(i18n.FormatText(l.ctx, "login.loginSuccess"))
+
+ case models.CALLBACK_EVENT_UNSUBSCRIBE:
+ msg := models.EventUnSubscribe{}
+ err := event.ReadMessage(&msg)
+ if err != nil {
+ logx.Error(err.Error())
+ return "error"
+ }
+ return messages.NewText("ok")
+
+ case models.CALLBACK_EVENT_SCAN:
+ msg := models.EventScan{}
+ err := event.ReadMessage(&msg)
+ if err != nil {
+ logx.Error(err.Error())
+ return "error"
+ }
+ err = l.SendMessage(msg.FromUserName, msg.EventKey)
+ if err != nil {
+ return messages.NewText(i18n.FormatText(l.ctx, "login.loginFailed"))
+ }
+ return messages.NewText(i18n.FormatText(l.ctx, "login.loginSuccess"))
+
+ }
+
+ case models2.CALLBACK_MSG_TYPE_TEXT:
+ msg := models.MessageText{}
+ err := event.ReadMessage(&msg)
+ if err != nil {
+ logx.Error(err.Error())
+ return "error"
+ }
+ }
+ return messages.NewText("ok")
+ })
+ if err != nil {
+ return nil, err
+ }
+ return rs, nil
+}
+
+// SendMessage 发送消息到客户端
+func (l *WechatOffiaccountCallbackLogic) SendMessage(openId string, clientId string) error {
+ messageData := MessageData{
+ Openid: openId,
+ ClientId: clientId,
+ }
+ jsonData, err := json.Marshal(response.SuccessWithData(messageData))
+ if err != nil {
+ return err
+ }
+ err = websocket.QrcodeWebSocketHandler.SendMessageToClient(clientId, jsonData)
+ if err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/app/core/api/internal/logic/oauth/wechat_offiaccount_callback_verify_logic.go b/app/core/api/internal/logic/oauth/wechat_offiaccount_callback_verify_logic.go
new file mode 100644
index 0000000..3bb5bda
--- /dev/null
+++ b/app/core/api/internal/logic/oauth/wechat_offiaccount_callback_verify_logic.go
@@ -0,0 +1,31 @@
+package oauth
+
+import (
+ "context"
+ "net/http"
+
+ "github.com/zeromicro/go-zero/core/logx"
+ "schisandra-album-cloud-microservices/app/core/api/internal/svc"
+)
+
+type WechatOffiaccountCallbackVerifyLogic struct {
+ logx.Logger
+ ctx context.Context
+ svcCtx *svc.ServiceContext
+}
+
+func NewWechatOffiaccountCallbackVerifyLogic(ctx context.Context, svcCtx *svc.ServiceContext) *WechatOffiaccountCallbackVerifyLogic {
+ return &WechatOffiaccountCallbackVerifyLogic{
+ Logger: logx.WithContext(ctx),
+ ctx: ctx,
+ svcCtx: svcCtx,
+ }
+}
+
+func (l *WechatOffiaccountCallbackVerifyLogic) WechatOffiaccountCallbackVerify(r *http.Request) (*http.Response, error) {
+ rs, err := l.svcCtx.WechatOfficial.Server.VerifyURL(r)
+ if err != nil {
+ return nil, err
+ }
+ return rs, nil
+}
diff --git a/app/core/api/internal/logic/token/refresh_token_logic.go b/app/core/api/internal/logic/token/refresh_token_logic.go
index 2a45c50..9fe6dc2 100644
--- a/app/core/api/internal/logic/token/refresh_token_logic.go
+++ b/app/core/api/internal/logic/token/refresh_token_logic.go
@@ -30,12 +30,8 @@ func NewRefreshTokenLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Refr
}
func (l *RefreshTokenLogic) RefreshToken(r *http.Request) (resp *types.Response, err error) {
- session, err := l.svcCtx.Session.Get(r, constant.SESSION_KEY)
- if err != nil {
- return nil, err
- }
- userId, ok := session.Values["user_id"].(string)
- if !ok {
+ userId := r.Header.Get(constant.UID_HEADER_KEY)
+ if userId == "" {
return response.ErrorWithCode(403), nil
}
tokenData := l.svcCtx.RedisClient.Get(l.ctx, constant.UserTokenPrefix+userId).Val()
@@ -47,6 +43,9 @@ func (l *RefreshTokenLogic) RefreshToken(r *http.Request) (resp *types.Response,
if err != nil {
return nil, err
}
+ if redisTokenData.Revoked {
+ return response.ErrorWithCode(403), nil
+ }
refreshToken, result := jwt.ParseRefreshToken(l.svcCtx.Config.Auth.AccessSecret, redisTokenData.RefreshToken)
if !result {
return response.ErrorWithCode(403), nil
@@ -62,6 +61,7 @@ func (l *RefreshTokenLogic) RefreshToken(r *http.Request) (resp *types.Response,
AccessToken: accessToken,
RefreshToken: redisTokenData.RefreshToken,
UID: refreshToken.UserID,
+ Revoked: false,
}
err = l.svcCtx.RedisClient.Set(l.ctx, constant.UserTokenPrefix+refreshToken.UserID, redisToken, time.Hour*24*7).Err()
if err != nil {
diff --git a/app/core/api/internal/logic/user/account_login_logic.go b/app/core/api/internal/logic/user/account_login_logic.go
index 25daa8e..287e1c5 100644
--- a/app/core/api/internal/logic/user/account_login_logic.go
+++ b/app/core/api/internal/logic/user/account_login_logic.go
@@ -3,7 +3,8 @@ package user
import (
"context"
"errors"
- "github.com/rbcervilla/redisstore/v9"
+ "github.com/lionsoul2014/ip2region/binding/golang/xdb"
+ "github.com/mssola/useragent"
"net/http"
"time"
@@ -65,19 +66,20 @@ func (l *AccountLoginLogic) AccountLogin(w http.ResponseWriter, r *http.Request,
if !utils.Verify(userInfo.Password, req.Password) {
return response.ErrorWithI18n(l.ctx, "login.invalidPassword"), nil
}
- data, err := HandleUserLogin(userInfo, l.svcCtx, req.AutoLogin, r, w, l.ctx)
+ data, err := HandleLoginJWT(userInfo, l.svcCtx, req.AutoLogin, r, l.ctx)
if err != nil {
return nil, err
}
- // 记录用户登录设备
- if err = GetUserLoginDevice(userInfo.UID, r, l.svcCtx.Ip2Region, l.svcCtx.DB); err != nil {
- return nil, err
- }
return response.SuccessWithData(data), nil
}
-// HandleUserLogin 处理用户登录
-func HandleUserLogin(user *model.ScaAuthUser, svcCtx *svc.ServiceContext, autoLogin bool, r *http.Request, w http.ResponseWriter, ctx context.Context) (*types.LoginResponse, error) {
+// HandleLoginJWT 处理用户登录
+func HandleLoginJWT(user *model.ScaAuthUser, svcCtx *svc.ServiceContext, autoLogin bool, r *http.Request, ctx context.Context) (*types.LoginResponse, error) {
+ // 获取用户登录设备
+ err := GetUserLoginDevice(user.UID, r, svcCtx.Ip2Region, svcCtx.DB)
+ if err != nil {
+ return nil, err
+ }
// 生成jwt token
accessToken := jwt.GenerateAccessToken(svcCtx.Config.Auth.AccessSecret, jwt.AccessJWTPayload{
UserID: user.UID,
@@ -85,9 +87,9 @@ func HandleUserLogin(user *model.ScaAuthUser, svcCtx *svc.ServiceContext, autoLo
})
var days time.Duration
if autoLogin {
- days = 7 * 24 * time.Hour
+ days = 24 * time.Hour
} else {
- days = time.Hour * 24
+ days = time.Hour * 1
}
refreshToken := jwt.GenerateRefreshToken(svcCtx.Config.Auth.AccessSecret, jwt.RefreshJWTPayload{
UserID: user.UID,
@@ -106,29 +108,76 @@ func HandleUserLogin(user *model.ScaAuthUser, svcCtx *svc.ServiceContext, autoLo
AccessToken: accessToken,
RefreshToken: refreshToken,
UID: user.UID,
+ Revoked: false,
}
- err := svcCtx.RedisClient.Set(ctx, constant.UserTokenPrefix+user.UID, redisToken, days).Err()
- if err != nil {
- return nil, err
- }
- err = HandlerSession(r, w, user.UID, svcCtx.Session)
+ err = svcCtx.RedisClient.Set(ctx, constant.UserTokenPrefix+user.UID, redisToken, days).Err()
if err != nil {
return nil, err
}
return &data, nil
-
}
-// HandlerSession is a function to set the user_id in the session
-func HandlerSession(r *http.Request, w http.ResponseWriter, userID string, redisSession *redisstore.RedisStore) error {
- session, err := redisSession.Get(r, constant.SESSION_KEY)
+// GetUserLoginDevice 获取用户登录设备
+func GetUserLoginDevice(userId string, r *http.Request, ip2location *xdb.Searcher, DB *query.Query) error {
+ userAgent := r.UserAgent()
+ if userAgent == "" {
+ return errors.New("user agent not found")
+ }
+ ip := utils.GetClientIP(r)
+ location, err := ip2location.SearchByStr(ip)
if err != nil {
return err
}
- session.Values["user_id"] = userID
- err = session.Save(r, w)
- if err != nil {
+ location = utils.RemoveZeroAndAdjust(location)
+
+ ua := useragent.New(userAgent)
+ isBot := ua.Bot()
+ browser, browserVersion := ua.Browser()
+ os := ua.OS()
+ mobile := ua.Mobile()
+ mozilla := ua.Mozilla()
+ platform := ua.Platform()
+ engine, engineVersion := ua.Engine()
+ var newIsBot int64 = 0
+ var newIsMobile int64 = 0
+ if isBot {
+ newIsBot = 1
+ }
+ if mobile {
+ newIsMobile = 1
+ }
+ userDevice := DB.ScaAuthUserDevice
+ device, err := userDevice.Where(userDevice.UserID.Eq(userId), userDevice.IP.Eq(ip), userDevice.Agent.Eq(userAgent)).First()
+ if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return err
}
- return nil
+ newDevice := &model.ScaAuthUserDevice{
+ UserID: userId,
+ Bot: newIsBot,
+ Agent: userAgent,
+ Browser: browser,
+ BrowserVersion: browserVersion,
+ EngineName: engine,
+ EngineVersion: engineVersion,
+ IP: ip,
+ Location: location,
+ OperatingSystem: os,
+ Mobile: newIsMobile,
+ Mozilla: mozilla,
+ Platform: platform,
+ }
+ if device == nil {
+ // 创建新的设备记录
+ err = DB.ScaAuthUserDevice.Create(newDevice)
+ if err != nil {
+ return err
+ }
+ return nil
+ } else {
+ resultInfo, err := userDevice.Where(userDevice.ID.Eq(device.ID)).Updates(newDevice)
+ if err != nil || resultInfo.RowsAffected == 0 {
+ return errors.New("update device failed")
+ }
+ return nil
+ }
}
diff --git a/app/core/api/internal/logic/user/get_user_device_logic.go b/app/core/api/internal/logic/user/get_user_device_logic.go
deleted file mode 100644
index c77962e..0000000
--- a/app/core/api/internal/logic/user/get_user_device_logic.go
+++ /dev/null
@@ -1,115 +0,0 @@
-package user
-
-import (
- "context"
- "errors"
- "github.com/lionsoul2014/ip2region/binding/golang/xdb"
- "github.com/mssola/useragent"
- "gorm.io/gorm"
- "net/http"
- "schisandra-album-cloud-microservices/app/core/api/common/jwt"
- "schisandra-album-cloud-microservices/app/core/api/common/response"
- "schisandra-album-cloud-microservices/app/core/api/common/utils"
- "schisandra-album-cloud-microservices/app/core/api/repository/mysql/model"
- "schisandra-album-cloud-microservices/app/core/api/repository/mysql/query"
-
- "schisandra-album-cloud-microservices/app/core/api/internal/svc"
- "schisandra-album-cloud-microservices/app/core/api/internal/types"
-
- "github.com/zeromicro/go-zero/core/logx"
-)
-
-type GetUserDeviceLogic struct {
- logx.Logger
- ctx context.Context
- svcCtx *svc.ServiceContext
-}
-
-func NewGetUserDeviceLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUserDeviceLogic {
- return &GetUserDeviceLogic{
- Logger: logx.WithContext(ctx),
- ctx: ctx,
- svcCtx: svcCtx,
- }
-}
-
-func (l *GetUserDeviceLogic) GetUserDevice(r *http.Request, w http.ResponseWriter, req *types.UserDeviceRequest) (resp *types.Response, err error) {
- token, ok := jwt.ParseAccessToken(l.svcCtx.Config.Auth.AccessSecret, req.AccessToken)
- if !ok {
- return response.Error(), nil
- }
- err = HandlerSession(r, w, token.UserID, l.svcCtx.Session)
- if err != nil {
- return nil, err
- }
- err = GetUserLoginDevice(token.UserID, r, l.svcCtx.Ip2Region, l.svcCtx.DB)
- if err != nil {
- return nil, err
- }
- return response.Success(), nil
-}
-
-// GetUserLoginDevice 获取用户登录设备
-func GetUserLoginDevice(userId string, r *http.Request, ip2location *xdb.Searcher, DB *query.Query) error {
- userAgent := r.Header.Get("User-Agent")
- if userAgent == "" {
- return errors.New("user agent not found")
- }
- ip := utils.GetClientIP(r)
- location, err := ip2location.SearchByStr(ip)
- if err != nil {
- return err
- }
- location = utils.RemoveZeroAndAdjust(location)
-
- ua := useragent.New(userAgent)
- isBot := ua.Bot()
- browser, browserVersion := ua.Browser()
- os := ua.OS()
- mobile := ua.Mobile()
- mozilla := ua.Mozilla()
- platform := ua.Platform()
- engine, engineVersion := ua.Engine()
- var newIsBot int64 = 0
- var newIsMobile int64 = 0
- if isBot {
- newIsBot = 1
- }
- if mobile {
- newIsMobile = 1
- }
- userDevice := DB.ScaAuthUserDevice
- device, err := userDevice.Where(userDevice.UserID.Eq(userId), userDevice.IP.Eq(ip), userDevice.Agent.Eq(userAgent)).First()
- if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
- return err
- }
- newDevice := &model.ScaAuthUserDevice{
- UserID: userId,
- Bot: newIsBot,
- Agent: userAgent,
- Browser: browser,
- BrowserVersion: browserVersion,
- EngineName: engine,
- EngineVersion: engineVersion,
- IP: ip,
- Location: location,
- OperatingSystem: os,
- Mobile: newIsMobile,
- Mozilla: mozilla,
- Platform: platform,
- }
- if device == nil {
- // 创建新的设备记录
- err = DB.ScaAuthUserDevice.Create(newDevice)
- if err != nil {
- return err
- }
- return nil
- } else {
- resultInfo, err := userDevice.Where(userDevice.ID.Eq(device.ID)).Updates(newDevice)
- if err != nil || resultInfo.RowsAffected == 0 {
- return errors.New("update device failed")
- }
- return nil
- }
-}
diff --git a/app/core/api/internal/logic/oauth/get_wechat_qrcode_logic.go b/app/core/api/internal/logic/user/get_wechat_offiaccount_qrcode_logic.go
similarity index 75%
rename from app/core/api/internal/logic/oauth/get_wechat_qrcode_logic.go
rename to app/core/api/internal/logic/user/get_wechat_offiaccount_qrcode_logic.go
index bf2f6f3..353b7d2 100644
--- a/app/core/api/internal/logic/oauth/get_wechat_qrcode_logic.go
+++ b/app/core/api/internal/logic/user/get_wechat_offiaccount_qrcode_logic.go
@@ -1,37 +1,36 @@
-package oauth
+package user
import (
"context"
"encoding/json"
- "net/http"
- "time"
-
"github.com/ArtisanCloud/PowerWeChat/v3/src/basicService/qrCode/response"
-
+ "net/http"
"schisandra-album-cloud-microservices/app/core/api/common/constant"
response2 "schisandra-album-cloud-microservices/app/core/api/common/response"
"schisandra-album-cloud-microservices/app/core/api/common/utils"
+ "time"
+
"schisandra-album-cloud-microservices/app/core/api/internal/svc"
"schisandra-album-cloud-microservices/app/core/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
-type GetWechatQrcodeLogic struct {
+type GetWechatOffiaccountQrcodeLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
-func NewGetWechatQrcodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetWechatQrcodeLogic {
- return &GetWechatQrcodeLogic{
+func NewGetWechatOffiaccountQrcodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetWechatOffiaccountQrcodeLogic {
+ return &GetWechatOffiaccountQrcodeLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
-func (l *GetWechatQrcodeLogic) GetWechatQrcode(r *http.Request, req *types.OAuthWechatRequest) (resp *types.Response, err error) {
+func (l *GetWechatOffiaccountQrcodeLogic) GetWechatOffiaccountQrcode(r *http.Request, req *types.OAuthWechatRequest) (resp *types.Response, err error) {
ip := utils.GetClientIP(r) // 使用工具函数获取客户端IP
key := constant.UserQrcodePrefix + ip
@@ -46,7 +45,7 @@ func (l *GetWechatQrcodeLogic) GetWechatQrcode(r *http.Request, req *types.OAuth
}
// 生成临时二维码
- data, err := l.svcCtx.WechatPublic.QRCode.Temporary(l.ctx, req.Client_id, 7*24*3600)
+ data, err := l.svcCtx.WechatOfficial.QRCode.Temporary(l.ctx, req.Client_id, 7*24*3600)
if err != nil {
return nil, err
}
diff --git a/app/core/api/internal/logic/user/phone_login_logic.go b/app/core/api/internal/logic/user/phone_login_logic.go
index 3676575..e40019a 100644
--- a/app/core/api/internal/logic/user/phone_login_logic.go
+++ b/app/core/api/internal/logic/user/phone_login_logic.go
@@ -79,32 +79,22 @@ func (l *PhoneLoginLogic) PhoneLogin(r *http.Request, w http.ResponseWriter, req
_ = tx.Rollback()
return nil, err
}
- data, err := HandleUserLogin(user, l.svcCtx, req.AutoLogin, r, w, l.ctx)
+ data, err := HandleLoginJWT(user, l.svcCtx, req.AutoLogin, r, l.ctx)
if err != nil {
_ = tx.Rollback()
return nil, err
}
- // 记录用户登录设备
- if err = GetUserLoginDevice(user.UID, r, l.svcCtx.Ip2Region, l.svcCtx.DB); err != nil {
- _ = tx.Rollback()
- return nil, err
- }
err = tx.Commit()
if err != nil {
return nil, err
}
return response.SuccessWithData(data), nil
} else {
- data, err := HandleUserLogin(userInfo, l.svcCtx, req.AutoLogin, r, w, l.ctx)
+ data, err := HandleLoginJWT(userInfo, l.svcCtx, req.AutoLogin, r, l.ctx)
if err != nil {
_ = tx.Rollback()
return nil, err
}
- // 记录用户登录设备
- if err = GetUserLoginDevice(userInfo.UID, r, l.svcCtx.Ip2Region, l.svcCtx.DB); err != nil {
- _ = tx.Rollback()
- return nil, err
- }
err = tx.Commit()
if err != nil {
return nil, err
diff --git a/app/core/api/internal/logic/user/wechat_offiaccount_login_logic.go b/app/core/api/internal/logic/user/wechat_offiaccount_login_logic.go
new file mode 100644
index 0000000..98d1707
--- /dev/null
+++ b/app/core/api/internal/logic/user/wechat_offiaccount_login_logic.go
@@ -0,0 +1,107 @@
+package user
+
+import (
+ "context"
+ "errors"
+ "github.com/yitter/idgenerator-go/idgen"
+ "gorm.io/gorm"
+ "net/http"
+ "schisandra-album-cloud-microservices/app/core/api/common/constant"
+ randomname "schisandra-album-cloud-microservices/app/core/api/common/random_name"
+ "schisandra-album-cloud-microservices/app/core/api/common/response"
+ "schisandra-album-cloud-microservices/app/core/api/common/utils"
+ "schisandra-album-cloud-microservices/app/core/api/repository/mysql/model"
+ "strconv"
+
+ "schisandra-album-cloud-microservices/app/core/api/internal/svc"
+ "schisandra-album-cloud-microservices/app/core/api/internal/types"
+
+ "github.com/zeromicro/go-zero/core/logx"
+)
+
+type WechatOffiaccountLoginLogic struct {
+ logx.Logger
+ ctx context.Context
+ svcCtx *svc.ServiceContext
+}
+
+func NewWechatOffiaccountLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *WechatOffiaccountLoginLogic {
+ return &WechatOffiaccountLoginLogic{
+ Logger: logx.WithContext(ctx),
+ ctx: ctx,
+ svcCtx: svcCtx,
+ }
+}
+
+func (l *WechatOffiaccountLoginLogic) WechatOffiaccountLogin(r *http.Request, req *types.WechatOffiaccountLoginRequest) (resp *types.Response, err error) {
+ tx := l.svcCtx.DB.Begin()
+ userSocial := l.svcCtx.DB.ScaAuthUserSocial
+ socialUser, err := tx.ScaAuthUserSocial.Where(userSocial.OpenID.Eq(req.Openid), userSocial.Source.Eq(constant.OAuthSourceWechat)).First()
+ if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
+ return nil, err
+ }
+ if socialUser == nil {
+ // 创建用户
+ uid := idgen.NextId()
+ uidStr := strconv.FormatInt(uid, 10)
+ avatar := utils.GenerateAvatar(uidStr)
+ name := randomname.GenerateName()
+
+ addUser := &model.ScaAuthUser{
+ UID: uidStr,
+ Avatar: avatar,
+ Username: req.Openid,
+ Nickname: name,
+ Gender: constant.Male,
+ }
+ err = tx.ScaAuthUser.Create(addUser)
+ if err != nil {
+ _ = tx.Rollback()
+ return nil, err
+ }
+
+ newSocialUser := &model.ScaAuthUserSocial{
+ UserID: uidStr,
+ OpenID: req.Openid,
+ Source: constant.OAuthSourceWechat,
+ }
+ err = tx.ScaAuthUserSocial.Create(newSocialUser)
+ if err != nil {
+ _ = tx.Rollback()
+ return nil, err
+ }
+
+ if res, err := l.svcCtx.CasbinEnforcer.AddRoleForUser(uidStr, constant.User); !res || err != nil {
+ _ = tx.Rollback()
+ return nil, err
+ }
+
+ data, err := HandleLoginJWT(addUser, l.svcCtx, true, r, l.ctx)
+ if err != nil {
+ _ = tx.Rollback()
+ return nil, err
+ }
+ if err = tx.Commit(); err != nil {
+ return nil, err
+ }
+ return response.SuccessWithData(data), nil
+ } else {
+ authUser := l.svcCtx.DB.ScaAuthUser
+
+ authUserInfo, err := tx.ScaAuthUser.Where(authUser.UID.Eq(socialUser.UserID)).First()
+ if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
+ _ = tx.Rollback()
+ return nil, err
+ }
+ data, err := HandleLoginJWT(authUserInfo, l.svcCtx, true, r, l.ctx)
+ if err != nil {
+ _ = tx.Rollback()
+ return nil, err
+ }
+ if err = tx.Commit(); err != nil {
+ return nil, err
+ }
+ return response.SuccessWithData(data), nil
+
+ }
+}
diff --git a/app/core/api/internal/middleware/authorization_middleware.go b/app/core/api/internal/middleware/authorization_middleware.go
new file mode 100644
index 0000000..dc8a63b
--- /dev/null
+++ b/app/core/api/internal/middleware/authorization_middleware.go
@@ -0,0 +1,31 @@
+package middleware
+
+import (
+ "github.com/redis/go-redis/v9"
+ "github.com/zeromicro/go-zero/rest/httpx"
+ "net/http"
+ "schisandra-album-cloud-microservices/app/core/api/common/constant"
+ "schisandra-album-cloud-microservices/app/core/api/common/response"
+)
+
+type AuthorizationMiddleware struct {
+ Redis *redis.Client
+}
+
+func NewAuthorizationMiddleware(redis *redis.Client) *AuthorizationMiddleware {
+ return &AuthorizationMiddleware{
+ Redis: redis,
+ }
+}
+
+func (m *AuthorizationMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+ userId := r.Context().Value("user_id").(string)
+ redisToken := m.Redis.Get(r.Context(), constant.UserTokenPrefix+userId).Val()
+ if redisToken == "" {
+ httpx.OkJson(w, response.ErrorWithCodeMessage(403, "unauthorized"))
+ return
+ }
+ next(w, r)
+ }
+}
diff --git a/app/core/api/internal/middleware/casbinverify_middleware.go b/app/core/api/internal/middleware/casbinverify_middleware.go
index 19d39d1..ab0019d 100644
--- a/app/core/api/internal/middleware/casbinverify_middleware.go
+++ b/app/core/api/internal/middleware/casbinverify_middleware.go
@@ -1,37 +1,24 @@
package middleware
import (
+ "github.com/casbin/casbin/v2"
"net/http"
"schisandra-album-cloud-microservices/app/core/api/common/constant"
-
- "github.com/casbin/casbin/v2"
- "github.com/rbcervilla/redisstore/v9"
)
type CasbinVerifyMiddleware struct {
- casbin *casbin.SyncedCachedEnforcer
- session *redisstore.RedisStore
+ casbin *casbin.SyncedCachedEnforcer
}
-func NewCasbinVerifyMiddleware(casbin *casbin.SyncedCachedEnforcer, session *redisstore.RedisStore) *CasbinVerifyMiddleware {
+func NewCasbinVerifyMiddleware(casbin *casbin.SyncedCachedEnforcer) *CasbinVerifyMiddleware {
return &CasbinVerifyMiddleware{
- casbin: casbin,
- session: session,
+ casbin: casbin,
}
}
func (m *CasbinVerifyMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
- session, err := m.session.Get(r, constant.SESSION_KEY)
- if err != nil {
- http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
- return
- }
- userId, ok := session.Values["user_id"].(string)
- if !ok {
- http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
- return
- }
+ userId := r.Header.Get(constant.UID_HEADER_KEY)
correct, err := m.casbin.Enforce(userId, r.URL.Path, r.Method)
if err != nil || !correct {
http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
diff --git a/app/core/api/internal/svc/service_context.go b/app/core/api/internal/svc/service_context.go
index f1c9b81..d7233df 100644
--- a/app/core/api/internal/svc/service_context.go
+++ b/app/core/api/internal/svc/service_context.go
@@ -4,7 +4,6 @@ import (
"github.com/ArtisanCloud/PowerWeChat/v3/src/officialAccount"
"github.com/casbin/casbin/v2"
"github.com/lionsoul2014/ip2region/binding/golang/xdb"
- "github.com/rbcervilla/redisstore/v9"
"github.com/redis/go-redis/v9"
"github.com/wenlng/go-captcha/v2/rotate"
"github.com/wenlng/go-captcha/v2/slide"
@@ -20,7 +19,6 @@ import (
"schisandra-album-cloud-microservices/app/core/api/repository/mongodb"
"schisandra-album-cloud-microservices/app/core/api/repository/mysql"
"schisandra-album-cloud-microservices/app/core/api/repository/mysql/query"
- "schisandra-album-cloud-microservices/app/core/api/repository/redis_session"
"schisandra-album-cloud-microservices/app/core/api/repository/redisx"
"schisandra-album-cloud-microservices/app/core/api/repository/sensitivex"
"schisandra-album-cloud-microservices/app/core/api/repository/wechat_official"
@@ -30,13 +28,13 @@ type ServiceContext struct {
Config config.Config
SecurityHeadersMiddleware rest.Middleware
CasbinVerifyMiddleware rest.Middleware
+ AuthorizationMiddleware rest.Middleware
DB *query.Query
RedisClient *redis.Client
MongoClient *mongo.Database
- Session *redisstore.RedisStore
Ip2Region *xdb.Searcher
CasbinEnforcer *casbin.SyncedCachedEnforcer
- WechatPublic *officialAccount.OfficialAccount
+ WechatOfficial *officialAccount.OfficialAccount
Sensitive *sensitive.Manager
RotateCaptcha rotate.Captcha
SlideCaptcha slide.Captcha
@@ -46,18 +44,17 @@ func NewServiceContext(c config.Config) *ServiceContext {
redisClient := redisx.NewRedis(c.Redis.Host, c.Redis.Pass, c.Redis.DB)
db, queryDB := mysql.NewMySQL(c.Mysql.DataSource, c.Mysql.MaxOpenConn, c.Mysql.MaxIdleConn, redisClient)
casbinEnforcer := casbinx.NewCasbin(db)
- session := redis_session.NewRedisSession(redisClient)
return &ServiceContext{
Config: c,
SecurityHeadersMiddleware: middleware.NewSecurityHeadersMiddleware().Handle,
- CasbinVerifyMiddleware: middleware.NewCasbinVerifyMiddleware(casbinEnforcer, session).Handle,
+ CasbinVerifyMiddleware: middleware.NewCasbinVerifyMiddleware(casbinEnforcer).Handle,
+ AuthorizationMiddleware: middleware.NewAuthorizationMiddleware(redisClient).Handle,
DB: queryDB,
RedisClient: redisClient,
MongoClient: mongodb.NewMongoDB(c.Mongo.Uri, c.Mongo.Username, c.Mongo.Password, c.Mongo.AuthSource, c.Mongo.Database),
- Session: session,
Ip2Region: ip2region.NewIP2Region(),
CasbinEnforcer: casbinEnforcer,
- WechatPublic: wechat_official.NewWechatPublic(c.Wechat.AppID, c.Wechat.AppSecret, c.Wechat.Token, c.Wechat.AESKey, c.Redis.Host, c.Redis.Pass, c.Redis.DB),
+ WechatOfficial: wechat_official.NewWechatPublic(c.Wechat.AppID, c.Wechat.AppSecret, c.Wechat.Token, c.Wechat.AESKey, c.Redis.Host, c.Redis.Pass, c.Redis.DB),
Sensitive: sensitivex.NewSensitive(),
RotateCaptcha: captcha.NewRotateCaptcha(),
SlideCaptcha: captcha.NewSlideCaptcha(),
diff --git a/app/core/api/internal/types/token.go b/app/core/api/internal/types/token.go
index a7fa5ba..fea3007 100644
--- a/app/core/api/internal/types/token.go
+++ b/app/core/api/internal/types/token.go
@@ -6,6 +6,7 @@ type RedisToken struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
UID string `json:"uid"`
+ Revoked bool `json:"revoked" default:"false"`
}
func (res RedisToken) MarshalBinary() ([]byte, error) {
diff --git a/app/core/api/internal/types/types.go b/app/core/api/internal/types/types.go
index ed23728..81025a4 100644
--- a/app/core/api/internal/types/types.go
+++ b/app/core/api/internal/types/types.go
@@ -119,6 +119,7 @@ type UploadRequest struct {
UserId string `json:"user_id"`
}
-type UserDeviceRequest struct {
- AccessToken string `json:"access_token"`
+type WechatOffiaccountLoginRequest struct {
+ Openid string `json:"openid"`
+ ClientId string `json:"client_id"`
}
diff --git a/app/core/api/repository/redis_session/redis_session.go b/app/core/api/repository/redis_session/redis_session.go
deleted file mode 100644
index 871e923..0000000
--- a/app/core/api/repository/redis_session/redis_session.go
+++ /dev/null
@@ -1,28 +0,0 @@
-package redis_session
-
-import (
- "context"
- "net/http"
-
- "github.com/gorilla/sessions"
- "github.com/rbcervilla/redisstore/v9"
- "github.com/redis/go-redis/v9"
-
- "schisandra-album-cloud-microservices/app/core/api/common/constant"
-)
-
-func NewRedisSession(client *redis.Client) *redisstore.RedisStore {
- store, err := redisstore.NewRedisStore(context.Background(), client)
- if err != nil {
- panic(err)
- }
- store.KeyPrefix(constant.UserSessionPrefix)
- store.Options(sessions.Options{
- Path: "/",
- MaxAge: 86400 * 7,
- HttpOnly: true,
- Secure: true,
- SameSite: http.SameSiteLaxMode,
- })
- return store
-}
diff --git a/go.mod b/go.mod
index fc07d18..51a082c 100644
--- a/go.mod
+++ b/go.mod
@@ -4,7 +4,7 @@ go 1.23.4
require (
github.com/ArtisanCloud/PowerLibs/v3 v3.2.6
- github.com/ArtisanCloud/PowerWeChat/v3 v3.2.57
+ github.com/ArtisanCloud/PowerWeChat/v3 v3.2.58
github.com/asjdf/gorm-cache v1.2.3
github.com/casbin/casbin/v2 v2.102.0
github.com/casbin/gorm-adapter/v3 v3.32.0
@@ -12,7 +12,6 @@ require (
github.com/chenmingyong0423/go-mongox/v2 v2.0.0
github.com/golang-jwt/jwt/v5 v5.2.1
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
- github.com/gorilla/sessions v1.4.0
github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20240510055607-89e20ab7b6c6
github.com/lxzan/gws v1.8.8
github.com/microcosm-cc/bluemonday v1.0.27
@@ -20,7 +19,6 @@ require (
github.com/nicksnyder/go-i18n/v2 v2.4.1
github.com/pelletier/go-toml/v2 v2.2.3
github.com/pkg6/go-sms v0.1.2
- github.com/rbcervilla/redisstore/v9 v9.0.0
github.com/redis/go-redis/v9 v9.7.0
github.com/wenlng/go-captcha-assets v1.0.1
github.com/wenlng/go-captcha/v2 v2.0.2
@@ -30,7 +28,7 @@ require (
go.mongodb.org/mongo-driver/v2 v2.0.0
golang.org/x/crypto v0.31.0
golang.org/x/text v0.21.0
- google.golang.org/grpc v1.69.0
+ google.golang.org/grpc v1.69.2
gorm.io/driver/mysql v1.5.7
gorm.io/gen v0.3.26
gorm.io/gorm v1.25.12
@@ -72,8 +70,7 @@ require (
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/css v1.0.1 // indirect
- github.com/gorilla/securecookie v1.1.2 // indirect
- github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 // indirect
+ github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/imroc/req/v3 v3.49.0 // indirect
@@ -95,7 +92,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
- github.com/onsi/ginkgo/v2 v2.22.0 // indirect
+ github.com/onsi/ginkgo/v2 v2.22.1 // indirect
github.com/openzipkin/zipkin-go v0.4.3 // indirect
github.com/orcaman/concurrent-map/v2 v2.0.1 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
@@ -130,15 +127,15 @@ require (
go.uber.org/mock v0.5.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
- golang.org/x/exp v0.0.0-20241215155358-4a5509556b9e // indirect
+ golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 // indirect
golang.org/x/image v0.23.0 // indirect
golang.org/x/mod v0.22.0 // indirect
- golang.org/x/net v0.32.0 // indirect
+ golang.org/x/net v0.33.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.28.0 // indirect
golang.org/x/tools v0.28.0 // indirect
- google.golang.org/genproto/googleapis/api v0.0.0-20241216192217-9240e9c98484 // indirect
- google.golang.org/genproto/googleapis/rpc v0.0.0-20241216192217-9240e9c98484 // indirect
+ google.golang.org/genproto/googleapis/api v0.0.0-20241219192143-6b3ec007d9bb // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20241219192143-6b3ec007d9bb // indirect
google.golang.org/protobuf v1.36.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
@@ -149,5 +146,5 @@ require (
modernc.org/libc v1.61.4 // indirect
modernc.org/mathutil v1.6.0 // indirect
modernc.org/memory v1.8.0 // indirect
- modernc.org/sqlite v1.34.2 // indirect
+ modernc.org/sqlite v1.34.3 // indirect
)
diff --git a/go.sum b/go.sum
index 5116881..e404152 100644
--- a/go.sum
+++ b/go.sum
@@ -6,6 +6,8 @@ github.com/ArtisanCloud/PowerSocialite/v3 v3.0.7 h1:P+erNlErr+X2v7Et+yTWaTfIRhw+
github.com/ArtisanCloud/PowerSocialite/v3 v3.0.7/go.mod h1:VZQNCvcK/rldF3QaExiSl1gJEAkyc5/I8RLOd3WFZq4=
github.com/ArtisanCloud/PowerWeChat/v3 v3.2.57 h1:6IEFuaPJdB2HVGePyInVN9KuSiXk83Kfls4rYZd0mXQ=
github.com/ArtisanCloud/PowerWeChat/v3 v3.2.57/go.mod h1:D2cB1wtwC1YgzYT1Ni8NWS5wJCm5n1T18TybXkFlwvo=
+github.com/ArtisanCloud/PowerWeChat/v3 v3.2.58 h1:EkU5bWuy4irw23EooJliTjA/ucSnLaZIB9Ab3DyVweo=
+github.com/ArtisanCloud/PowerWeChat/v3 v3.2.58/go.mod h1:D2cB1wtwC1YgzYT1Ni8NWS5wJCm5n1T18TybXkFlwvo=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0/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/azcore v1.9.1/go.mod h1:RKUqNu35KJYcVG/fqTRqmuXJZYNhYkBrnC/hX7yGbTA=
@@ -100,6 +102,7 @@ github.com/go-playground/validator/v10 v10.23.0/go.mod h1:dbuPbCMFw/DrkbEynArYaC
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
+github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo=
@@ -124,8 +127,6 @@ github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
-github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
-github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -135,13 +136,11 @@ github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
-github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
-github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
-github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ=
-github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 h1:TmHmbvxPmaegwhDubVz0lICL0J5Ka2vwTzhoePEXsGE=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0/go.mod h1:qztMSjm835F2bXf+5HKAPIS5qsmQDqZna/PgVt4rWtI=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ=
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@@ -221,8 +220,11 @@ github.com/nicksnyder/go-i18n/v2 v2.4.1 h1:zwzjtX4uYyiaU02K5Ia3zSkpJZrByARkRB4V3
github.com/nicksnyder/go-i18n/v2 v2.4.1/go.mod h1:++Pl70FR6Cki7hdzZRnEEqdc2dJt+SAGotyFg/SvZMk=
github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg=
github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
+github.com/onsi/ginkgo/v2 v2.22.1 h1:QW7tbJAUDyVDVOM5dFa7qaybo+CRfR7bemlQUN6Z8aM=
+github.com/onsi/ginkgo/v2 v2.22.1/go.mod h1:S6aTpoRsSq2cZOd+pssHAlKW/Q/jZt6cPrPlnj4a1xM=
github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8=
github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc=
+github.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw=
github.com/openzipkin/zipkin-go v0.4.3 h1:9EGwpqkgnwdEIJ+Od7QVSEIH+ocmm5nPat0G7sjsSdg=
github.com/openzipkin/zipkin-go v0.4.3/go.mod h1:M9wCJZFWCo2RiY+o1eBCEMe0Dp2S5LDHcMZmk3RmK7c=
github.com/orcaman/concurrent-map/v2 v2.0.1 h1:jOJ5Pg2w1oeB6PeDurIYf6k9PQ+aTITr/6lP/L/zp6c=
@@ -256,8 +258,6 @@ github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
github.com/quic-go/quic-go v0.48.2 h1:wsKXZPeGWpMpCGSWqOcqpW2wZYic/8T3aqiOID0/KWE=
github.com/quic-go/quic-go v0.48.2/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs=
-github.com/rbcervilla/redisstore/v9 v9.0.0 h1:wOPbBaydbdxzi1gTafDftCI/Z7vnsXw0QDPCuhiMG0g=
-github.com/rbcervilla/redisstore/v9 v9.0.0/go.mod h1:q/acLpoKkTZzIsBYt0R4THDnf8W/BH6GjQYvxDSSfdI=
github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E=
github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw=
github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM=
@@ -303,6 +303,7 @@ github.com/zeromicro/go-zero v1.7.4 h1:lyIUsqbpVRzM4NmXu5pRM3XrdRdUuWOkQmHiNmJF0
github.com/zeromicro/go-zero v1.7.4/go.mod h1:jmv4hTdUBkDn6kxgI+WrKQw0q6LKxDElGPMfCLOeeEY=
github.com/zmexing/go-sensitive-word v1.3.0 h1:dB9S9kNklksOODGLLAov0RaVCwC2w9Kwxz6NZMdM6rk=
github.com/zmexing/go-sensitive-word v1.3.0/go.mod h1:wkNIpkq1iPOe3l7l83zvnnV5mm20jfj2x8V8kjOTsUM=
+go.mongodb.org/mongo-driver v1.17.1 h1:Wic5cJIwJgSpBhe3lx3+/RybR5PiYRMpVFgO7cOHyIM=
go.mongodb.org/mongo-driver/v2 v2.0.0 h1:Jfd7XpdZa9yk3eY774bO7SWVb30noLSirL9nKTpavhI=
go.mongodb.org/mongo-driver/v2 v2.0.0/go.mod h1:nSjmNq4JUstE8IRZKTktLgMHM4F1fccL6HGX1yh+8RA=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
@@ -354,6 +355,8 @@ golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/exp v0.0.0-20241215155358-4a5509556b9e h1:4qufH0hlUYs6AO6XmZC3GqfDPGSXHVXUFR6OND+iJX4=
golang.org/x/exp v0.0.0-20241215155358-4a5509556b9e/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
+golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 h1:1UoZQm6f0P/ZO0w1Ri+f+ifG/gXhegadRdwBIXEFWDo=
+golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
golang.org/x/image v0.16.0/go.mod h1:ugSZItdV4nOxyqp56HmXwH0Ry0nBCpjnZdpDaIHdoPs=
golang.org/x/image v0.23.0 h1:HseQ7c2OpPKTPVzNjG5fwJsOTCiiwS4QdsYi5XU6H68=
golang.org/x/image v0.23.0/go.mod h1:wJJBTdLfCCf3tiHa1fNxpZmUI4mmoZvwMCPP0ddoNKY=
@@ -377,6 +380,8 @@ golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
+golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
+golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -436,10 +441,16 @@ golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto/googleapis/api v0.0.0-20241216192217-9240e9c98484 h1:ChAdCYNQFDk5fYvFZMywKLIijG7TC2m1C2CMEu11G3o=
google.golang.org/genproto/googleapis/api v0.0.0-20241216192217-9240e9c98484/go.mod h1:KRUmxRI4JmbpAm8gcZM4Jsffi859fo5LQjILwuqj9z8=
+google.golang.org/genproto/googleapis/api v0.0.0-20241219192143-6b3ec007d9bb h1:B7GIB7sr443wZ/EAEl7VZjmh1V6qzkt5V+RYcUYtS1U=
+google.golang.org/genproto/googleapis/api v0.0.0-20241219192143-6b3ec007d9bb/go.mod h1:E5//3O5ZIG2l71Xnt+P/CYUY8Bxs8E7WMoZ9tlcMbAY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241216192217-9240e9c98484 h1:Z7FRVJPSMaHQxD0uXU8WdgFh8PseLM8Q8NzhnpMrBhQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241216192217-9240e9c98484/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20241219192143-6b3ec007d9bb h1:3oy2tynMOP1QbTC0MsNNAV+Se8M2Bd0A5+x1QHyw+pI=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20241219192143-6b3ec007d9bb/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA=
google.golang.org/grpc v1.69.0 h1:quSiOM1GJPmPH5XtU+BCoVXcDVJJAzNcoyfC2cCjGkI=
google.golang.org/grpc v1.69.0/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4=
+google.golang.org/grpc v1.69.2 h1:U3S9QEtbXC0bYNvRtcoklF3xGtLViumSYxWykJS+7AU=
+google.golang.org/grpc v1.69.2/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4=
google.golang.org/protobuf v1.36.0 h1:mjIs9gYtt56AzC4ZaffQuh88TZurBGhIJMBZGSxNerQ=
google.golang.org/protobuf v1.36.0/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -501,6 +512,8 @@ modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss=
modernc.org/sqlite v1.34.2 h1:J9n76TPsfYYkFkZ9Uy1QphILYifiVEwwOT7yP5b++2Y=
modernc.org/sqlite v1.34.2/go.mod h1:dnR723UrTtjKpoHCAMN0Q/gZ9MT4r+iRvIBb9umWFkU=
+modernc.org/sqlite v1.34.3 h1:494MIwJKBLd0tErBYkRar2HvEpy04Bl0ykPEm4XLhbo=
+modernc.org/sqlite v1.34.3/go.mod h1:dnR723UrTtjKpoHCAMN0Q/gZ9MT4r+iRvIBb9umWFkU=
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=