♻️ refactored login-related code

This commit is contained in:
2024-12-21 00:51:59 +08:00
parent 40d073db0f
commit f213644aa9
33 changed files with 802 additions and 535 deletions

276
.idea/GOHCache.xml generated
View File

@@ -38,6 +38,13 @@
</set> </set>
</value> </value>
</entry> </entry>
<entry key="AuthorizationMiddleware">
<value>
<set>
<option value="file://$PROJECT_DIR$/app/core/api/internal/middleware/authorization_middleware.go" />
</set>
</value>
</entry>
<entry key="BaseResponse"> <entry key="BaseResponse">
<value> <value>
<set> <set>
@@ -213,6 +220,14 @@
</set> </set>
</value> </value>
</entry> </entry>
<entry key="GetWechatOffiaccountQrcodeLogic">
<value>
<set>
<option value="file://$PROJECT_DIR$/app/core/api/internal/logic/oauth/get_wechat_offiaccount_qrcode_logic.go" />
<option value="file://$PROJECT_DIR$/app/core/api/internal/logic/user/get_wechat_offiaccount_qrcode_logic.go" />
</set>
</value>
</entry>
<entry key="GetWechatQrcodeLogic"> <entry key="GetWechatQrcodeLogic">
<value> <value>
<set> <set>
@@ -276,6 +291,14 @@
</set> </set>
</value> </value>
</entry> </entry>
<entry key="MessageData">
<value>
<set>
<option value="file://$PROJECT_DIR$/app/core/api/internal/logic/oauth/wechat_callback_logic.go" />
<option value="file://$PROJECT_DIR$/app/core/api/internal/logic/oauth/wechat_offiaccount_callback_logic.go" />
</set>
</value>
</entry>
<entry key="MessageWebSocket"> <entry key="MessageWebSocket">
<value> <value>
<set> <set>
@@ -577,6 +600,13 @@
</set> </set>
</value> </value>
</entry> </entry>
<entry key="SendMessage">
<value>
<set>
<option value="file://$PROJECT_DIR$/app/core/api/internal/logic/oauth/wechat_callback_logic.go" />
</set>
</value>
</entry>
<entry key="SendSmsByAliyunLogic"> <entry key="SendSmsByAliyunLogic">
<value> <value>
<set> <set>
@@ -661,6 +691,20 @@
</set> </set>
</value> </value>
</entry> </entry>
<entry key="WebsocketJWTClaims">
<value>
<set>
<option value="file://$PROJECT_DIR$/app/core/api/common/jwt/websocket_token.go" />
</set>
</value>
</entry>
<entry key="WebsocketJWTPayload">
<value>
<set>
<option value="file://$PROJECT_DIR$/app/core/api/common/jwt/websocket_token.go" />
</set>
</value>
</entry>
<entry key="WechatCallbackLogic"> <entry key="WechatCallbackLogic">
<value> <value>
<set> <set>
@@ -668,6 +712,34 @@
</set> </set>
</value> </value>
</entry> </entry>
<entry key="WechatCallbackVerifyLogic">
<value>
<set>
<option value="file://$PROJECT_DIR$/app/core/api/internal/logic/oauth/wechat_callback_verify_logic.go" />
</set>
</value>
</entry>
<entry key="WechatOffiaccountCallbackLogic">
<value>
<set>
<option value="file://$PROJECT_DIR$/app/core/api/internal/logic/oauth/wechat_offiaccount_callback_logic.go" />
</set>
</value>
</entry>
<entry key="WechatOffiaccountCallbackVerifyLogic">
<value>
<set>
<option value="file://$PROJECT_DIR$/app/core/api/internal/logic/oauth/wechat_offiaccount_callback_verify_logic.go" />
</set>
</value>
</entry>
<entry key="WechatOffiaccountLoginLogic">
<value>
<set>
<option value="file://$PROJECT_DIR$/app/core/api/internal/logic/user/wechat_offiaccount_login_logic.go" />
</set>
</value>
</entry>
<entry key="baseXmlResponse"> <entry key="baseXmlResponse">
<value> <value>
<set> <set>
@@ -983,7 +1055,7 @@
<entry key="file://$PROJECT_DIR$/app/core/api/common/constant/jwt_type.go"> <entry key="file://$PROJECT_DIR$/app/core/api/common/constant/jwt_type.go">
<value> <value>
<ScannedPath> <ScannedPath>
<option name="lastModified" value="1734585304638" /> <option name="lastModified" value="1734692829250" />
</ScannedPath> </ScannedPath>
</value> </value>
</entry> </entry>
@@ -1008,10 +1080,10 @@
</ScannedPath> </ScannedPath>
</value> </value>
</entry> </entry>
<entry key="file://$PROJECT_DIR$/app/core/api/common/constant/session_key.go"> <entry key="file://$PROJECT_DIR$/app/core/api/common/constant/uid_key.go">
<value> <value>
<ScannedPath> <ScannedPath>
<option name="lastModified" value="1731503839158" /> <option name="lastModified" value="1734682023828" />
</ScannedPath> </ScannedPath>
</value> </value>
</entry> </entry>
@@ -1123,7 +1195,7 @@
<entry key="file://$PROJECT_DIR$/app/core/api/common/jwt/access_token.go"> <entry key="file://$PROJECT_DIR$/app/core/api/common/jwt/access_token.go">
<value> <value>
<ScannedPath> <ScannedPath>
<option name="lastModified" value="1734627130905" /> <option name="lastModified" value="1734682778489" />
<option name="schema"> <option name="schema">
<list> <list>
<option value="AccessJWTPayload" /> <option value="AccessJWTPayload" />
@@ -1146,10 +1218,23 @@
</ScannedPath> </ScannedPath>
</value> </value>
</entry> </entry>
<entry key="file://$PROJECT_DIR$/app/core/api/common/jwt/websocket_token.go">
<value>
<ScannedPath>
<option name="lastModified" value="1734685303630" />
<option name="schema">
<list>
<option value="WebsocketJWTPayload" />
<option value="WebsocketJWTClaims" />
</list>
</option>
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/app/core/api/common/middleware/cors_middleware.go"> <entry key="file://$PROJECT_DIR$/app/core/api/common/middleware/cors_middleware.go">
<value> <value>
<ScannedPath> <ScannedPath>
<option name="lastModified" value="1731945430237" /> <option name="lastModified" value="1734682151710" />
</ScannedPath> </ScannedPath>
</value> </value>
</entry> </entry>
@@ -1170,7 +1255,7 @@
<entry key="file://$PROJECT_DIR$/app/core/api/common/middleware/unauthorized_callback_middleware.go"> <entry key="file://$PROJECT_DIR$/app/core/api/common/middleware/unauthorized_callback_middleware.go">
<value> <value>
<ScannedPath> <ScannedPath>
<option name="lastModified" value="1731723288201" /> <option name="lastModified" value="1734672079755" />
</ScannedPath> </ScannedPath>
</value> </value>
</entry> </entry>
@@ -1280,7 +1365,7 @@
<entry key="file://$PROJECT_DIR$/app/core/api/core.go"> <entry key="file://$PROJECT_DIR$/app/core/api/core.go">
<value> <value>
<ScannedPath> <ScannedPath>
<option name="lastModified" value="1734422263961" /> <option name="lastModified" value="1734693433014" />
</ScannedPath> </ScannedPath>
</value> </value>
</entry> </entry>
@@ -1394,6 +1479,13 @@
</ScannedPath> </ScannedPath>
</value> </value>
</entry> </entry>
<entry key="file://$PROJECT_DIR$/app/core/api/internal/handler/oauth/get_wechat_offiaccount_qrcode_handler.go">
<value>
<ScannedPath>
<option name="lastModified" value="1734712613824" />
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/app/core/api/internal/handler/oauth/get_wechat_qrcode_handler.go"> <entry key="file://$PROJECT_DIR$/app/core/api/internal/handler/oauth/get_wechat_qrcode_handler.go">
<value> <value>
<ScannedPath> <ScannedPath>
@@ -1425,14 +1517,35 @@
<entry key="file://$PROJECT_DIR$/app/core/api/internal/handler/oauth/wechat_callback_handler.go"> <entry key="file://$PROJECT_DIR$/app/core/api/internal/handler/oauth/wechat_callback_handler.go">
<value> <value>
<ScannedPath> <ScannedPath>
<option name="lastModified" value="1731862717048" /> <option name="lastModified" value="1734710082690" />
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/app/core/api/internal/handler/oauth/wechat_callback_verify_handler.go">
<value>
<ScannedPath>
<option name="lastModified" value="1734706549624" />
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/app/core/api/internal/handler/oauth/wechat_offiaccount_callback_handler.go">
<value>
<ScannedPath>
<option name="lastModified" value="1734712724197" />
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/app/core/api/internal/handler/oauth/wechat_offiaccount_callback_verify_handler.go">
<value>
<ScannedPath>
<option name="lastModified" value="1734712613290" />
</ScannedPath> </ScannedPath>
</value> </value>
</entry> </entry>
<entry key="file://$PROJECT_DIR$/app/core/api/internal/handler/routes.go"> <entry key="file://$PROJECT_DIR$/app/core/api/internal/handler/routes.go">
<value> <value>
<ScannedPath> <ScannedPath>
<option name="lastModified" value="1734584742648" /> <option name="lastModified" value="1734712935626" />
</ScannedPath> </ScannedPath>
</value> </value>
</entry> </entry>
@@ -1485,6 +1598,13 @@
</ScannedPath> </ScannedPath>
</value> </value>
</entry> </entry>
<entry key="file://$PROJECT_DIR$/app/core/api/internal/handler/user/get_wechat_offiaccount_qrcode_handler.go">
<value>
<ScannedPath>
<option name="lastModified" value="1734712935631" />
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/app/core/api/internal/handler/user/phone_login_handler.go"> <entry key="file://$PROJECT_DIR$/app/core/api/internal/handler/user/phone_login_handler.go">
<value> <value>
<ScannedPath> <ScannedPath>
@@ -1499,6 +1619,13 @@
</ScannedPath> </ScannedPath>
</value> </value>
</entry> </entry>
<entry key="file://$PROJECT_DIR$/app/core/api/internal/handler/user/wechat_offiaccount_login_handler.go">
<value>
<ScannedPath>
<option name="lastModified" value="1734710236074" />
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/app/core/api/internal/handler/websocket/file_websocket_handler.go"> <entry key="file://$PROJECT_DIR$/app/core/api/internal/handler/websocket/file_websocket_handler.go">
<value> <value>
<ScannedPath> <ScannedPath>
@@ -1676,10 +1803,22 @@
</ScannedPath> </ScannedPath>
</value> </value>
</entry> </entry>
<entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/oauth/get_wechat_offiaccount_qrcode_logic.go">
<value>
<ScannedPath>
<option name="lastModified" value="1734712486975" />
<option name="schema">
<list>
<option value="GetWechatOffiaccountQrcodeLogic" />
</list>
</option>
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/oauth/get_wechat_qrcode_logic.go"> <entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/oauth/get_wechat_qrcode_logic.go">
<value> <value>
<ScannedPath> <ScannedPath>
<option name="lastModified" value="1731863022429" /> <option name="lastModified" value="1734702605921" />
<option name="schema"> <option name="schema">
<list> <list>
<option value="GetWechatQrcodeLogic" /> <option value="GetWechatQrcodeLogic" />
@@ -1691,7 +1830,7 @@
<entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/oauth/gitee_callback_logic.go"> <entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/oauth/gitee_callback_logic.go">
<value> <value>
<ScannedPath> <ScannedPath>
<option name="lastModified" value="1734537913336" /> <option name="lastModified" value="1734709587419" />
<option name="schema"> <option name="schema">
<list> <list>
<option value="GiteeCallbackLogic" /> <option value="GiteeCallbackLogic" />
@@ -1705,7 +1844,7 @@
<entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/oauth/github_callback_logic.go"> <entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/oauth/github_callback_logic.go">
<value> <value>
<ScannedPath> <ScannedPath>
<option name="lastModified" value="1734534251287" /> <option name="lastModified" value="1734709097463" />
<option name="schema"> <option name="schema">
<list> <list>
<option value="GithubCallbackLogic" /> <option value="GithubCallbackLogic" />
@@ -1718,7 +1857,7 @@
<entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/oauth/qq_callback_logic.go"> <entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/oauth/qq_callback_logic.go">
<value> <value>
<ScannedPath> <ScannedPath>
<option name="lastModified" value="1734628607288" /> <option name="lastModified" value="1734709097444" />
<option name="schema"> <option name="schema">
<list> <list>
<option value="QqCallbackLogic" /> <option value="QqCallbackLogic" />
@@ -1733,10 +1872,48 @@
<entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/oauth/wechat_callback_logic.go"> <entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/oauth/wechat_callback_logic.go">
<value> <value>
<ScannedPath> <ScannedPath>
<option name="lastModified" value="1734534398664" /> <option name="lastModified" value="1734710679760" />
<option name="schema"> <option name="schema">
<list> <list>
<option value="WechatCallbackLogic" /> <option value="WechatCallbackLogic" />
<option value="MessageData" />
</list>
</option>
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/oauth/wechat_callback_verify_logic.go">
<value>
<ScannedPath>
<option name="lastModified" value="1734706458837" />
<option name="schema">
<list>
<option value="WechatCallbackVerifyLogic" />
</list>
</option>
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/oauth/wechat_offiaccount_callback_logic.go">
<value>
<ScannedPath>
<option name="lastModified" value="1734712747630" />
<option name="schema">
<list>
<option value="WechatOffiaccountCallbackLogic" />
<option value="MessageData" />
</list>
</option>
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/oauth/wechat_offiaccount_callback_verify_logic.go">
<value>
<ScannedPath>
<option name="lastModified" value="1734712613711" />
<option name="schema">
<list>
<option value="WechatOffiaccountCallbackVerifyLogic" />
</list> </list>
</option> </option>
</ScannedPath> </ScannedPath>
@@ -1781,7 +1958,7 @@
<entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/token/refresh_token_logic.go"> <entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/token/refresh_token_logic.go">
<value> <value>
<ScannedPath> <ScannedPath>
<option name="lastModified" value="1734584546882" /> <option name="lastModified" value="1734692914876" />
<option name="schema"> <option name="schema">
<list> <list>
<option value="RefreshTokenLogic" /> <option value="RefreshTokenLogic" />
@@ -1805,7 +1982,7 @@
<entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/user/account_login_logic.go"> <entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/user/account_login_logic.go">
<value> <value>
<ScannedPath> <ScannedPath>
<option name="lastModified" value="1734584691324" /> <option name="lastModified" value="1734709587740" />
<option name="schema"> <option name="schema">
<list> <list>
<option value="AccountLoginLogic" /> <option value="AccountLoginLogic" />
@@ -1817,7 +1994,7 @@
<entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/user/get_user_device_logic.go"> <entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/user/get_user_device_logic.go">
<value> <value>
<ScannedPath> <ScannedPath>
<option name="lastModified" value="1734584662756" /> <option name="lastModified" value="1734709292150" />
<option name="schema"> <option name="schema">
<list> <list>
<option value="GetUserDeviceLogic" /> <option value="GetUserDeviceLogic" />
@@ -1826,10 +2003,22 @@
</ScannedPath> </ScannedPath>
</value> </value>
</entry> </entry>
<entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/user/get_wechat_offiaccount_qrcode_logic.go">
<value>
<ScannedPath>
<option name="lastModified" value="1734712935637" />
<option name="schema">
<list>
<option value="GetWechatOffiaccountQrcodeLogic" />
</list>
</option>
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/user/phone_login_logic.go"> <entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/user/phone_login_logic.go">
<value> <value>
<ScannedPath> <ScannedPath>
<option name="lastModified" value="1732207481081" /> <option name="lastModified" value="1734709292172" />
<option name="schema"> <option name="schema">
<list> <list>
<option value="PhoneLoginLogic" /> <option value="PhoneLoginLogic" />
@@ -1850,6 +2039,18 @@
</ScannedPath> </ScannedPath>
</value> </value>
</entry> </entry>
<entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/user/wechat_offiaccount_login_logic.go">
<value>
<ScannedPath>
<option name="lastModified" value="1734711022532" />
<option name="schema">
<list>
<option value="WechatOffiaccountLoginLogic" />
</list>
</option>
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/websocket/file_websocket_logic.go"> <entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/websocket/file_websocket_logic.go">
<value> <value>
<ScannedPath> <ScannedPath>
@@ -1889,10 +2090,22 @@
</ScannedPath> </ScannedPath>
</value> </value>
</entry> </entry>
<entry key="file://$PROJECT_DIR$/app/core/api/internal/middleware/authorization_middleware.go">
<value>
<ScannedPath>
<option name="lastModified" value="1734692269196" />
<option name="schema">
<list>
<option value="AuthorizationMiddleware" />
</list>
</option>
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/app/core/api/internal/middleware/casbinverify_middleware.go"> <entry key="file://$PROJECT_DIR$/app/core/api/internal/middleware/casbinverify_middleware.go">
<value> <value>
<ScannedPath> <ScannedPath>
<option name="lastModified" value="1734583810496" /> <option name="lastModified" value="1734682271288" />
<option name="schema"> <option name="schema">
<list> <list>
<option value="CasbinVerifyMiddleware" /> <option value="CasbinVerifyMiddleware" />
@@ -1916,7 +2129,7 @@
<entry key="file://$PROJECT_DIR$/app/core/api/internal/svc/service_context.go"> <entry key="file://$PROJECT_DIR$/app/core/api/internal/svc/service_context.go">
<value> <value>
<ScannedPath> <ScannedPath>
<option name="lastModified" value="1734586605604" /> <option name="lastModified" value="1734702591918" />
<option name="schema"> <option name="schema">
<list> <list>
<option value="ServiceContext" /> <option value="ServiceContext" />
@@ -1945,7 +2158,7 @@
<entry key="file://$PROJECT_DIR$/app/core/api/internal/types/token.go"> <entry key="file://$PROJECT_DIR$/app/core/api/internal/types/token.go">
<value> <value>
<ScannedPath> <ScannedPath>
<option name="lastModified" value="1731722350830" /> <option name="lastModified" value="1734692829235" />
<option name="schema"> <option name="schema">
<list> <list>
<option value="RedisToken" /> <option value="RedisToken" />
@@ -1957,7 +2170,7 @@
<entry key="file://$PROJECT_DIR$/app/core/api/internal/types/types.go"> <entry key="file://$PROJECT_DIR$/app/core/api/internal/types/types.go">
<value> <value>
<ScannedPath> <ScannedPath>
<option name="lastModified" value="1734584742644" /> <option name="lastModified" value="1734692204790" />
<option name="schema"> <option name="schema">
<list> <list>
<option value="AccountLoginRequest" /> <option value="AccountLoginRequest" />
@@ -2481,13 +2694,6 @@
</ScannedPath> </ScannedPath>
</value> </value>
</entry> </entry>
<entry key="file://$PROJECT_DIR$/app/core/api/repository/redis_session/redis_session.go">
<value>
<ScannedPath>
<option name="lastModified" value="1734586600191" />
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/app/core/api/repository/redisx/redis.go"> <entry key="file://$PROJECT_DIR$/app/core/api/repository/redisx/redis.go">
<value> <value>
<ScannedPath> <ScannedPath>
@@ -2518,6 +2724,7 @@
<entry key="account_login_logic" value="AccountLoginLogic" /> <entry key="account_login_logic" value="AccountLoginLogic" />
<entry key="account_login_request" value="AccountLoginRequest" /> <entry key="account_login_request" value="AccountLoginRequest" />
<entry key="auth_q_qme" value="AuthQQme" /> <entry key="auth_q_qme" value="AuthQQme" />
<entry key="authorization_middleware" value="AuthorizationMiddleware" />
<entry key="base_response" value="BaseResponse" /> <entry key="base_response" value="BaseResponse" />
<entry key="base_xml_response" value="baseXmlResponse" /> <entry key="base_xml_response" value="baseXmlResponse" />
<entry key="casbin_verify_middleware" value="CasbinVerifyMiddleware" /> <entry key="casbin_verify_middleware" value="CasbinVerifyMiddleware" />
@@ -2544,6 +2751,7 @@
<entry key="get_qq_oauth_url_logic" value="GetQqOauthUrlLogic" /> <entry key="get_qq_oauth_url_logic" value="GetQqOauthUrlLogic" />
<entry key="get_reply_list_logic" value="GetReplyListLogic" /> <entry key="get_reply_list_logic" value="GetReplyListLogic" />
<entry key="get_user_device_logic" value="GetUserDeviceLogic" /> <entry key="get_user_device_logic" value="GetUserDeviceLogic" />
<entry key="get_wechat_offiaccount_qrcode_logic" value="GetWechatOffiaccountQrcodeLogic" />
<entry key="get_wechat_qrcode_logic" value="GetWechatQrcodeLogic" /> <entry key="get_wechat_qrcode_logic" value="GetWechatQrcodeLogic" />
<entry key="git_hub_user" value="GitHubUser" /> <entry key="git_hub_user" value="GitHubUser" />
<entry key="gitee_callback_logic" value="GiteeCallbackLogic" /> <entry key="gitee_callback_logic" value="GiteeCallbackLogic" />
@@ -2553,6 +2761,7 @@
<entry key="i18n_middleware" value="I18nMiddleware" /> <entry key="i18n_middleware" value="I18nMiddleware" />
<entry key="like_comment_logic" value="LikeCommentLogic" /> <entry key="like_comment_logic" value="LikeCommentLogic" />
<entry key="login_response" value="LoginResponse" /> <entry key="login_response" value="LoginResponse" />
<entry key="message_data" value="MessageData" />
<entry key="message_web_socket" value="MessageWebSocket" /> <entry key="message_web_socket" value="MessageWebSocket" />
<entry key="message_websocket_logic" value="MessageWebsocketLogic" /> <entry key="message_websocket_logic" value="MessageWebsocketLogic" />
<entry key="o_auth_callback_request" value="OAuthCallbackRequest" /> <entry key="o_auth_callback_request" value="OAuthCallbackRequest" />
@@ -2613,6 +2822,7 @@
<entry key="sca_user_message" value="scaUserMessage" /> <entry key="sca_user_message" value="scaUserMessage" />
<entry key="sca_user_message_do" value="scaUserMessageDo" /> <entry key="sca_user_message_do" value="scaUserMessageDo" />
<entry key="security_headers_middleware" value="SecurityHeadersMiddleware" /> <entry key="security_headers_middleware" value="SecurityHeadersMiddleware" />
<entry key="send_message" value="SendMessage" />
<entry key="send_sms_by_aliyun_logic" value="SendSmsByAliyunLogic" /> <entry key="send_sms_by_aliyun_logic" value="SendSmsByAliyunLogic" />
<entry key="send_sms_by_smsbao_logic" value="SendSmsBySmsbaoLogic" /> <entry key="send_sms_by_smsbao_logic" value="SendSmsBySmsbaoLogic" />
<entry key="send_sms_by_test_logic" value="SendSmsByTestLogic" /> <entry key="send_sms_by_test_logic" value="SendSmsByTestLogic" />
@@ -2625,9 +2835,15 @@
<entry key="upload_image_logic" value="UploadImageLogic" /> <entry key="upload_image_logic" value="UploadImageLogic" />
<entry key="upload_request" value="UploadRequest" /> <entry key="upload_request" value="UploadRequest" />
<entry key="user_device_request" value="UserDeviceRequest" /> <entry key="user_device_request" value="UserDeviceRequest" />
<entry key="websocket_jwt_claims" value="WebsocketJWTClaims" />
<entry key="websocket_jwt_payload" value="WebsocketJWTPayload" />
<entry key="wechat_callback_logic" value="WechatCallbackLogic" /> <entry key="wechat_callback_logic" value="WechatCallbackLogic" />
<entry key="wechat_callback_verify_logic" value="WechatCallbackVerifyLogic" />
<entry key="wechat_offiaccount_callback_logic" value="WechatOffiaccountCallbackLogic" />
<entry key="wechat_offiaccount_callback_verify_logic" value="WechatOffiaccountCallbackVerifyLogic" />
<entry key="wechat_offiaccount_login_logic" value="WechatOffiaccountLoginLogic" />
</map> </map>
</option> </option>
<option name="lastTimeChecked" value="1734592292465" /> <option name="lastTimeChecked" value="1734699497598" />
</component> </component>
</project> </project>

