From c9cb8c65421e9175d1aae0f956beac06a370d354 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Sat, 11 May 2024 09:05:07 +0800 Subject: [PATCH 1/5] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E9=80=9A=E7=9F=A5?= =?UTF-8?q?=E5=85=AC=E5=91=8A=E5=88=97=E8=A1=A8=E6=9F=A5=E8=AF=A2=E5=89=8D?= =?UTF-8?q?=E5=90=8E=E7=AB=AF=E5=AD=97=E6=AE=B5=E4=B8=8D=E4=B8=80=E8=87=B4?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-fastapi-backend/module_admin/dao/notice_dao.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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)), From 901a66bafa4ff5d2015dad3dfa513fd564c14d76 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Sat, 11 May 2024 14:58:02 +0800 Subject: [PATCH 2/5] =?UTF-8?q?feat:=20=E7=94=A8=E6=88=B7=E5=AF=86?= =?UTF-8?q?=E7=A0=81=E6=96=B0=E5=A2=9E=E9=9D=9E=E6=B3=95=E5=AD=97=E7=AC=A6?= =?UTF-8?q?=E9=AA=8C=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-fastapi-backend/exceptions/exception.py | 10 +++++++ ruoyi-fastapi-backend/exceptions/handle.py | 7 ++++- .../controller/user_controller.py | 6 ++-- .../module_admin/entity/vo/login_vo.py | 12 +++++++- .../module_admin/entity/vo/user_vo.py | 29 +++++++++++++++++++ ruoyi-fastapi-frontend/src/views/register.vue | 3 +- .../src/views/system/user/index.vue | 7 ++++- .../views/system/user/profile/resetPwd.vue | 2 +- 8 files changed, 68 insertions(+), 8 deletions(-) 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..a991556 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/user_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/user_controller.py @@ -217,12 +217,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/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/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" }] }); From 6ea8ada989cfb5fdd00bdf58e489525a79346ed8 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Sat, 11 May 2024 21:15:14 +0800 Subject: [PATCH 3/5] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E4=B8=AA=E4=BA=BA?= =?UTF-8?q?=E4=B8=AD=E5=BF=83=E4=BF=AE=E6=94=B9=E5=9F=BA=E6=9C=AC=E8=B5=84?= =?UTF-8?q?=E6=96=99=E5=90=8E=E7=AB=AF=E5=BC=82=E5=B8=B8=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/user_controller.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/ruoyi-fastapi-backend/module_admin/controller/user_controller.py b/ruoyi-fastapi-backend/module_admin/controller/user_controller.py index a991556..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) From 266b3e3b5ca7b53c16f0dc2a5993c720d8c88b9f Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Mon, 13 May 2024 09:15:01 +0800 Subject: [PATCH 4/5] =?UTF-8?q?chore:=20=E5=8D=87=E7=BA=A7=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E8=87=B31.1.3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-fastapi-backend/.env.dev | 2 +- ruoyi-fastapi-backend/.env.prod | 2 +- ruoyi-fastapi-frontend/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) 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-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", From cb96c878bf10047022ff31e26f955b3420674f88 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Mon, 13 May 2024 09:16:04 +0800 Subject: [PATCH 5/5] =?UTF-8?q?docs:=20=E6=9B=B4=E6=96=B0README=E6=96=87?= =?UTF-8?q?=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bd0db5b..680011f 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@

logo

-

RuoYi-Vue3-FastAPI v1.1.2

+

RuoYi-Vue3-FastAPI v1.1.3

基于RuoYi-Vue3+FastAPI前后端分离的快速开发框架

- + @@ -18,6 +18,7 @@ + ## 平台简介 RuoYi-Vue3-FastAPI是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。