rainycode 1.5.4__tar.gz → 1.5.6__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.
- {rainycode-1.5.4 → rainycode-1.5.6}/PKG-INFO +1 -1
- {rainycode-1.5.4 → rainycode-1.5.6}/common_base/exception.py +8 -6
- {rainycode-1.5.4 → rainycode-1.5.6}/common_depends/auth_depend.py +7 -6
- {rainycode-1.5.4 → rainycode-1.5.6}/common_servers/api/auth_api.py +16 -3
- {rainycode-1.5.4 → rainycode-1.5.6}/common_servers/service/auth_svc.py +4 -4
- {rainycode-1.5.4 → rainycode-1.5.6}/common_utils/snowflake_util.py +1 -1
- {rainycode-1.5.4 → rainycode-1.5.6}/common_utils/wechat_util.py +3 -3
- {rainycode-1.5.4 → rainycode-1.5.6}/core/base_config.py +1 -1
- {rainycode-1.5.4 → rainycode-1.5.6}/core/start.py +1 -1
- {rainycode-1.5.4 → rainycode-1.5.6}/pyproject.toml +1 -1
- {rainycode-1.5.4 → rainycode-1.5.6}/rainycode.egg-info/PKG-INFO +1 -1
- {rainycode-1.5.4 → rainycode-1.5.6}/common_base/aiorequests.py +0 -0
- {rainycode-1.5.4 → rainycode-1.5.6}/common_base/consts.py +0 -0
- {rainycode-1.5.4 → rainycode-1.5.6}/common_base/logging.py +0 -0
- {rainycode-1.5.4 → rainycode-1.5.6}/common_base/response.py +0 -0
- {rainycode-1.5.4 → rainycode-1.5.6}/common_models/__init__.py +0 -0
- {rainycode-1.5.4 → rainycode-1.5.6}/common_models/base_model.py +0 -0
- {rainycode-1.5.4 → rainycode-1.5.6}/common_models/file_model.py +0 -0
- {rainycode-1.5.4 → rainycode-1.5.6}/common_models/user_model.py +0 -0
- {rainycode-1.5.4 → rainycode-1.5.6}/common_models/wechat_model.py +0 -0
- {rainycode-1.5.4 → rainycode-1.5.6}/common_servers/api/wechat_api.py +0 -0
- {rainycode-1.5.4 → rainycode-1.5.6}/common_servers/router.py +0 -0
- {rainycode-1.5.4 → rainycode-1.5.6}/common_servers/schemas/auth_schema.py +0 -0
- {rainycode-1.5.4 → rainycode-1.5.6}/common_servers/service/file_svc.py +0 -0
- {rainycode-1.5.4 → rainycode-1.5.6}/common_servers/service/wechat_svc.py +0 -0
- {rainycode-1.5.4 → rainycode-1.5.6}/common_utils/bcrypt_util.py +0 -0
- {rainycode-1.5.4 → rainycode-1.5.6}/common_utils/captcha_util.py +0 -0
- {rainycode-1.5.4 → rainycode-1.5.6}/common_utils/datetime_util.py +0 -0
- {rainycode-1.5.4 → rainycode-1.5.6}/common_utils/ip_util.py +0 -0
- {rainycode-1.5.4 → rainycode-1.5.6}/common_utils/jwt_util.py +0 -0
- {rainycode-1.5.4 → rainycode-1.5.6}/core/databases/aiodb.py +0 -0
- {rainycode-1.5.4 → rainycode-1.5.6}/core/databases/aioredis.py +0 -0
- {rainycode-1.5.4 → rainycode-1.5.6}/core/middleware/http_middleware.py +0 -0
- {rainycode-1.5.4 → rainycode-1.5.6}/rainycode.egg-info/SOURCES.txt +0 -0
- {rainycode-1.5.4 → rainycode-1.5.6}/rainycode.egg-info/dependency_links.txt +0 -0
- {rainycode-1.5.4 → rainycode-1.5.6}/rainycode.egg-info/requires.txt +0 -0
- {rainycode-1.5.4 → rainycode-1.5.6}/rainycode.egg-info/top_level.txt +0 -0
- {rainycode-1.5.4 → rainycode-1.5.6}/setup.cfg +0 -0
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
from typing import cast
|
|
2
2
|
|
|
3
|
-
from common_base.logging import logger
|
|
4
|
-
from common_base.response import ErrorReturn
|
|
5
3
|
from fastapi import HTTPException, Request, status
|
|
6
4
|
from fastapi.exceptions import RequestValidationError, ResponseValidationError
|
|
7
5
|
from starlette.responses import JSONResponse
|
|
8
6
|
|
|
7
|
+
from common_base.logging import logger
|
|
8
|
+
from common_base.response import ErrorReturn
|
|
9
|
+
|
|
9
10
|
|
|
10
11
|
class CustomException(Exception):
|
|
11
12
|
"""自定义异常"""
|
|
12
13
|
def __init__(
|
|
13
|
-
self,
|
|
14
|
+
self,
|
|
14
15
|
msg: str | None = None,
|
|
15
|
-
code: int =
|
|
16
|
+
code: int = -1,
|
|
16
17
|
data: object | None = None,
|
|
17
18
|
status_code: int = status.HTTP_500_INTERNAL_SERVER_ERROR
|
|
18
19
|
) -> None:
|
|
@@ -41,10 +42,11 @@ async def RequestValidationHandle(request: Request, exc: RequestValidationError)
|
|
|
41
42
|
"""请求参数验证异常处理器"""
|
|
42
43
|
error_mapping = {
|
|
43
44
|
"Field required": "请求失败,缺少必填项!",
|
|
44
|
-
"value is not a valid list": "类型错误,提交参数应该为列表!",
|
|
45
|
+
"value is not a valid list": "类型错误,提交参数应该为列表!",
|
|
45
46
|
"value is not a valid int": "类型错误,提交参数应该为整数!",
|
|
46
47
|
"value could not be parsed to a boolean": "类型错误,提交参数应该为布尔值!",
|
|
47
|
-
"Input should be a valid list": "类型错误,输入应该是一个有效的列表!"
|
|
48
|
+
"Input should be a valid list": "类型错误,输入应该是一个有效的列表!",
|
|
49
|
+
"String should have at least 6 characters": "密码长度不能小于6位!"
|
|
48
50
|
}
|
|
49
51
|
msg = error_mapping.get(exc.errors()[0].get('msg'), exc.errors()[0].get('msg'))
|
|
50
52
|
logger.error(f"请求地址: {request.url}, 错误信息: {msg}, 错误详情: {exc}")
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import json
|
|
2
2
|
|
|
3
|
+
from fastapi import Depends, Request
|
|
4
|
+
from fastapi.security import OAuth2PasswordBearer, SecurityScopes
|
|
5
|
+
|
|
3
6
|
from common_base.consts import (
|
|
4
7
|
REDIS_PREFIX_BLOCKLIST,
|
|
5
8
|
REDIS_PREFIX_USER_INFO,
|
|
@@ -9,8 +12,6 @@ from common_models.user_model import User
|
|
|
9
12
|
from common_utils.jwt_util import JwtUtil
|
|
10
13
|
from core.databases.aioredis import AioRedis
|
|
11
14
|
from core.start import base_config
|
|
12
|
-
from fastapi import Depends, Request
|
|
13
|
-
from fastapi.security import OAuth2PasswordBearer, SecurityScopes
|
|
14
15
|
|
|
15
16
|
oauth2_scheme = OAuth2PasswordBearer(tokenUrl=f"/api/{base_config.app_name}/auth/login", auto_error=False)
|
|
16
17
|
|
|
@@ -20,15 +21,15 @@ async def get_current_user(request: Request, token: str, security_scopes: Securi
|
|
|
20
21
|
"""
|
|
21
22
|
payload = JwtUtil.decode_token(token)
|
|
22
23
|
if not payload:
|
|
23
|
-
raise CustomException(msg="无效的令牌")
|
|
24
|
+
raise CustomException(msg="无效的令牌", status_code=401)
|
|
24
25
|
|
|
25
26
|
# 检查是否在黑名单中
|
|
26
27
|
if await AioRedis.get(f"{REDIS_PREFIX_BLOCKLIST}{token}"):
|
|
27
|
-
raise CustomException(msg="令牌已失效")
|
|
28
|
+
raise CustomException(msg="令牌已失效", status_code=401)
|
|
28
29
|
|
|
29
30
|
user_id = payload.get("sub")
|
|
30
31
|
if not user_id:
|
|
31
|
-
raise CustomException(msg="无效的令牌")
|
|
32
|
+
raise CustomException(msg="无效的令牌", status_code=401)
|
|
32
33
|
|
|
33
34
|
# 1. 尝试从缓存获取
|
|
34
35
|
user = None
|
|
@@ -65,7 +66,7 @@ async def get_current_user(request: Request, token: str, security_scopes: Securi
|
|
|
65
66
|
async def login_require(request: Request, security_scopes: SecurityScopes, token=Depends(oauth2_scheme)) -> User:
|
|
66
67
|
"""获取用户,获取不到报错"""
|
|
67
68
|
if not token:
|
|
68
|
-
raise CustomException('请先登录')
|
|
69
|
+
raise CustomException('请先登录', status_code=401)
|
|
69
70
|
|
|
70
71
|
return await get_current_user(request, token, security_scopes)
|
|
71
72
|
|
|
@@ -1,14 +1,27 @@
|
|
|
1
|
-
from fastapi import APIRouter, Body, Query, Request, Security
|
|
1
|
+
from fastapi import APIRouter, Body, Depends, Query, Request, Security
|
|
2
2
|
|
|
3
|
+
from common_base.exception import CustomException
|
|
3
4
|
from common_base.response import SuccessReturn
|
|
4
5
|
from common_depends.auth_depend import login_require
|
|
5
6
|
from common_models.user_model import User
|
|
6
7
|
from common_servers.schemas.auth_schema import TokenResponse, UserInfo
|
|
7
8
|
from common_servers.service.auth_svc import AuthService, UserLogin, UserRegister, WechatLogin
|
|
9
|
+
from core.base_config import base_config
|
|
8
10
|
|
|
9
11
|
router = APIRouter(prefix="/auth")
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
|
|
14
|
+
def password_login_require() -> None:
|
|
15
|
+
"""账号密码登录门禁。
|
|
16
|
+
|
|
17
|
+
以 APP_DEBUG 区分环境:生产(APP_DEBUG=False)关闭 /auth/register、/auth/login,
|
|
18
|
+
仅保留微信网页授权与小程序登录;本地开发/测试(APP_DEBUG=True)不受影响。
|
|
19
|
+
"""
|
|
20
|
+
if not base_config.app_debug:
|
|
21
|
+
raise CustomException(msg="账号密码登录已停用,请使用微信登录", status_code=403)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@router.post("/register", summary="用户注册", dependencies=[Depends(password_login_require)])
|
|
12
25
|
async def register(user_in: UserRegister):
|
|
13
26
|
user = await AuthService.register(user_in)
|
|
14
27
|
return SuccessReturn(
|
|
@@ -16,7 +29,7 @@ async def register(user_in: UserRegister):
|
|
|
16
29
|
)
|
|
17
30
|
|
|
18
31
|
|
|
19
|
-
@router.post("/login", summary="用户密码登录")
|
|
32
|
+
@router.post("/login", summary="用户密码登录", dependencies=[Depends(password_login_require)])
|
|
20
33
|
async def login(user_in: UserLogin, request: Request):
|
|
21
34
|
client_ip = request.client.host if request.client else "unknown"
|
|
22
35
|
token_data = await AuthService.login(user_in, client_ip)
|
|
@@ -106,11 +106,11 @@ class AuthService:
|
|
|
106
106
|
"""
|
|
107
107
|
user_id = await AioRedis.get(f"{REDIS_PREFIX_REFRESH_TOKEN}{refresh_token}")
|
|
108
108
|
if not user_id:
|
|
109
|
-
raise CustomException(msg="无效或已过期的刷新令牌")
|
|
109
|
+
raise CustomException(msg="无效或已过期的刷新令牌", status_code=401)
|
|
110
110
|
try:
|
|
111
111
|
user_id = int(user_id)
|
|
112
112
|
except (ValueError, TypeError):
|
|
113
|
-
raise CustomException(msg="无效的刷新令牌")
|
|
113
|
+
raise CustomException(msg="无效的刷新令牌", status_code=401) from None
|
|
114
114
|
|
|
115
115
|
user = await User.get_or_none(id=user_id)
|
|
116
116
|
if not user or not user.is_active:
|
|
@@ -209,8 +209,8 @@ class AuthService:
|
|
|
209
209
|
cached_data = json.loads(cache_value)
|
|
210
210
|
redirect_uri = cached_data.get("redirect_uri")
|
|
211
211
|
app_pk = cached_data.get("app_pk")
|
|
212
|
-
except (json.JSONDecodeError, TypeError):
|
|
213
|
-
raise CustomException(msg="授权数据格式错误")
|
|
212
|
+
except (json.JSONDecodeError, TypeError) as e:
|
|
213
|
+
raise CustomException(msg="授权数据格式错误") from e
|
|
214
214
|
|
|
215
215
|
if not redirect_uri or not app_pk:
|
|
216
216
|
raise CustomException(msg="授权数据不完整")
|
|
@@ -50,9 +50,9 @@ class WechatUtil:
|
|
|
50
50
|
return data
|
|
51
51
|
except Exception as e:
|
|
52
52
|
if isinstance(e, CustomException):
|
|
53
|
-
raise e
|
|
53
|
+
raise e from e
|
|
54
54
|
logger.error(f"Wechat API request error: {e}")
|
|
55
|
-
raise CustomException(msg="微信服务暂时不可用")
|
|
55
|
+
raise CustomException(msg="微信服务暂时不可用") from None
|
|
56
56
|
|
|
57
57
|
@classmethod
|
|
58
58
|
async def get_oauth_access_token(cls, appid: str, secret: str, code: str) -> dict:
|
|
@@ -116,4 +116,4 @@ class WechatUtil:
|
|
|
116
116
|
return data
|
|
117
117
|
except Exception as e:
|
|
118
118
|
logger.error(f"Decrypt wechat data failed: {e}")
|
|
119
|
-
raise CustomException(msg="微信数据解密失败")
|
|
119
|
+
raise CustomException(msg="微信数据解密失败") from None
|
|
@@ -28,7 +28,7 @@ class BaseConfig(BaseSettings):
|
|
|
28
28
|
jwt_secret_key: str = "bgb0tnl9d58+6n-6h-ea&u^1#s0ccp!794=krylacjq75vzps$"
|
|
29
29
|
|
|
30
30
|
# Access Token 有效期
|
|
31
|
-
access_token_expire_minutes: int =
|
|
31
|
+
access_token_expire_minutes: int = 1440
|
|
32
32
|
# Refresh Token 有效期
|
|
33
33
|
refresh_token_expire_days: int = 30
|
|
34
34
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|