View File

@@ -1,3 +0,0 @@
package constant
const SESSION_KEY = "SESSION"

View File

@@ -0,0 +1,3 @@
package constant
const UID_HEADER_KEY = "X-UID"

View File

@@ -19,7 +19,7 @@ func GenerateAccessToken(secret string, payload AccessJWTPayload) string {
claims := AccessJWTClaims{ claims := AccessJWTClaims{
AccessJWTPayload: payload, AccessJWTPayload: payload,
RegisteredClaims: jwt.RegisteredClaims{ 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()), IssuedAt: jwt.NewNumericDate(time.Now()),
NotBefore: jwt.NewNumericDate(time.Now()), NotBefore: jwt.NewNumericDate(time.Now()),
}, },

View File

@@ -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
}

View File

@@ -7,7 +7,7 @@ func CORSMiddleware() func(http.Header) {
header.Set("Access-Control-Allow-Origin", "*") header.Set("Access-Control-Allow-Origin", "*")
header.Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, PATCH") 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-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") header.Set("Access-Control-Allow-Credentials", "true")
} }
} }

View File

@@ -10,7 +10,7 @@ import (
func UnauthorizedCallbackMiddleware() func(w http.ResponseWriter, r *http.Request, err error) { func UnauthorizedCallbackMiddleware() func(w http.ResponseWriter, r *http.Request, err error) {
return 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, err.Error()))
httpx.OkJsonCtx(r.Context(), w, response.ErrorWithCodeMessage(http.StatusUnauthorized, "Unauthorized")) return
} }
} }

