rainycode 1.1.1__tar.gz → 1.1.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. {rainycode-1.1.1 → rainycode-1.1.3}/PKG-INFO +1 -1
  2. {rainycode-1.1.1 → rainycode-1.1.3}/common_base/consts.py +0 -1
  3. {rainycode-1.1.1 → rainycode-1.1.3}/common_servers/api/auth_api.py +5 -17
  4. {rainycode-1.1.1 → rainycode-1.1.3}/common_servers/service/auth_svc.py +21 -41
  5. {rainycode-1.1.1 → rainycode-1.1.3}/pyproject.toml +1 -1
  6. {rainycode-1.1.1 → rainycode-1.1.3}/rainycode.egg-info/PKG-INFO +1 -1
  7. {rainycode-1.1.1 → rainycode-1.1.3}/common_base/aiorequests.py +0 -0
  8. {rainycode-1.1.1 → rainycode-1.1.3}/common_base/exception.py +0 -0
  9. {rainycode-1.1.1 → rainycode-1.1.3}/common_base/logging.py +0 -0
  10. {rainycode-1.1.1 → rainycode-1.1.3}/common_base/response.py +0 -0
  11. {rainycode-1.1.1 → rainycode-1.1.3}/common_depends/auth_depend.py +0 -0
  12. {rainycode-1.1.1 → rainycode-1.1.3}/common_models/__init__.py +0 -0
  13. {rainycode-1.1.1 → rainycode-1.1.3}/common_models/base_model.py +0 -0
  14. {rainycode-1.1.1 → rainycode-1.1.3}/common_models/user_model.py +0 -0
  15. {rainycode-1.1.1 → rainycode-1.1.3}/common_models/wechat_model.py +0 -0
  16. {rainycode-1.1.1 → rainycode-1.1.3}/common_servers/api/wechat_api.py +0 -0
  17. {rainycode-1.1.1 → rainycode-1.1.3}/common_servers/router.py +0 -0
  18. {rainycode-1.1.1 → rainycode-1.1.3}/common_servers/schemas/__init__.py +0 -0
  19. {rainycode-1.1.1 → rainycode-1.1.3}/common_servers/schemas/auth_schema.py +0 -0
  20. {rainycode-1.1.1 → rainycode-1.1.3}/common_servers/service/wechat_svc.py +0 -0
  21. {rainycode-1.1.1 → rainycode-1.1.3}/common_utils/bcrypt_util.py +0 -0
  22. {rainycode-1.1.1 → rainycode-1.1.3}/common_utils/captcha_util.py +0 -0
  23. {rainycode-1.1.1 → rainycode-1.1.3}/common_utils/ip_util.py +0 -0
  24. {rainycode-1.1.1 → rainycode-1.1.3}/common_utils/jwt_util.py +0 -0
  25. {rainycode-1.1.1 → rainycode-1.1.3}/common_utils/snowflake_util.py +0 -0
  26. {rainycode-1.1.1 → rainycode-1.1.3}/common_utils/wechat_util.py +0 -0
  27. {rainycode-1.1.1 → rainycode-1.1.3}/core/base_config.py +0 -0
  28. {rainycode-1.1.1 → rainycode-1.1.3}/core/databases/aiodb.py +0 -0
  29. {rainycode-1.1.1 → rainycode-1.1.3}/core/databases/aioredis.py +0 -0
  30. {rainycode-1.1.1 → rainycode-1.1.3}/core/middleware/http_middleware.py +0 -0
  31. {rainycode-1.1.1 → rainycode-1.1.3}/core/start.py +0 -0
  32. {rainycode-1.1.1 → rainycode-1.1.3}/rainycode.egg-info/SOURCES.txt +0 -0
  33. {rainycode-1.1.1 → rainycode-1.1.3}/rainycode.egg-info/dependency_links.txt +0 -0
  34. {rainycode-1.1.1 → rainycode-1.1.3}/rainycode.egg-info/requires.txt +0 -0
  35. {rainycode-1.1.1 → rainycode-1.1.3}/rainycode.egg-info/top_level.txt +0 -0
  36. {rainycode-1.1.1 → rainycode-1.1.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rainycode
3
- Version: 1.1.1
3
+ Version: 1.1.3
4
4
  Summary: FastAPI base modules
5
5
  Requires-Python: >=3.8
6
6
  Requires-Dist: build==1.4.0
@@ -4,6 +4,5 @@ REDIS_PREFIX_USER_INFO: str = "user:info:"
4
4
  REDIS_PREFIX_OAUTH_STATE: str = "oauth:state:"
5
5
  REDIS_PREFIX_WECHAT_CODE: str = "wechat:code:"
6
6
  REDIS_PREFIX_WECHAT_OAUTH_CODE: str = "wechat:oauth:code:"
7
- REDIS_PREFIX_TEMP_CODE: str = "oauth:temp_code:"
8
7
  REDIS_PREFIX_LOGIN_LOCK_USER: str = "auth:login_lock:user:"
9
8
  REDIS_PREFIX_LOGIN_LOCK_IP: str = "auth:login_lock:ip:"
@@ -1,7 +1,7 @@
1
1
  from common_models.user_model import User
2
- from fastapi import APIRouter, Security, Body, Depends, Query, Request
2
+ from fastapi import APIRouter, Security, Body, Query, Request
3
3
  from common_base.response import SuccessReturn
4
- from common_depends.auth_depend import login_require, oauth2_scheme
4
+ from common_depends.auth_depend import login_require
5
5
  from common_servers.schemas.auth_schema import *
6
6
  from common_servers.service.auth_svc import AuthService
7
7
 
@@ -58,7 +58,7 @@ async def login_mini(wechat_in: WechatLogin):
58
58
 
59
59
  @router.get("/wechat/oauth", summary="获取微信网页授权链接 - 回调(/oauth/callback)")
60
60
  async def get_wechat_oauth_url(
61
- app_id: str = Query(..., description="微信 AppID"),
61
+ app_pk: int = Query(..., description="微信应用主键ID"),
62
62
  redirect_uri: str = Query(..., description="授权成功后跳转地址"),
63
63
  state: str | None = Query(default=None, description="自定义状态参数"),
64
64
  ):
@@ -69,17 +69,5 @@ async def get_wechat_oauth_url(
69
69
  - 如果用户已注册,回调后直接返回 token
70
70
  - 如果用户未注册,自动重定向到 snsapi_userinfo 授权
71
71
  """
72
- authorize_url = await AuthService.get_wechat_oauth_url(app_id, redirect_uri, state)
73
- return SuccessReturn(data={"authorize_url": authorize_url})
74
-
75
-
76
- @router.get("/wechat/token", summary="通过临时授权码获取 token")
77
- async def get_token_by_temp_code(code: str = Query(..., description="临时授权码")):
78
- """
79
- OAuth 回调后,前端使用临时码换取 token
80
-
81
- - 临时码有效期:120 秒
82
- - 一次性使用,获取后立即失效
83
- """
84
- token_data = await AuthService.get_token_by_temp_code(code)
85
- return SuccessReturn(data=token_data, msg="获取成功")
72
+ authorize_url = await AuthService.get_wechat_oauth_url(app_pk, redirect_uri, state)
73
+ return SuccessReturn(data={"authorize_url": authorize_url})
@@ -11,7 +11,6 @@ from common_base.consts import (
11
11
  REDIS_PREFIX_USER_INFO,
12
12
  REDIS_PREFIX_WECHAT_CODE,
13
13
  REDIS_PREFIX_WECHAT_OAUTH_CODE,
14
- REDIS_PREFIX_TEMP_CODE,
15
14
  REDIS_PREFIX_LOGIN_LOCK_USER,
16
15
  REDIS_PREFIX_LOGIN_LOCK_IP,
17
16
  )
@@ -33,7 +32,6 @@ from core.base_config import base_config
33
32
  LOGIN_FAIL_LIMIT = 5 # 最大失败次数
34
33
  LOGIN_LOCK_SECONDS = 900 # 锁定时间(15分钟)
35
34
  IP_FAIL_LIMIT = 20 # 单 IP 最大失败次数
36
- TEMP_CODE_EXPIRE_SECONDS = 120 # 临时授权码有效期
37
35
 
38
36
 
39
37
  class AuthService:
@@ -148,17 +146,17 @@ class AuthService:
148
146
  logger.info(f"用户登出: user_id={user_id}, username={username}")
149
147
 
150
148
  @classmethod
151
- async def get_wechat_oauth_url(cls, app_id: str, redirect_uri: str, state: str | None = None) -> str:
149
+ async def get_wechat_oauth_url(cls, app_pk: int, redirect_uri: str, state: str | None = None) -> str:
152
150
  """
153
151
  生成微信网页授权链接(snsapi_base)
154
152
 
155
- :param app_id: 微信 AppID
153
+ :param app_pk: 微信应用主键ID
156
154
  :param redirect_uri: 授权成功后跳转的前端地址
157
155
  :param state: 自定义状态参数
158
156
  :return: 微信授权链接
159
157
  """
160
158
  # 验证公众号配置
161
- app_config = await WechatApp.get_or_none(app_id=app_id, app_type=AppTypeEnum.OFFICIAL_ACCOUNT)
159
+ app_config = await WechatApp.get_or_none(id=app_pk, app_type=AppTypeEnum.OFFICIAL_ACCOUNT)
162
160
  if not app_config:
163
161
  raise CustomException(msg="无效的公众号配置")
164
162
 
@@ -170,8 +168,8 @@ class AuthService:
170
168
  # 生成内部 state
171
169
  internal_state = state or str(uuid.uuid4())
172
170
 
173
- # 缓存 state -> (redirect_uri, app_id) 映射,有效期 5 分钟
174
- cache_value = json.dumps({"redirect_uri": redirect_uri, "app_id": app_id})
171
+ # 缓存 state -> (redirect_uri, app_pk) 映射,有效期 5 分钟
172
+ cache_value = json.dumps({"redirect_uri": redirect_uri, "app_pk": app_pk})
175
173
  await AioRedis.set(f"{REDIS_PREFIX_OAUTH_STATE}{internal_state}", cache_value, ex=300)
176
174
 
177
175
  # 构建回调地址
@@ -204,11 +202,11 @@ class AuthService:
204
202
  try:
205
203
  cached_data = json.loads(cache_value)
206
204
  redirect_uri = cached_data.get("redirect_uri")
207
- app_id = cached_data.get("app_id")
205
+ app_pk = cached_data.get("app_pk")
208
206
  except (json.JSONDecodeError, TypeError):
209
207
  raise CustomException(msg="授权数据格式错误")
210
208
 
211
- if not redirect_uri or not app_id:
209
+ if not redirect_uri or not app_pk:
212
210
  raise CustomException(msg="授权数据不完整")
213
211
 
214
212
  # 删除已使用的 state
@@ -220,7 +218,7 @@ class AuthService:
220
218
  raise CustomException(msg="授权码已失效,请重新授权")
221
219
 
222
220
  # 获取公众号配置
223
- app_config = await WechatApp.get_or_none(app_id=app_id, app_type=AppTypeEnum.OFFICIAL_ACCOUNT)
221
+ app_config = await WechatApp.get_or_none(id=app_pk, app_type=AppTypeEnum.OFFICIAL_ACCOUNT)
224
222
  if not app_config:
225
223
  raise CustomException(msg="公众号配置不存在")
226
224
 
@@ -283,22 +281,6 @@ class AuthService:
283
281
 
284
282
  return RedirectResponse(url=userinfo_auth_url, status_code=302)
285
283
 
286
- @classmethod
287
- async def get_token_by_temp_code(cls, temp_code: str) -> dict:
288
- """
289
- 通过临时授权码获取 token
290
- """
291
- cache_key = f"{REDIS_PREFIX_TEMP_CODE}{temp_code}"
292
- cache_value = await AioRedis.get(cache_key)
293
-
294
- if not cache_value:
295
- raise CustomException(msg="临时授权码已过期,请重新授权")
296
-
297
- # 删除临时码(一次性使用)
298
- await AioRedis.delete(cache_key)
299
-
300
- return json.loads(cache_value)
301
-
302
284
  # ==================== 私有方法 ====================
303
285
 
304
286
  @classmethod
@@ -529,22 +511,20 @@ class AuthService:
529
511
  return user
530
512
 
531
513
  @classmethod
532
- async def _build_redirect_response(cls, redirect_uri: str, token_data: dict, state: str | None = None) -> RedirectResponse:
533
- """构建带临时码的重定向响应"""
534
- # 生成临时授权码
535
- temp_code = str(uuid.uuid4())
536
-
537
- # 缓存 token 数据
538
- await AioRedis.set(
539
- f"{REDIS_PREFIX_TEMP_CODE}{temp_code}",
540
- json.dumps(token_data),
541
- ex=TEMP_CODE_EXPIRE_SECONDS
542
- )
543
-
544
- # 构建重定向 URL
545
- params = {"temp_code": temp_code}
514
+ async def _build_redirect_response(
515
+ cls, redirect_uri: str, token_data: dict, state: str | None = None
516
+ ) -> RedirectResponse:
517
+ """构建带 token 的重定向响应(使用 URL Fragment)"""
518
+ params = {
519
+ "access_token": token_data["access_token"],
520
+ "refresh_token": token_data["refresh_token"],
521
+ "token_type": token_data["token_type"],
522
+ "expires_in": str(token_data["expires_in"]),
523
+ }
546
524
  if state:
547
525
  params["state"] = state
548
526
 
549
- redirect_url = f"{redirect_uri}?{urlencode(params)}"
527
+ # 使用 # fragment 传递 token,避免出现在服务器日志中
528
+ fragment = urlencode(params)
529
+ redirect_url = f"{redirect_uri}#{fragment}"
550
530
  return RedirectResponse(url=redirect_url, status_code=302)
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "rainycode"
7
- version = "1.1.1"
7
+ version = "1.1.3"
8
8
  description = "FastAPI base modules"
9
9
  requires-python = ">=3.8"
10
10
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rainycode
3
- Version: 1.1.1
3
+ Version: 1.1.3
4
4
  Summary: FastAPI base modules
5
5
  Requires-Python: >=3.8
6
6
  Requires-Dist: build==1.4.0
File without changes
File without changes
File without changes