Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions ruoyi-fastapi-backend/module_admin/entity/vo/config_vo.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,15 @@ def get_config_name(self) -> str | None:
def get_config_value(self) -> str | None:
return self.config_value

@Size(field_name='remark', min_length=0, max_length=500, message='备注长度不能超过500个字符')
def get_remark(self) -> str | None:
return self.remark

def validate_fields(self) -> None:
self.get_config_key()
self.get_config_name()
self.get_config_value()
self.get_remark()


class ConfigQueryModel(DateRangeQueryMixin, ConfigModel):
Expand Down
10 changes: 10 additions & 0 deletions ruoyi-fastapi-backend/module_admin/entity/vo/dict_vo.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,14 @@ def get_dict_name(self) -> str | None:
def get_dict_type(self) -> str | None:
return self.dict_type

@Size(field_name='remark', min_length=0, max_length=500, message='备注长度不能超过500个字符')
def get_remark(self) -> str | None:
return self.remark

def validate_fields(self) -> None:
self.get_dict_name()
self.get_dict_type()
self.get_remark()


class DictDataModel(BaseModel):
Expand Down Expand Up @@ -86,11 +91,16 @@ def get_dict_type(self) -> str | None:
def get_css_class(self) -> str | None:
return self.css_class

@Size(field_name='remark', min_length=0, max_length=500, message='备注长度不能超过500个字符')
def get_remark(self) -> str | None:
return self.remark

def validate_fields(self) -> None:
self.get_dict_label()
self.get_dict_value()
self.get_dict_type()
self.get_css_class()
self.get_remark()


class DictTypeQueryModel(DateRangeQueryMixin, DictTypeModel):
Expand Down
5 changes: 5 additions & 0 deletions ruoyi-fastapi-backend/module_admin/entity/vo/job_vo.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,14 @@ def get_invoke_target(self) -> str | None:
def get_cron_expression(self) -> str | None:
return self.cron_expression

@Size(field_name='remark', min_length=0, max_length=500, message='备注长度不能超过500个字符')
def get_remark(self) -> str | None:
return self.remark

def validate_fields(self) -> None:
self.get_invoke_target()
self.get_cron_expression()
self.get_remark()


class JobPreviewRequest(BaseModel):
Expand Down
5 changes: 5 additions & 0 deletions ruoyi-fastapi-backend/module_admin/entity/vo/menu_vo.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,18 @@ def get_menu_type(self) -> Literal['M', 'C', 'F'] | None:
def get_perms(self) -> str | None:
return self.perms

@Size(field_name='remark', min_length=0, max_length=500, message='备注长度不能超过500个字符')
def get_remark(self) -> str | None:
return self.remark

def validate_fields(self) -> None:
self.get_menu_name()
self.get_order_num()
self.get_path()
self.get_component()
self.get_menu_type()
self.get_perms()
self.get_remark()


class MenuQueryModel(DateRangeQueryMixin, MenuModel):
Expand Down
5 changes: 5 additions & 0 deletions ruoyi-fastapi-backend/module_admin/entity/vo/notice_vo.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,13 @@ class NoticeModel(BaseModel):
def get_notice_title(self) -> str | None:
return self.notice_title

@Size(field_name='remark', min_length=0, max_length=255, message='备注长度不能超过255个字符')
def get_remark(self) -> str | None:
return self.remark

def validate_fields(self) -> None:
self.get_notice_title()
self.get_remark()


class NoticeQueryModel(DateRangeQueryMixin, NoticeModel):
Expand Down
5 changes: 5 additions & 0 deletions ruoyi-fastapi-backend/module_admin/entity/vo/post_vo.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,15 @@ def get_post_name(self) -> str | None:
def get_post_sort(self) -> int | None:
return self.post_sort

@Size(field_name='remark', min_length=0, max_length=500, message='备注长度不能超过500个字符')
def get_remark(self) -> str | None:
return self.remark