View File

@@ -31,8 +31,9 @@ type (
Password string `json:"password"` Password string `json:"password"`
Repassword string `json:"repassword"` Repassword string `json:"repassword"`
} }
UserDeviceRequest { WechatOffiaccountLoginRequest {
AccessToken string `json:"access_token"` Openid string `json:"openid"`
ClientId string `json:"client_id"`
} }
// 登录响应参数 // 登录响应参数
LoginResponse { LoginResponse {
@@ -170,8 +171,13 @@ service core {
@handler resetPassword @handler resetPassword
post /reset/password (ResetPasswordRequest) returns (Response) 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 ( @server (
@@ -249,11 +255,12 @@ service core {
@handler qqCallback @handler qqCallback
get /qq/callback (OAuthCallbackRequest) returns (string) get /qq/callback (OAuthCallbackRequest) returns (string)
@handler wechatCallback @handler wechatOffiaccountCallback
get /wechat/callback post /wechat/offiaccount/callback
@handler getWechatQrcode // important!
get /wechat/qrcode (OAuthWechatRequest) returns (Response) @handler wechatOffiaccountCallbackVerify
get /wechat/offiaccount/callback
} }
@server ( @server (
@@ -301,7 +308,7 @@ service core {
timeout: 10s // 超时时间 timeout: 10s // 超时时间
maxBytes: 1048576 // 最大请求大小 maxBytes: 1048576 // 最大请求大小
signature: false // 是否开启签名验证 signature: false // 是否开启签名验证
middleware: SecurityHeadersMiddleware,CasbinVerifyMiddleware // 注册中间件 middleware: SecurityHeadersMiddleware,CasbinVerifyMiddleware,AuthorizationMiddleware // 注册中间件
MaxConns: true // 是否开启最大连接数限制 MaxConns: true // 是否开启最大连接数限制
Recover: true // 是否开启自动恢复 Recover: true // 是否开启自动恢复
jwt: Auth // 是否开启jwt验证 jwt: Auth // 是否开启jwt验证

View File

@@ -1,20 +1,20 @@
package oauth package oauth
import ( import (
"github.com/ArtisanCloud/PowerLibs/v3/http/helper"
"github.com/zeromicro/go-zero/core/logx"
"net/http" "net/http"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/rest/httpx" "github.com/zeromicro/go-zero/rest/httpx"
"schisandra-album-cloud-microservices/app/core/api/common/response" "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/logic/oauth"
"schisandra-album-cloud-microservices/app/core/api/internal/svc" "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) { return func(w http.ResponseWriter, r *http.Request) {
l := oauth.NewWechatCallbackLogic(r.Context(), svcCtx) l := oauth.NewWechatOffiaccountCallbackLogic(r.Context(), svcCtx)
err := l.WechatCallback(w, r) res, err := l.WechatOffiaccountCallback(r)
if err != nil { if err != nil {
logx.Error(err) logx.Error(err)
httpx.WriteJsonCtx( httpx.WriteJsonCtx(
@@ -23,7 +23,7 @@ func WechatCallbackHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
http.StatusInternalServerError, http.StatusInternalServerError,
response.ErrorWithI18n(r.Context(), "system.error")) response.ErrorWithI18n(r.Context(), "system.error"))
} else { } else {
httpx.Ok(w) _ = helper.HttpResponseSend(res, w)
} }
} }
} }

View File

@@ -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)
}
}
}

View File

@@ -61,7 +61,7 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
server.AddRoutes( server.AddRoutes(
rest.WithMiddlewares( rest.WithMiddlewares(
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware, serverCtx.CasbinVerifyMiddleware}, []rest.Middleware{serverCtx.SecurityHeadersMiddleware, serverCtx.CasbinVerifyMiddleware, serverCtx.AuthorizationMiddleware},
[]rest.Route{ []rest.Route{
{ {
Method: http.MethodPost, Method: http.MethodPost,
@@ -141,14 +141,14 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Handler: oauth.GetQqOauthUrlHandler(serverCtx), Handler: oauth.GetQqOauthUrlHandler(serverCtx),
}, },
{ {
Method: http.MethodGet, Method: http.MethodPost,
Path: "/wechat/callback", Path: "/wechat/offiaccount/callback",
Handler: oauth.WechatCallbackHandler(serverCtx), Handler: oauth.WechatOffiaccountCallbackHandler(serverCtx),
}, },
{ {
Method: http.MethodGet, Method: http.MethodGet,
Path: "/wechat/qrcode", Path: "/wechat/offiaccount/callback",
Handler: oauth.GetWechatQrcodeHandler(serverCtx), Handler: oauth.WechatOffiaccountCallbackVerifyHandler(serverCtx),
}, },
}..., }...,
), ),
@@ -220,11 +220,6 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
rest.WithMiddlewares( rest.WithMiddlewares(
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware}, []rest.Middleware{serverCtx.SecurityHeadersMiddleware},
[]rest.Route{ []rest.Route{
{
Method: http.MethodPost,
Path: "/device",
Handler: user.GetUserDeviceHandler(serverCtx),
},
{ {
Method: http.MethodPost, Method: http.MethodPost,
Path: "/login", Path: "/login",
@@ -240,6 +235,16 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/reset/password", Path: "/reset/password",
Handler: user.ResetPasswordHandler(serverCtx), 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), rest.WithSignature(serverCtx.Config.Signature),

View File

@@ -1,18 +1,17 @@
package oauth package user
import ( import (
"net/http"
"github.com/zeromicro/go-zero/core/logx" "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/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/svc"
"schisandra-album-cloud-microservices/app/core/api/internal/types" "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) { return func(w http.ResponseWriter, r *http.Request) {
var req types.OAuthWechatRequest var req types.OAuthWechatRequest
if err := httpx.Parse(r, &req); err != nil { if err := httpx.Parse(r, &req); err != nil {
@@ -20,8 +19,8 @@ func GetWechatQrcodeHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return return
} }
l := oauth.NewGetWechatQrcodeLogic(r.Context(), svcCtx) l := user.NewGetWechatOffiaccountQrcodeLogic(r.Context(), svcCtx)
resp, err := l.GetWechatQrcode(r, &req) resp, err := l.GetWechatOffiaccountQrcode(r, &req)
if err != nil { if err != nil {
logx.Error(err) logx.Error(err)
httpx.WriteJsonCtx( httpx.WriteJsonCtx(

View File

@@ -11,16 +11,16 @@ import (
"schisandra-album-cloud-microservices/app/core/api/internal/types" "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) { return func(w http.ResponseWriter, r *http.Request) {
var req types.UserDeviceRequest var req types.WechatOffiaccountLoginRequest
if err := httpx.Parse(r, &req); err != nil { if err := httpx.Parse(r, &req); err != nil {
httpx.ErrorCtx(r.Context(), w, err) httpx.ErrorCtx(r.Context(), w, err)
return return
} }
l := user.NewGetUserDeviceLogic(r.Context(), svcCtx) l := user.NewWechatOffiaccountLoginLogic(r.Context(), svcCtx)
resp, err := l.GetUserDevice(r, w, &req) resp, err := l.WechatOffiaccountLogin(r, &req)
if err != nil { if err != nil {
logx.Error(err) logx.Error(err)
httpx.WriteJsonCtx( httpx.WriteJsonCtx(

View File

@@ -149,7 +149,7 @@ func (l *GiteeCallbackLogic) GiteeCallback(w http.ResponseWriter, r *http.Reques
_ = tx.Rollback() _ = tx.Rollback()
return "", err return "", err
} }
data, err := HandleOauthLoginResponse(addUser, l.svcCtx, r, w, l.ctx) data, err := HandleOauthLoginResponse(addUser, l.svcCtx, r, l.ctx)
if err != nil { if err != nil {
_ = tx.Rollback() _ = tx.Rollback()
return "", err return "", err
@@ -167,7 +167,7 @@ func (l *GiteeCallbackLogic) GiteeCallback(w http.ResponseWriter, r *http.Reques
return "", err return "", err
} }
data, err := HandleOauthLoginResponse(authUserInfo, l.svcCtx, r, w, l.ctx) data, err := HandleOauthLoginResponse(authUserInfo, l.svcCtx, r, l.ctx)
if err != nil { if err != nil {
_ = tx.Rollback() _ = tx.Rollback()
return "", err return "", err
@@ -180,13 +180,12 @@ func (l *GiteeCallbackLogic) GiteeCallback(w http.ResponseWriter, r *http.Reques
} }
// HandleOauthLoginResponse 处理登录响应 // HandleOauthLoginResponse 处理登录响应
func HandleOauthLoginResponse(scaAuthUser *model.ScaAuthUser, svcCtx *svc.ServiceContext, r *http.Request, w http.ResponseWriter, ctx context.Context) (string, error) { func HandleOauthLoginResponse(scaAuthUser *model.ScaAuthUser, svcCtx *svc.ServiceContext, r *http.Request, ctx context.Context) (string, error) {
data, err := user.HandleUserLogin(scaAuthUser, svcCtx, true, r, w, ctx) data, err := user.HandleLoginJWT(scaAuthUser, svcCtx, true, r, ctx)
if err != nil { if err != nil {
return "", err return "", err
} }
responseData := response.SuccessWithData(data) marshalData, err := json.Marshal(response.SuccessWithData(data))
marshalData, err := json.Marshal(responseData)
if err != nil { if err != nil {
return "", err return "", err
} }

View File

@@ -149,7 +149,7 @@ func (l *GithubCallbackLogic) GithubCallback(w http.ResponseWriter, r *http.Requ
return "", err return "", err
} }
data, err := HandleOauthLoginResponse(addUser, l.svcCtx, r, w, l.ctx) data, err := HandleOauthLoginResponse(addUser, l.svcCtx, r, l.ctx)
if err != nil { if err != nil {
_ = tx.Rollback() _ = tx.Rollback()
return "", err return "", err
@@ -167,7 +167,7 @@ func (l *GithubCallbackLogic) GithubCallback(w http.ResponseWriter, r *http.Requ
return "", err return "", err
} }
data, err := HandleOauthLoginResponse(authUserInfo, l.svcCtx, r, w, l.ctx) data, err := HandleOauthLoginResponse(authUserInfo, l.svcCtx, r, l.ctx)
if err != nil { if err != nil {
_ = tx.Rollback() _ = tx.Rollback()
return "", err return "", err

View File

@@ -149,7 +149,7 @@ func (l *QqCallbackLogic) QqCallback(w http.ResponseWriter, r *http.Request, req
return "", err return "", err
} }
data, err := HandleOauthLoginResponse(addUser, l.svcCtx, r, w, l.ctx) data, err := HandleOauthLoginResponse(addUser, l.svcCtx, r, l.ctx)
if err != nil { if err != nil {
_ = tx.Rollback() _ = tx.Rollback()
return "", err return "", err
@@ -167,7 +167,7 @@ func (l *QqCallbackLogic) QqCallback(w http.ResponseWriter, r *http.Request, req
return "", err return "", err
} }
data, err := HandleOauthLoginResponse(authUserInfo, l.svcCtx, r, w, l.ctx) data, err := HandleOauthLoginResponse(authUserInfo, l.svcCtx, r, l.ctx)
if err != nil { if err != nil {
_ = tx.Rollback() _ = tx.Rollback()
return "", err return "", err

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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) { func (l *RefreshTokenLogic) RefreshToken(r *http.Request) (resp *types.Response, err error) {
session, err := l.svcCtx.Session.Get(r, constant.SESSION_KEY) userId := r.Header.Get(constant.UID_HEADER_KEY)
if err != nil { if userId == "" {
return nil, err
}
userId, ok := session.Values["user_id"].(string)
if !ok {
return response.ErrorWithCode(403), nil return response.ErrorWithCode(403), nil
} }
tokenData := l.svcCtx.RedisClient.Get(l.ctx, constant.UserTokenPrefix+userId).Val() 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 { if err != nil {
return nil, err return nil, err
} }
if redisTokenData.Revoked {
return response.ErrorWithCode(403), nil
}
refreshToken, result := jwt.ParseRefreshToken(l.svcCtx.Config.Auth.AccessSecret, redisTokenData.RefreshToken) refreshToken, result := jwt.ParseRefreshToken(l.svcCtx.Config.Auth.AccessSecret, redisTokenData.RefreshToken)
if !result { if !result {
return response.ErrorWithCode(403), nil return response.ErrorWithCode(403), nil
@@ -62,6 +61,7 @@ func (l *RefreshTokenLogic) RefreshToken(r *http.Request) (resp *types.Response,
AccessToken: accessToken, AccessToken: accessToken,
RefreshToken: redisTokenData.RefreshToken, RefreshToken: redisTokenData.RefreshToken,
UID: refreshToken.UserID, UID: refreshToken.UserID,
Revoked: false,
} }
err = l.svcCtx.RedisClient.Set(l.ctx, constant.UserTokenPrefix+refreshToken.UserID, redisToken, time.Hour*24*7).Err() err = l.svcCtx.RedisClient.Set(l.ctx, constant.UserTokenPrefix+refreshToken.UserID, redisToken, time.Hour*24*7).Err()
if err != nil { if err != nil {

View File

@@ -3,7 +3,8 @@ package user
import ( import (
"context" "context"
"errors" "errors"
"github.com/rbcervilla/redisstore/v9" "github.com/lionsoul2014/ip2region/binding/golang/xdb"
"github.com/mssola/useragent"
"net/http" "net/http"
"time" "time"
@@ -65,19 +66,20 @@ func (l *AccountLoginLogic) AccountLogin(w http.ResponseWriter, r *http.Request,
if !utils.Verify(userInfo.Password, req.Password) { if !utils.Verify(userInfo.Password, req.Password) {
return response.ErrorWithI18n(l.ctx, "login.invalidPassword"), nil 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 { if err != nil {
return nil, err 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 return response.SuccessWithData(data), nil
} }
// HandleUserLogin 处理用户登录 // HandleLoginJWT 处理用户登录
func HandleUserLogin(user *model.ScaAuthUser, svcCtx *svc.ServiceContext, autoLogin bool, r *http.Request, w http.ResponseWriter, ctx context.Context) (*types.LoginResponse, error) { 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 // 生成jwt token
accessToken := jwt.GenerateAccessToken(svcCtx.Config.Auth.AccessSecret, jwt.AccessJWTPayload{ accessToken := jwt.GenerateAccessToken(svcCtx.Config.Auth.AccessSecret, jwt.AccessJWTPayload{
UserID: user.UID, UserID: user.UID,
@@ -85,9 +87,9 @@ func HandleUserLogin(user *model.ScaAuthUser, svcCtx *svc.ServiceContext, autoLo
}) })
var days time.Duration var days time.Duration
if autoLogin { if autoLogin {
days = 7 * 24 * time.Hour days = 24 * time.Hour
} else { } else {
days = time.Hour * 24 days = time.Hour * 1
} }
refreshToken := jwt.GenerateRefreshToken(svcCtx.Config.Auth.AccessSecret, jwt.RefreshJWTPayload{ refreshToken := jwt.GenerateRefreshToken(svcCtx.Config.Auth.AccessSecret, jwt.RefreshJWTPayload{
UserID: user.UID, UserID: user.UID,
@@ -106,29 +108,76 @@ func HandleUserLogin(user *model.ScaAuthUser, svcCtx *svc.ServiceContext, autoLo
AccessToken: accessToken, AccessToken: accessToken,
RefreshToken: refreshToken, RefreshToken: refreshToken,
UID: user.UID, UID: user.UID,
Revoked: false,
} }
err := svcCtx.RedisClient.Set(ctx, constant.UserTokenPrefix+user.UID, redisToken, days).Err() 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)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &data, nil return &data, nil
} }
// HandlerSession is a function to set the user_id in the session // GetUserLoginDevice 获取用户登录设备
func HandlerSession(r *http.Request, w http.ResponseWriter, userID string, redisSession *redisstore.RedisStore) error { func GetUserLoginDevice(userId string, r *http.Request, ip2location *xdb.Searcher, DB *query.Query) error {
session, err := redisSession.Get(r, constant.SESSION_KEY) userAgent := r.UserAgent()
if userAgent == "" {
return errors.New("user agent not found")
}
ip := utils.GetClientIP(r)
location, err := ip2location.SearchByStr(ip)
if err != nil { if err != nil {
return err return err
} }
session.Values["user_id"] = userID location = utils.RemoveZeroAndAdjust(location)
err = session.Save(r, w)
if err != nil { 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 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
}
} }

View File

@@ -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
}
}

View File

@@ -1,37 +1,36 @@
package oauth package user
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"net/http"
"time"
"github.com/ArtisanCloud/PowerWeChat/v3/src/basicService/qrCode/response" "github.com/ArtisanCloud/PowerWeChat/v3/src/basicService/qrCode/response"
"net/http"
"schisandra-album-cloud-microservices/app/core/api/common/constant" "schisandra-album-cloud-microservices/app/core/api/common/constant"
response2 "schisandra-album-cloud-microservices/app/core/api/common/response" response2 "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/common/utils"
"time"
"schisandra-album-cloud-microservices/app/core/api/internal/svc" "schisandra-album-cloud-microservices/app/core/api/internal/svc"
"schisandra-album-cloud-microservices/app/core/api/internal/types" "schisandra-album-cloud-microservices/app/core/api/internal/types"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
) )
type GetWechatQrcodeLogic struct { type GetWechatOffiaccountQrcodeLogic struct {
logx.Logger logx.Logger
ctx context.Context ctx context.Context
svcCtx *svc.ServiceContext svcCtx *svc.ServiceContext
} }
func NewGetWechatQrcodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetWechatQrcodeLogic { func NewGetWechatOffiaccountQrcodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetWechatOffiaccountQrcodeLogic {
return &GetWechatQrcodeLogic{ return &GetWechatOffiaccountQrcodeLogic{
Logger: logx.WithContext(ctx), Logger: logx.WithContext(ctx),
ctx: ctx, ctx: ctx,
svcCtx: svcCtx, 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 ip := utils.GetClientIP(r) // 使用工具函数获取客户端IP
key := constant.UserQrcodePrefix + 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 { if err != nil {
return nil, err return nil, err
} }

View File

@@ -79,32 +79,22 @@ func (l *PhoneLoginLogic) PhoneLogin(r *http.Request, w http.ResponseWriter, req
_ = tx.Rollback() _ = tx.Rollback()
return nil, err 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 { if err != nil {
_ = tx.Rollback() _ = tx.Rollback()
return nil, err 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() err = tx.Commit()
if err != nil { if err != nil {
return nil, err return nil, err
} }
return response.SuccessWithData(data), nil return response.SuccessWithData(data), nil
} else { } 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 { if err != nil {
_ = tx.Rollback() _ = tx.Rollback()
return nil, err 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() err = tx.Commit()
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -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
}
}

View File

@@ -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)
}
}

View File

@@ -1,37 +1,24 @@
package middleware package middleware
import ( import (
"github.com/casbin/casbin/v2"
"net/http" "net/http"
"schisandra-album-cloud-microservices/app/core/api/common/constant" "schisandra-album-cloud-microservices/app/core/api/common/constant"
"github.com/casbin/casbin/v2"
"github.com/rbcervilla/redisstore/v9"
) )
type CasbinVerifyMiddleware struct { type CasbinVerifyMiddleware struct {
casbin *casbin.SyncedCachedEnforcer casbin *casbin.SyncedCachedEnforcer
session *redisstore.RedisStore
} }
func NewCasbinVerifyMiddleware(casbin *casbin.SyncedCachedEnforcer, session *redisstore.RedisStore) *CasbinVerifyMiddleware { func NewCasbinVerifyMiddleware(casbin *casbin.SyncedCachedEnforcer) *CasbinVerifyMiddleware {
return &CasbinVerifyMiddleware{ return &CasbinVerifyMiddleware{
casbin: casbin, casbin: casbin,
session: session,
} }
} }
func (m *CasbinVerifyMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc { func (m *CasbinVerifyMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
session, err := m.session.Get(r, constant.SESSION_KEY) userId := r.Header.Get(constant.UID_HEADER_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
}
correct, err := m.casbin.Enforce(userId, r.URL.Path, r.Method) correct, err := m.casbin.Enforce(userId, r.URL.Path, r.Method)
if err != nil || !correct { if err != nil || !correct {
http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden) http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)

View File

@@ -4,7 +4,6 @@ import (
"github.com/ArtisanCloud/PowerWeChat/v3/src/officialAccount" "github.com/ArtisanCloud/PowerWeChat/v3/src/officialAccount"
"github.com/casbin/casbin/v2" "github.com/casbin/casbin/v2"
"github.com/lionsoul2014/ip2region/binding/golang/xdb" "github.com/lionsoul2014/ip2region/binding/golang/xdb"
"github.com/rbcervilla/redisstore/v9"
"github.com/redis/go-redis/v9" "github.com/redis/go-redis/v9"
"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"
@@ -20,7 +19,6 @@ import (
"schisandra-album-cloud-microservices/app/core/api/repository/mongodb" "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"
"schisandra-album-cloud-microservices/app/core/api/repository/mysql/query" "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/redisx"
"schisandra-album-cloud-microservices/app/core/api/repository/sensitivex" "schisandra-album-cloud-microservices/app/core/api/repository/sensitivex"
"schisandra-album-cloud-microservices/app/core/api/repository/wechat_official" "schisandra-album-cloud-microservices/app/core/api/repository/wechat_official"
@@ -30,13 +28,13 @@ type ServiceContext struct {
Config config.Config Config config.Config
SecurityHeadersMiddleware rest.Middleware SecurityHeadersMiddleware rest.Middleware
CasbinVerifyMiddleware rest.Middleware CasbinVerifyMiddleware rest.Middleware
AuthorizationMiddleware rest.Middleware
DB *query.Query DB *query.Query
RedisClient *redis.Client RedisClient *redis.Client
MongoClient *mongo.Database MongoClient *mongo.Database
Session *redisstore.RedisStore
Ip2Region *xdb.Searcher Ip2Region *xdb.Searcher
CasbinEnforcer *casbin.SyncedCachedEnforcer CasbinEnforcer *casbin.SyncedCachedEnforcer
WechatPublic *officialAccount.OfficialAccount WechatOfficial *officialAccount.OfficialAccount
Sensitive *sensitive.Manager Sensitive *sensitive.Manager
RotateCaptcha rotate.Captcha RotateCaptcha rotate.Captcha
SlideCaptcha slide.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) 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) db, queryDB := mysql.NewMySQL(c.Mysql.DataSource, c.Mysql.MaxOpenConn, c.Mysql.MaxIdleConn, redisClient)
casbinEnforcer := casbinx.NewCasbin(db) casbinEnforcer := casbinx.NewCasbin(db)
session := redis_session.NewRedisSession(redisClient)
return &ServiceContext{ return &ServiceContext{
Config: c, Config: c,
SecurityHeadersMiddleware: middleware.NewSecurityHeadersMiddleware().Handle, SecurityHeadersMiddleware: middleware.NewSecurityHeadersMiddleware().Handle,
CasbinVerifyMiddleware: middleware.NewCasbinVerifyMiddleware(casbinEnforcer, session).Handle, CasbinVerifyMiddleware: middleware.NewCasbinVerifyMiddleware(casbinEnforcer).Handle,
AuthorizationMiddleware: middleware.NewAuthorizationMiddleware(redisClient).Handle,
DB: queryDB, DB: queryDB,
RedisClient: redisClient, RedisClient: redisClient,
MongoClient: mongodb.NewMongoDB(c.Mongo.Uri, c.Mongo.Username, c.Mongo.Password, c.Mongo.AuthSource, c.Mongo.Database), MongoClient: mongodb.NewMongoDB(c.Mongo.Uri, c.Mongo.Username, c.Mongo.Password, c.Mongo.AuthSource, c.Mongo.Database),
Session: session,
Ip2Region: ip2region.NewIP2Region(), Ip2Region: ip2region.NewIP2Region(),
CasbinEnforcer: casbinEnforcer, 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(), Sensitive: sensitivex.NewSensitive(),
RotateCaptcha: captcha.NewRotateCaptcha(), RotateCaptcha: captcha.NewRotateCaptcha(),
SlideCaptcha: captcha.NewSlideCaptcha(), SlideCaptcha: captcha.NewSlideCaptcha(),

View File

@@ -6,6 +6,7 @@ type RedisToken struct {
AccessToken string `json:"access_token"` AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"` RefreshToken string `json:"refresh_token"`
UID string `json:"uid"` UID string `json:"uid"`
Revoked bool `json:"revoked" default:"false"`
} }
func (res RedisToken) MarshalBinary() ([]byte, error) { func (res RedisToken) MarshalBinary() ([]byte, error) {

View File

@@ -119,6 +119,7 @@ type UploadRequest struct {
UserId string `json:"user_id"` UserId string `json:"user_id"`
} }
type UserDeviceRequest struct { type WechatOffiaccountLoginRequest struct {
AccessToken string `json:"access_token"` Openid string `json:"openid"`
ClientId string `json:"client_id"`
} }

View File

@@ -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
}

21
go.mod
View File

@@ -4,7 +4,7 @@ go 1.23.4
require ( require (
github.com/ArtisanCloud/PowerLibs/v3 v3.2.6 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/asjdf/gorm-cache v1.2.3
github.com/casbin/casbin/v2 v2.102.0 github.com/casbin/casbin/v2 v2.102.0
github.com/casbin/gorm-adapter/v3 v3.32.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/chenmingyong0423/go-mongox/v2 v2.0.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/sessions v1.4.0
github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20240510055607-89e20ab7b6c6 github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20240510055607-89e20ab7b6c6
github.com/lxzan/gws v1.8.8 github.com/lxzan/gws v1.8.8
github.com/microcosm-cc/bluemonday v1.0.27 github.com/microcosm-cc/bluemonday v1.0.27
@@ -20,7 +19,6 @@ require (
github.com/nicksnyder/go-i18n/v2 v2.4.1 github.com/nicksnyder/go-i18n/v2 v2.4.1
github.com/pelletier/go-toml/v2 v2.2.3 github.com/pelletier/go-toml/v2 v2.2.3
github.com/pkg6/go-sms v0.1.2 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/redis/go-redis/v9 v9.7.0
github.com/wenlng/go-captcha-assets v1.0.1 github.com/wenlng/go-captcha-assets v1.0.1
github.com/wenlng/go-captcha/v2 v2.0.2 github.com/wenlng/go-captcha/v2 v2.0.2
@@ -30,7 +28,7 @@ require (
go.mongodb.org/mongo-driver/v2 v2.0.0 go.mongodb.org/mongo-driver/v2 v2.0.0
golang.org/x/crypto v0.31.0 golang.org/x/crypto v0.31.0
golang.org/x/text v0.21.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/driver/mysql v1.5.7
gorm.io/gen v0.3.26 gorm.io/gen v0.3.26
gorm.io/gorm v1.25.12 gorm.io/gorm v1.25.12
@@ -72,8 +70,7 @@ require (
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
github.com/google/uuid v1.6.0 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/css v1.0.1 // 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.25.1 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/imroc/req/v3 v3.49.0 // 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/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/ncruces/go-strftime v0.1.9 // 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/openzipkin/zipkin-go v0.4.3 // indirect
github.com/orcaman/concurrent-map/v2 v2.0.1 // indirect github.com/orcaman/concurrent-map/v2 v2.0.1 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // 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/mock v0.5.0 // indirect
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.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/image v0.23.0 // indirect
golang.org/x/mod v0.22.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/sync v0.10.0 // indirect
golang.org/x/sys v0.28.0 // indirect golang.org/x/sys v0.28.0 // indirect
golang.org/x/tools 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/api v0.0.0-20241219192143-6b3ec007d9bb // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241216192217-9240e9c98484 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20241219192143-6b3ec007d9bb // indirect
google.golang.org/protobuf v1.36.0 // indirect google.golang.org/protobuf v1.36.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
@@ -149,5 +146,5 @@ require (
modernc.org/libc v1.61.4 // indirect modernc.org/libc v1.61.4 // indirect
modernc.org/mathutil v1.6.0 // indirect modernc.org/mathutil v1.6.0 // indirect
modernc.org/memory v1.8.0 // indirect modernc.org/memory v1.8.0 // indirect
modernc.org/sqlite v1.34.2 // indirect modernc.org/sqlite v1.34.3 // indirect
) )

29
go.sum
View File

@@ -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/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 h1:6IEFuaPJdB2HVGePyInVN9KuSiXk83Kfls4rYZd0mXQ=
github.com/ArtisanCloud/PowerWeChat/v3 v3.2.57/go.mod h1:D2cB1wtwC1YgzYT1Ni8NWS5wJCm5n1T18TybXkFlwvo= 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.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.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= 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.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 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= 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 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= 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= 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 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/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 h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= 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= 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 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= 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.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.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 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.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 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= 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= 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/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 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg=
github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= 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 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8=
github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc= 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 h1:9EGwpqkgnwdEIJ+Od7QVSEIH+ocmm5nPat0G7sjsSdg=
github.com/openzipkin/zipkin-go v0.4.3/go.mod h1:M9wCJZFWCo2RiY+o1eBCEMe0Dp2S5LDHcMZmk3RmK7c= 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= 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/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 h1:wsKXZPeGWpMpCGSWqOcqpW2wZYic/8T3aqiOID0/KWE=
github.com/quic-go/quic-go v0.48.2/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs= 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 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E=
github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw= github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw=
github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM= 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/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 h1:dB9S9kNklksOODGLLAov0RaVCwC2w9Kwxz6NZMdM6rk=
github.com/zmexing/go-sensitive-word v1.3.0/go.mod h1:wkNIpkq1iPOe3l7l83zvnnV5mm20jfj2x8V8kjOTsUM= 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 h1:Jfd7XpdZa9yk3eY774bO7SWVb30noLSirL9nKTpavhI=
go.mongodb.org/mongo-driver/v2 v2.0.0/go.mod h1:nSjmNq4JUstE8IRZKTktLgMHM4F1fccL6HGX1yh+8RA= 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= 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/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 h1:4qufH0hlUYs6AO6XmZC3GqfDPGSXHVXUFR6OND+iJX4=
golang.org/x/exp v0.0.0-20241215155358-4a5509556b9e/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= 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.16.0/go.mod h1:ugSZItdV4nOxyqp56HmXwH0Ry0nBCpjnZdpDaIHdoPs=
golang.org/x/image v0.23.0 h1:HseQ7c2OpPKTPVzNjG5fwJsOTCiiwS4QdsYi5XU6H68= golang.org/x/image v0.23.0 h1:HseQ7c2OpPKTPVzNjG5fwJsOTCiiwS4QdsYi5XU6H68=
golang.org/x/image v0.23.0/go.mod h1:wJJBTdLfCCf3tiHa1fNxpZmUI4mmoZvwMCPP0ddoNKY= 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.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 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= 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-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.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/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= 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 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-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 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-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 h1:quSiOM1GJPmPH5XtU+BCoVXcDVJJAzNcoyfC2cCjGkI=
google.golang.org/grpc v1.69.0/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= 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 h1:mjIs9gYtt56AzC4ZaffQuh88TZurBGhIJMBZGSxNerQ=
google.golang.org/protobuf v1.36.0/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= 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= 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/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss=
modernc.org/sqlite v1.34.2 h1:J9n76TPsfYYkFkZ9Uy1QphILYifiVEwwOT7yP5b++2Y= 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.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 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=