diff --git a/README.md b/README.md index bd0db5b..680011f 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@
-
+
@@ -18,6 +18,7 @@
+
## 平台简介
RuoYi-Vue3-FastAPI是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。
diff --git a/ruoyi-fastapi-backend/.env.dev b/ruoyi-fastapi-backend/.env.dev
index 6249b39..e3916a8 100644
--- a/ruoyi-fastapi-backend/.env.dev
+++ b/ruoyi-fastapi-backend/.env.dev
@@ -10,7 +10,7 @@ APP_HOST = '0.0.0.0'
# 应用端口
APP_PORT = 9099
# 应用版本
-APP_VERSION= '1.1.2'
+APP_VERSION= '1.1.3'
# 应用是否开启热重载
APP_RELOAD = true
# 应用是否开启IP归属区域查询
diff --git a/ruoyi-fastapi-backend/.env.prod b/ruoyi-fastapi-backend/.env.prod
index aeda10f..193077d 100644
--- a/ruoyi-fastapi-backend/.env.prod
+++ b/ruoyi-fastapi-backend/.env.prod
@@ -10,7 +10,7 @@ APP_HOST = '0.0.0.0'
# 应用端口
APP_PORT = 9099
# 应用版本
-APP_VERSION= '1.1.2'
+APP_VERSION= '1.1.3'
# 应用是否开启热重载
APP_RELOAD = false
# 应用是否开启IP归属区域查询
diff --git a/ruoyi-fastapi-backend/exceptions/exception.py b/ruoyi-fastapi-backend/exceptions/exception.py
index ef2fda0..28c39a6 100644
--- a/ruoyi-fastapi-backend/exceptions/exception.py
+++ b/ruoyi-fastapi-backend/exceptions/exception.py
@@ -26,3 +26,13 @@ class PermissionException(Exception):
def __init__(self, data: str = None, message: str = None):
self.data = data
self.message = message
+
+
+class ModelValidatorException(Exception):
+ """
+ 自定义模型校验异常ModelValidatorException
+ """
+
+ def __init__(self, data: str = None, message: str = None):
+ self.data = data
+ self.message = message
diff --git a/ruoyi-fastapi-backend/exceptions/handle.py b/ruoyi-fastapi-backend/exceptions/handle.py
index 61b7f90..040a11f 100644
--- a/ruoyi-fastapi-backend/exceptions/handle.py
+++ b/ruoyi-fastapi-backend/exceptions/handle.py
@@ -1,6 +1,6 @@
from fastapi import FastAPI, Request
from fastapi.exceptions import HTTPException
-from exceptions.exception import AuthException, PermissionException
+from exceptions.exception import AuthException, PermissionException, ModelValidatorException
from utils.response_util import ResponseUtil, JSONResponse, jsonable_encoder
@@ -18,6 +18,11 @@ def handle_exception(app: FastAPI):
async def permission_exception_handler(request: Request, exc: PermissionException):
return ResponseUtil.forbidden(data=exc.data, msg=exc.message)
+ # 自定义模型检验异常
+ @app.exception_handler(ModelValidatorException)
+ async def model_validator_exception_handler(request: Request, exc: ModelValidatorException):
+ return ResponseUtil.failure(data=exc.data, msg=exc.message)
+
# 处理其他http请求异常
@app.exception_handler(HTTPException)
async def http_exception_handler(request: Request, exc: HTTPException):
diff --git a/ruoyi-fastapi-backend/module_admin/controller/user_controller.py b/ruoyi-fastapi-backend/module_admin/controller/user_controller.py
index 46ea0b8..9385a6d 100644
--- a/ruoyi-fastapi-backend/module_admin/controller/user_controller.py
+++ b/ruoyi-fastapi-backend/module_admin/controller/user_controller.py
@@ -198,11 +198,20 @@ async def change_system_user_profile_avatar(request: Request, avatarfile: bytes
@log_decorator(title='个人信息', business_type=2)
async def change_system_user_profile_info(request: Request, user_info: UserInfoModel, query_db: Session = Depends(get_db), current_user: CurrentUserModel = Depends(LoginService.get_current_user)):
try:
- edit_user = EditUserModel(**user_info.model_dump(by_alias=True, exclude={'role_ids', 'post_ids'}), roleIds=user_info.role_ids.split(','), postIds=user_info.post_ids.split(','))
- edit_user.user_id = current_user.user.user_id
- edit_user.update_by = current_user.user.user_name
- edit_user.update_time = datetime.now()
- print(edit_user.model_dump())
+ edit_user = EditUserModel(
+ **user_info.model_dump(
+ exclude_unset=True,
+ by_alias=True,
+ exclude={'role_ids', 'post_ids'}
+ ),
+ userId=current_user.user.user_id,
+ userName=current_user.user.user_name,
+ updateBy=current_user.user.user_name,
+ updateTime=datetime.now(),
+ roleIds=current_user.user.role_ids.split(',') if current_user.user.role_ids else [],
+ postIds=current_user.user.post_ids.split(',') if current_user.user.post_ids else [],
+ role=current_user.user.role
+ )
edit_user_result = UserService.edit_user_services(query_db, edit_user)
if edit_user_result.is_success:
logger.info(edit_user_result.message)
@@ -217,12 +226,12 @@ async def change_system_user_profile_info(request: Request, user_info: UserInfoM
@userController.put("/profile/updatePwd")
@log_decorator(title='个人信息', business_type=2)
-async def reset_system_user_password(request: Request, old_password: str = Query(alias='oldPassword'), new_password: str = Query(alias='newPassword'), query_db: Session = Depends(get_db), current_user: CurrentUserModel = Depends(LoginService.get_current_user)):
+async def reset_system_user_password(request: Request, reset_password: ResetPasswordModel = Depends(ResetPasswordModel.as_query), query_db: Session = Depends(get_db), current_user: CurrentUserModel = Depends(LoginService.get_current_user)):
try:
reset_user = ResetUserModel(
userId=current_user.user.user_id,
- oldPassword=old_password,
- password=PwdUtil.get_password_hash(new_password),
+ oldPassword=reset_password.old_password,
+ password=PwdUtil.get_password_hash(reset_password.new_password),
updateBy=current_user.user.user_name,
updateTime=datetime.now()
)
diff --git a/ruoyi-fastapi-backend/module_admin/dao/notice_dao.py b/ruoyi-fastapi-backend/module_admin/dao/notice_dao.py
index 2d3646f..79f32a3 100644
--- a/ruoyi-fastapi-backend/module_admin/dao/notice_dao.py
+++ b/ruoyi-fastapi-backend/module_admin/dao/notice_dao.py
@@ -51,7 +51,7 @@ class NoticeDao:
"""
query = db.query(SysNotice) \
.filter(SysNotice.notice_title.like(f'%{query_object.notice_title}%') if query_object.notice_title else True,
- SysNotice.update_by.like(f'%{query_object.update_by}%') if query_object.update_by else True,
+ SysNotice.create_by.like(f'%{query_object.create_by}%') if query_object.create_by else True,
SysNotice.notice_type == query_object.notice_type if query_object.notice_type else True,
SysNotice.create_time.between(
datetime.combine(datetime.strptime(query_object.begin_time, '%Y-%m-%d'), time(00, 00, 00)),
diff --git a/ruoyi-fastapi-backend/module_admin/entity/vo/login_vo.py b/ruoyi-fastapi-backend/module_admin/entity/vo/login_vo.py
index 09a595f..13ad73a 100644
--- a/ruoyi-fastapi-backend/module_admin/entity/vo/login_vo.py
+++ b/ruoyi-fastapi-backend/module_admin/entity/vo/login_vo.py
@@ -1,6 +1,8 @@
-from pydantic import BaseModel, ConfigDict
+import re
+from pydantic import BaseModel, ConfigDict, model_validator
from pydantic.alias_generators import to_camel
from typing import Optional
+from exceptions.exception import ModelValidatorException
class UserLogin(BaseModel):
@@ -23,6 +25,14 @@ class UserRegister(BaseModel):
code: Optional[str] = None
uuid: Optional[str] = None
+ @model_validator(mode='after')
+ def check_password(self) -> 'UserRegister':
+ pattern = r'''^[^<>"'|\\]+$'''
+ if self.password is None or re.match(pattern, self.password):
+ return self
+ else:
+ raise ModelValidatorException(message="密码不能包含非法字符:< > \" ' \\ |")
+
class Token(BaseModel):
access_token: str
diff --git a/ruoyi-fastapi-backend/module_admin/entity/vo/user_vo.py b/ruoyi-fastapi-backend/module_admin/entity/vo/user_vo.py
index fbc3983..fa761ef 100644
--- a/ruoyi-fastapi-backend/module_admin/entity/vo/user_vo.py
+++ b/ruoyi-fastapi-backend/module_admin/entity/vo/user_vo.py
@@ -1,3 +1,4 @@
+import re
from pydantic import BaseModel, ConfigDict, model_validator
from pydantic.alias_generators import to_camel
from typing import Union, Optional, List
@@ -6,6 +7,7 @@ from module_admin.entity.vo.role_vo import RoleModel
from module_admin.entity.vo.dept_vo import DeptModel
from module_admin.entity.vo.post_vo import PostModel
from module_admin.annotation.pydantic_annotation import as_query, as_form
+from exceptions.exception import ModelValidatorException
class TokenData(BaseModel):
@@ -42,6 +44,14 @@ class UserModel(BaseModel):
remark: Optional[str] = None
admin: Optional[bool] = False
+ @model_validator(mode='after')
+ def check_password(self) -> 'UserModel':
+ pattern = r'''^[^<>"'|\\]+$'''
+ if self.password is None or re.match(pattern, self.password):
+ return self
+ else:
+ raise ModelValidatorException(message="密码不能包含非法字符:< > \" ' \\ |")
+
@model_validator(mode='after')
def check_admin(self) -> 'UserModel':
if self.user_id == 1:
@@ -144,6 +154,25 @@ class EditUserModel(AddUserModel):
role: Optional[List] = []
+@as_query
+class ResetPasswordModel(BaseModel):
+ """
+ 重置密码模型
+ """
+ model_config = ConfigDict(alias_generator=to_camel)
+
+ old_password: Optional[str] = None
+ new_password: Optional[str] = None
+
+ @model_validator(mode='after')
+ def check_new_password(self) -> 'ResetPasswordModel':
+ pattern = r'''^[^<>"'|\\]+$'''
+ if self.new_password is None or re.match(pattern, self.new_password):
+ return self
+ else:
+ raise ModelValidatorException(message="密码不能包含非法字符:< > \" ' \\ |")
+
+
class ResetUserModel(UserModel):
"""
重置用户密码模型
diff --git a/ruoyi-fastapi-frontend/package.json b/ruoyi-fastapi-frontend/package.json
index 5518ea0..733e362 100644
--- a/ruoyi-fastapi-frontend/package.json
+++ b/ruoyi-fastapi-frontend/package.json
@@ -1,6 +1,6 @@
{
"name": "vfadmin",
- "version": "1.1.2",
+ "version": "1.1.3",
"description": "vfadmin管理系统",
"author": "insistence",
"license": "MIT",
diff --git a/ruoyi-fastapi-frontend/src/views/register.vue b/ruoyi-fastapi-frontend/src/views/register.vue
index 43e97e4..810dea8 100644
--- a/ruoyi-fastapi-frontend/src/views/register.vue
+++ b/ruoyi-fastapi-frontend/src/views/register.vue
@@ -105,7 +105,8 @@ const registerRules = {
],
password: [
{ required: true, trigger: "blur", message: "请输入您的密码" },
- { min: 5, max: 20, message: "用户密码长度必须介于 5 和 20 之间", trigger: "blur" }
+ { min: 5, max: 20, message: "用户密码长度必须介于 5 和 20 之间", trigger: "blur" },
+ { pattern: /^[^<>"'|\\]+$/, message: "不能包含非法字符:< > \" ' \\\ |", trigger: "blur" }
],
confirmPassword: [
{ required: true, trigger: "blur", message: "请再次输入您的密码" },
diff --git a/ruoyi-fastapi-frontend/src/views/system/user/index.vue b/ruoyi-fastapi-frontend/src/views/system/user/index.vue
index d6cfdd6..5cd9936 100644
--- a/ruoyi-fastapi-frontend/src/views/system/user/index.vue
+++ b/ruoyi-fastapi-frontend/src/views/system/user/index.vue
@@ -391,7 +391,7 @@ const data = reactive({
rules: {
userName: [{ required: true, message: "用户名称不能为空", trigger: "blur" }, { min: 2, max: 20, message: "用户名称长度必须介于 2 和 20 之间", trigger: "blur" }],
nickName: [{ required: true, message: "用户昵称不能为空", trigger: "blur" }],
- password: [{ required: true, message: "用户密码不能为空", trigger: "blur" }, { min: 5, max: 20, message: "用户密码长度必须介于 5 和 20 之间", trigger: "blur" }],
+ password: [{ required: true, message: "用户密码不能为空", trigger: "blur" }, { min: 5, max: 20, message: "用户密码长度必须介于 5 和 20 之间", trigger: "blur" }, { pattern: /^[^<>"'|\\]+$/, message: "不能包含非法字符:< > \" ' \\\ |", trigger: "blur" }],
email: [{ type: "email", message: "请输入正确的邮箱地址", trigger: ["blur", "change"] }],
phonenumber: [{ pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: "请输入正确的手机号码", trigger: "blur" }]
}
@@ -494,6 +494,11 @@ function handleResetPwd(row) {
closeOnClickModal: false,
inputPattern: /^.{5,20}$/,
inputErrorMessage: "用户密码长度必须介于 5 和 20 之间",
+ inputValidator: (value) => {
+ if (/<|>|"|'|\||\\/.test(value)) {
+ return "不能包含非法字符:< > \" ' \\\ |"
+ }
+ },
}).then(({ value }) => {
resetUserPwd(row.userId, value).then(response => {
proxy.$modal.msgSuccess("修改成功,新密码是:" + value);
diff --git a/ruoyi-fastapi-frontend/src/views/system/user/profile/resetPwd.vue b/ruoyi-fastapi-frontend/src/views/system/user/profile/resetPwd.vue
index dec2d79..96daef3 100644
--- a/ruoyi-fastapi-frontend/src/views/system/user/profile/resetPwd.vue
+++ b/ruoyi-fastapi-frontend/src/views/system/user/profile/resetPwd.vue
@@ -36,7 +36,7 @@ const equalToPassword = (rule, value, callback) => {
};
const rules = ref({
oldPassword: [{ required: true, message: "旧密码不能为空", trigger: "blur" }],
- newPassword: [{ required: true, message: "新密码不能为空", trigger: "blur" }, { min: 6, max: 20, message: "长度在 6 到 20 个字符", trigger: "blur" }],
+ newPassword: [{ required: true, message: "新密码不能为空", trigger: "blur" }, { min: 6, max: 20, message: "长度在 6 到 20 个字符", trigger: "blur" }, { pattern: /^[^<>"'|\\]+$/, message: "不能包含非法字符:< > \" ' \\\ |", trigger: "blur" }],
confirmPassword: [{ required: true, message: "确认密码不能为空", trigger: "blur" }, { required: true, validator: equalToPassword, trigger: "blur" }]
});