def validate_fields(self) -> None:
self.get_post_code()
self.get_post_name()
self.get_post_sort()
self.get_remark()


class PostQueryModel(DateRangeQueryMixin, PostModel):
Expand Down
5 changes: 5 additions & 0 deletions ruoyi-fastapi-backend/module_admin/entity/vo/role_vo.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,15 @@ def get_role_key(self) -> str | None:
def get_role_sort(self) -> int | None:
return self.role_sort

@Size(field_name='remark', min_length=0, max_length=500, message='备注长度不能超过500个字符')
def get_remark(self) -> str | None:
return self.remark

def validate_fields(self) -> None:
self.get_role_name()
self.get_role_key()
self.get_role_sort()
self.get_remark()


class RoleMenuModel(BaseModel):
Expand Down
5 changes: 5 additions & 0 deletions ruoyi-fastapi-backend/module_admin/entity/vo/user_vo.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,16 @@ def get_email(self) -> str | None:
def get_phonenumber(self) -> str | None:
return self.phonenumber

@Size(field_name='remark', min_length=0, max_length=500, message='备注长度不能超过500个字符')
def get_remark(self) -> str | None:
return self.remark

def validate_fields(self) -> None:
self.get_user_name()
self.get_nick_name()
self.get_email()
self.get_phonenumber()
self.get_remark()


class UserRowModel(UserModel):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"""备注字段长度校验测试。

备注列在各表中的真实长度来自 sql/ruoyi-fastapi-pg.sql:
sys_notice.remark 为 varchar(255),其余业务表的 remark 为 varchar(500)。
超长备注在写库前必须被拦截,否则会在数据库层报错或(MySQL 非严格模式下)被静默截断。
"""

import pytest
from pydantic_validation_decorator import FieldValidationError

from module_admin.entity.vo.config_vo import ConfigModel
from module_admin.entity.vo.dict_vo import DictDataModel, DictTypeModel
from module_admin.entity.vo.job_vo import JobModel
from module_admin.entity.vo.menu_vo import MenuModel
from module_admin.entity.vo.notice_vo import NoticeModel
from module_admin.entity.vo.post_vo import PostModel
from module_admin.entity.vo.role_vo import RoleModel
from module_admin.entity.vo.user_vo import UserModel

# (模型, remark 列长度)
REMARK_LENGTH_CASES = [
(UserModel, 500),
(RoleModel, 500),
(PostModel, 500),
(MenuModel, 500),
(ConfigModel, 500),
(DictTypeModel, 500),
(DictDataModel, 500),
(JobModel, 500),
(NoticeModel, 255),
]


class TestRemarkLengthValidation:
"""备注字段长度校验。"""

@pytest.mark.parametrize(('model', 'max_length'), REMARK_LENGTH_CASES)
def test_remark_at_the_column_limit_is_accepted(self, model: type, max_length: int) -> None:
instance = model(remark='备' * max_length)

instance.get_remark()

assert len(instance.remark) == max_length

@pytest.mark.parametrize(('model', 'max_length'), REMARK_LENGTH_CASES)
def test_remark_one_past_the_column_limit_is_rejected(self, model: type, max_length: int) -> None:
instance = model(remark='备' * (max_length + 1))

with pytest.raises(FieldValidationError):
instance.get_remark()

@pytest.mark.parametrize(('model', 'max_length'), REMARK_LENGTH_CASES)
def test_remark_is_optional(self, model: type, max_length: int) -> None:
instance = model(remark=None)

instance.get_remark()

assert instance.remark is None

@pytest.mark.parametrize(('model', 'max_length'), REMARK_LENGTH_CASES)
def test_validate_fields_covers_remark(self, model: type, max_length: int) -> None:
"""validate_fields 是服务层实际调用的入口,它必须覆盖备注字段。"""
instance = model(remark='备' * (max_length + 1))

with pytest.raises(FieldValidationError):
instance.validate_fields()
Loading