Update the status field type to int (#143)

This commit is contained in:
Wu Clan
2023-06-17 17:22:32 +08:00
committed by GitHub
parent 29b170f599
commit 439ab09ebd
38 changed files with 78 additions and 64 deletions

View File

@ -26,7 +26,7 @@ async def get_all_depts(
name: Annotated[str | None, Query()] = None,
leader: Annotated[str | None, Query()] = None,
phone: Annotated[str | None, Query()] = None,
status: Annotated[bool | None, Query()] = None,
status: Annotated[int | None, Query()] = None,
):
dept = await DeptService.get_dept_tree(name=name, leader=leader, phone=phone, status=status)
return await response_base.success(data=dept)

View File

@ -27,7 +27,7 @@ async def get_all_dict_datas(
db: CurrentSession,
label: Annotated[str | None, Query()] = None,
value: Annotated[str | None, Query()] = None,
status: Annotated[str | None, Query()] = None,
status: Annotated[int | None, Query()] = None,
):
dict_data_select = await DictDataService.get_select(label=label, value=value, status=status)
page_data = await paging_data(db, dict_data_select, GetAllDictData)

View File

@ -19,7 +19,7 @@ async def get_all_dict_types(
db: CurrentSession,
name: Annotated[str | None, Query()] = None,
code: Annotated[str | None, Query()] = None,
status: Annotated[str | None, Query()] = None,
status: Annotated[int | None, Query()] = None,
):
dict_type_select = await DictTypeService.get_select(name=name, code=code, status=status)
page_data = await paging_data(db, dict_type_select, GetAllDictType)

View File

@ -18,7 +18,7 @@ router = APIRouter()
async def get_all_login_logs(
db: CurrentSession,
username: Annotated[str | None, Query()] = None,
status: Annotated[bool | None, Query()] = None,
status: Annotated[int | None, Query()] = None,
ip: Annotated[str | None, Query()] = None,
):
log_select = await LoginLogService.get_select(username=username, status=status, ip=ip)

View File

@ -29,7 +29,7 @@ async def get_menu(pk: int):
@router.get('', summary='获取所有菜单展示树', dependencies=[DependsRBAC])
async def get_all_menus(
name: Annotated[str | None, Query()] = None,
status: Annotated[bool | None, Query()] = None,
status: Annotated[int | None, Query()] = None,
):
menu = await MenuService.get_menu_tree(name=name, status=status)
return await response_base.success(data=menu)

View File

@ -18,7 +18,7 @@ router = APIRouter()
async def get_all_opera_logs(
db: CurrentSession,
username: Annotated[str | None, Query()] = None,
status: Annotated[bool | None, Query()] = None,
status: Annotated[int | None, Query()] = None,
ip: Annotated[str | None, Query()] = None,
):
log_select = await OperaLogService.get_select(username=username, status=status, ip=ip)

View File

@ -57,7 +57,7 @@ async def get_all_users(
db: CurrentSession,
username: Annotated[str | None, Query()] = None,
phone: Annotated[str | None, Query()] = None,
status: Annotated[bool | None, Query()] = None,
status: Annotated[int | None, Query()] = None,
):
user_select = await UserService.get_select(username=username, phone=phone, status=status)
page_data = await paging_data(db, user_select, GetAllUserInfo)
@ -73,8 +73,8 @@ async def super_set(request: Request, pk: int):
@router.post('/{pk}/action', summary='修改用户状态', dependencies=[DependsRBAC])
async def active_set(request: Request, pk: int):
count = await UserService.update_active(request=request, pk=pk)
async def status_set(request: Request, pk: int):
count = await UserService.update_status(request=request, pk=pk)
if count > 0:
return await response_base.success()
return await response_base.fail()

View File

@ -70,3 +70,10 @@ class OperaLogCipherType(IntEnum):
aes = 0
md5 = 1
plan = 2
class StatusType(IntEnum):
"""状态类型"""
disable = 0
enable = 1

View File

@ -169,7 +169,7 @@ async def get_current_user(db: AsyncSession, data: dict) -> User:
user = await UserDao.get_with_relation(db, user_id=user_id)
if not user:
raise TokenError(msg='token 无效')
if not user.is_active:
if not user.status:
raise AuthorizationError(msg='用户已锁定')
if user.dept_id:
if not user.dept.status:

View File

@ -19,7 +19,7 @@ class CRUDDept(CRUDBase[Dept, CreateDept, UpdateDept]):
return await self.get_(db, name=name)
async def get_all(
self, db: AsyncSession, name: str = None, leader: str = None, phone: str = None, status: bool = None
self, db: AsyncSession, name: str = None, leader: str = None, phone: str = None, status: int = None
) -> Any:
se = select(self.model).order_by(asc(self.model.sort))
where_list = [self.model.del_flag == 0]

View File

@ -11,7 +11,7 @@ from backend.app.schemas.login_log import CreateLoginLog, UpdateLoginLog
class CRUDLoginLog(CRUDBase[LoginLog, CreateLoginLog, UpdateLoginLog]):
async def get_all(self, username: str | None = None, status: bool | None = None, ip: str | None = None) -> Select:
async def get_all(self, username: str | None = None, status: int | None = None, ip: str | None = None) -> Select:
se = select(self.model).order_by(desc(self.model.create_time))
where_list = []
if username:

View File

@ -14,7 +14,7 @@ class CRUDMenu(CRUDBase[Menu, CreateMenu, UpdateMenu]):
async def get_by_name(self, db, name: str) -> Menu | None:
return await self.get_(db, name=name)
async def get_all(self, db, name: str | None = None, status: bool | None = None) -> list[Menu]:
async def get_all(self, db, name: str | None = None, status: int | None = None) -> list[Menu]:
se = select(self.model).order_by(asc(self.model.sort))
where_list = []
if name:

View File

@ -11,7 +11,7 @@ from backend.app.schemas.opera_log import CreateOperaLog, UpdateOperaLog
class CRUDOperaLogDao(CRUDBase[OperaLog, CreateOperaLog, UpdateOperaLog]):
async def get_all(self, username: str | None = None, status: bool | None = None, ip: str | None = None) -> Select:
async def get_all(self, username: str | None = None, status: int | None = None, ip: str | None = None) -> Select:
se = select(self.model).order_by(desc(self.model.create_time))
where_list = []
if username:

View File

@ -80,7 +80,7 @@ class CRUDUser(CRUDBase[User, CreateUser, UpdateUser]):
if phone:
where_list.append(self.model.phone.like(f'%{phone}%'))
if status is not None:
where_list.append(self.model.is_active == bool(status))
where_list.append(self.model.status == status)
if where_list:
se = se.where(and_(*where_list))
return se
@ -89,9 +89,9 @@ class CRUDUser(CRUDBase[User, CreateUser, UpdateUser]):
user = await self.get(db, user_id)
return user.is_superuser
async def get_active(self, db: AsyncSession, user_id: int) -> bool:
async def get_status(self, db: AsyncSession, user_id: int) -> bool:
user = await self.get(db, user_id)
return user.is_active
return user.status
async def get_multi_login(self, db: AsyncSession, user_id: int) -> bool:
user = await self.get(db, user_id)
@ -104,10 +104,10 @@ class CRUDUser(CRUDBase[User, CreateUser, UpdateUser]):
)
return user.rowcount
async def set_active(self, db: AsyncSession, user_id: int) -> int:
active_status = await self.get_active(db, user_id)
async def set_status(self, db: AsyncSession, user_id: int) -> int:
status = await self.get_status(db, user_id)
user = await db.execute(
update(self.model).where(self.model.id == user_id).values(is_active=False if active_status else True)
update(self.model).where(self.model.id == user_id).values(status=False if status else True)
)
return user.rowcount

View File

@ -98,7 +98,7 @@ class InitTestData:
db.add(user_obj)
log.info(f'普通用户创建成功,账号:{username},密码:{password}')
async def fake_no_active_user(self):
async def fake_no_status_user(self):
"""自动创建锁定普通用户"""
username = self.fake.user_name()
password = self.fake.password()
@ -108,7 +108,7 @@ class InitTestData:
nickname=username,
password=await get_hash_password(password),
email=email,
is_active=False,
status=0,
is_superuser=False,
dept_id=1,
)
@ -135,7 +135,7 @@ class InitTestData:
db.add(user_obj)
log.info(f'管理员用户创建成功,账号:{username},密码:{password}')
async def fake_no_active_superuser(self):
async def fake_no_status_superuser(self):
"""自动创建锁定管理员用户"""
username = self.fake.user_name()
password = self.fake.password()
@ -145,7 +145,7 @@ class InitTestData:
nickname=username,
password=await get_hash_password(password),
email=email,
is_active=False,
status=0,
is_superuser=True,
dept_id=1,
)
@ -162,9 +162,9 @@ class InitTestData:
await self.create_test_user()
await self.create_superuser_by_yourself()
await self.fake_user()
await self.fake_no_active_user()
await self.fake_no_status_user()
await self.fake_superuser()
await self.fake_no_active_superuser()
await self.fake_no_status_superuser()
log.info('✅ 数据初始化完成')

View File

@ -119,7 +119,7 @@ class OperaLogMiddleware:
log.exception(e)
code = getattr(e, 'code', '500')
msg = getattr(e, 'msg', 'Internal Server Error')
status = False
status = 0
err = e
return code, msg, status, err
@ -130,7 +130,7 @@ class OperaLogMiddleware:
# 预置响应信息
code: str = '200'
msg: str = 'Success'
status: bool = True
status: int = 1
try:
http_exception = request.state.__request_http_exception__
except AttributeError:
@ -138,7 +138,7 @@ class OperaLogMiddleware:
else:
code = http_exception.get('code', '500')
msg = http_exception.get('msg', 'Internal Server Error')
status = False
status = 0
try:
validation_exception = request.state.__request_validation_exception__
except AttributeError:
@ -146,7 +146,7 @@ class OperaLogMiddleware:
else:
code = validation_exception.get('code', '400')
msg = validation_exception.get('msg', 'Bad Request')
status = False
status = 0
return code, msg, status
@staticmethod

View File

@ -20,7 +20,7 @@ class Dept(Base):
leader: Mapped[str | None] = mapped_column(String(20), default=None, comment='负责人')
phone: Mapped[str | None] = mapped_column(String(11), default=None, comment='手机')
email: Mapped[str | None] = mapped_column(String(50), default=None, comment='邮箱')
status: Mapped[bool] = mapped_column(default=True, comment='部门状态(0停用 1正常)')
status: Mapped[int] = mapped_column(default=1, comment='部门状态(0停用 1正常)')
del_flag: Mapped[bool] = mapped_column(default=False, comment='删除标志0删除 1存在')
parent_id: Mapped[int | None] = mapped_column(
ForeignKey('sys_dept.id', ondelete='SET NULL'), default=None, index=True, comment='父部门ID'

View File

@ -17,7 +17,7 @@ class DictData(Base):
value: Mapped[str] = mapped_column(String(32), unique=True, comment='字典值')
type_id: Mapped[int] = mapped_column(ForeignKey('sys_dict_type.id'), comment='字典类型id')
sort: Mapped[int] = mapped_column(default=0, comment='排序')
status: Mapped[bool] = mapped_column(default=True, comment='状态0停用 1正常')
status: Mapped[int] = mapped_column(default=1, comment='状态0停用 1正常')
remark: Mapped[str | None] = mapped_column(LONGTEXT, default=None, comment='备注')
# 字典类型一对多
type: Mapped['DictType'] = relationship(init=False, back_populates='datas') # noqa: F821

View File

@ -15,7 +15,7 @@ class DictType(Base):
id: Mapped[id_key] = mapped_column(init=False)
name: Mapped[str] = mapped_column(String(32), unique=True, comment='字典类型名称')
code: Mapped[str] = mapped_column(String(32), unique=True, comment='字典类型编码')
status: Mapped[bool] = mapped_column(default=True, comment='状态0停用 1正常')
status: Mapped[int] = mapped_column(default=1, comment='状态0停用 1正常')
remark: Mapped[str | None] = mapped_column(LONGTEXT, default=None, comment='备注')
# 字典类型一对多
datas: Mapped[list['DictData']] = relationship(init=False, back_populates='type') # noqa: F821

View File

@ -17,7 +17,7 @@ class LoginLog(DataClassBase):
id: Mapped[id_key] = mapped_column(init=False)
user_uuid: Mapped[str] = mapped_column(String(50), comment='用户UUID')
username: Mapped[str] = mapped_column(String(20), comment='用户名')
status: Mapped[bool] = mapped_column(insert_default=0, comment='登录状态(0失败 1成功)')
status: Mapped[int] = mapped_column(insert_default=0, comment='登录状态(0失败 1成功)')
ip: Mapped[str] = mapped_column(String(50), comment='登录IP地址')
country: Mapped[str | None] = mapped_column(String(50), comment='国家')
region: Mapped[str | None] = mapped_column(String(50), comment='地区')

View File

@ -24,7 +24,7 @@ class Menu(Base):
menu_type: Mapped[int] = mapped_column(default=0, comment='菜单类型0目录 1菜单 2按钮')
component: Mapped[str | None] = mapped_column(String(255), default=None, comment='组件路径')
perms: Mapped[str | None] = mapped_column(String(100), default=None, comment='权限标识')
status: Mapped[bool] = mapped_column(default=True, comment='菜单状态0停用 1正常')
status: Mapped[int] = mapped_column(default=1, comment='菜单状态0停用 1正常')
remark: Mapped[str | None] = mapped_column(LONGTEXT, default=None, comment='备注')
parent_id: Mapped[int | None] = mapped_column(
ForeignKey('sys_menu.id', ondelete='SET NULL'), default=None, index=True, comment='父菜单ID'

View File

@ -28,7 +28,7 @@ class OperaLog(DataClassBase):
browser: Mapped[str | None] = mapped_column(String(50), comment='浏览器')
device: Mapped[str | None] = mapped_column(String(50), comment='设备')
args: Mapped[str | None] = mapped_column(JSON(), comment='请求参数')
status: Mapped[bool] = mapped_column(comment='操作状态0异常 1正常')
status: Mapped[int] = mapped_column(comment='操作状态0异常 1正常')
code: Mapped[str] = mapped_column(String(20), insert_default='200', comment='操作状态码')
msg: Mapped[str | None] = mapped_column(LONGTEXT, comment='提示消息')
cost_time: Mapped[float] = mapped_column(insert_default=0.0, comment='请求耗时ms')

View File

@ -17,7 +17,7 @@ class Role(Base):
id: Mapped[id_key] = mapped_column(init=False)
name: Mapped[str] = mapped_column(String(20), unique=True, comment='角色名称')
data_scope: Mapped[int | None] = mapped_column(default=2, comment='数据范围1全部数据权限 2自定数据权限')
status: Mapped[bool] = mapped_column(default=True, comment='角色状态0停用 1正常')
status: Mapped[int] = mapped_column(default=1, comment='角色状态0停用 1正常')
remark: Mapped[str | None] = mapped_column(LONGTEXT, default=None, comment='备注')
# 角色用户多对多
users: Mapped[list['User']] = relationship( # noqa: F821

View File

@ -22,7 +22,7 @@ class User(DataClassBase):
password: Mapped[str] = mapped_column(String(255), comment='密码')
email: Mapped[str] = mapped_column(String(50), unique=True, index=True, comment='邮箱')
is_superuser: Mapped[bool] = mapped_column(default=False, comment='超级权限(0否 1是)')
is_active: Mapped[bool] = mapped_column(default=True, comment='用户账号状态(0停用 1正常)')
status: Mapped[int] = mapped_column(default=1, comment='用户账号状态(0停用 1正常)')
is_multi_login: Mapped[bool] = mapped_column(default=False, comment='是否重复登陆(0否 1是)')
avatar: Mapped[str | None] = mapped_column(String(255), default=None, comment='头像')
phone: Mapped[str | None] = mapped_column(String(11), default=None, comment='手机号')

View File

@ -4,6 +4,7 @@ from datetime import datetime
from pydantic import BaseModel, Field, validator
from backend.app.common.enums import StatusType
from backend.app.utils.re_verify import is_phone
@ -14,7 +15,7 @@ class DeptBase(BaseModel):
leader: str | None = None
phone: str | None = None
email: str | None = None
status: bool
status: StatusType = Field(default=StatusType.enable)
@validator('phone')
def phone_validator(cls, v):

View File

@ -2,8 +2,9 @@
# -*- coding: utf-8 -*-
from datetime import datetime
from pydantic import BaseModel
from pydantic import BaseModel, Field
from backend.app.common.enums import StatusType
from backend.app.schemas.dict_type import GetAllDictType
@ -11,7 +12,7 @@ class DictDataBase(BaseModel):
label: str
value: str
sort: int
status: bool
status: StatusType = Field(default=StatusType.enable)
remark: str | None = None
type_id: int

View File

@ -2,13 +2,15 @@
# -*- coding: utf-8 -*-
from datetime import datetime
from pydantic import BaseModel
from pydantic import BaseModel, Field
from backend.app.common.enums import StatusType
class DictTypeBase(BaseModel):
name: str
code: str
status: bool
status: StatusType = Field(default=StatusType.enable)
remark: str | None = None

View File

@ -8,7 +8,7 @@ from pydantic import BaseModel
class LoginLogBase(BaseModel):
user_uuid: str
username: str
status: bool
status: int
ip: str
country: str | None
region: str | None

View File

@ -4,7 +4,7 @@ from datetime import datetime
from pydantic import BaseModel, Field, validator
from backend.app.common.enums import MenuType
from backend.app.common.enums import MenuType, StatusType
class MenuBase(BaseModel):
@ -13,10 +13,10 @@ class MenuBase(BaseModel):
sort: int = Field(default=0, ge=0, description='排序')
icon: str | None = None
path: str | None = None
menu_type: int = Field(default=MenuType.directory, ge=0, description='菜单类型0目录 1菜单 2按钮')
menu_type: MenuType = Field(default=MenuType.directory, ge=0, description='菜单类型0目录 1菜单 2按钮')
component: str | None = None
perms: str | None = None
status: bool
status: StatusType = Field(default=StatusType.enable)
remark: str | None = None
@validator('menu_type')

View File

@ -2,7 +2,9 @@
# -*- coding: utf-8 -*-
from datetime import datetime
from pydantic import BaseModel
from pydantic import BaseModel, Field
from backend.app.common.enums import StatusType
class OperaLogBase(BaseModel):
@ -19,7 +21,7 @@ class OperaLogBase(BaseModel):
browser: str | None = None
device: str | None = None
args: dict | None = None
status: bool
status: StatusType = Field(default=StatusType.enable)
code: str
msg: str | None = None
cost_time: float

View File

@ -4,14 +4,14 @@ from datetime import datetime
from pydantic import BaseModel, Field, validator
from backend.app.common.enums import RoleDataScope
from backend.app.common.enums import RoleDataScope, StatusType
from backend.app.schemas.menu import GetAllMenu
class RoleBase(BaseModel):
name: str
data_scope: int | None = Field(default=RoleDataScope.custom, description='数据范围1全部数据权限 2自定数据权限') # noqa: E501
status: bool
data_scope: RoleDataScope = Field(default=RoleDataScope.custom, description='数据范围1全部数据权限 2自定数据权限') # noqa: E501
status: StatusType = Field(default=StatusType.enable)
remark: str | None = None
@validator('data_scope')

View File

@ -5,6 +5,7 @@ from datetime import datetime
from email_validator import validate_email, EmailNotValidError
from pydantic import BaseModel, HttpUrl, Field, validator
from backend.app.common.enums import StatusType
from backend.app.schemas.dept import GetAllDept
from backend.app.schemas.role import GetAllRole
@ -68,7 +69,7 @@ class GetUserInfoNoRelation(_UserInfoBase):
id: int
user_uuid: str
avatar: str | None = None
is_active: bool
status: StatusType = Field(default=StatusType.enable)
is_superuser: bool
is_multi_login: bool
time_joined: datetime = None

View File

@ -31,7 +31,7 @@ class AuthService:
raise errors.NotFoundError(msg='用户不存在')
elif not await jwt.password_verify(form_data.password, current_user.password):
raise errors.AuthorizationError(msg='密码错误')
elif not current_user.is_active:
elif not current_user.status:
raise errors.AuthorizationError(msg='用户已锁定, 登陆失败')
# 更新登陆时间
await UserDao.update_login_time(db, form_data.username, self.login_time)
@ -49,7 +49,7 @@ class AuthService:
raise errors.NotFoundError(msg='用户不存在')
elif not await jwt.password_verify(obj.password, current_user.password):
raise errors.AuthorizationError(msg='密码错误')
elif not current_user.is_active:
elif not current_user.status:
raise errors.AuthorizationError(msg='用户已锁定, 登陆失败')
captcha_code = await redis_client.get(f'{settings.CAPTCHA_LOGIN_REDIS_PREFIX}:{request.state.ip}')
if not captcha_code:
@ -98,7 +98,7 @@ class AuthService:
current_user = await UserDao.get(db, user_id)
if not current_user:
raise errors.NotFoundError(msg='用户不存在')
elif not current_user.is_active:
elif not current_user.status:
raise errors.AuthorizationError(msg='用户已锁定, 获取失败')
access_new_token, access_new_token_expire_time = await jwt.create_new_token(
str(current_user.id), refresh_token, multi_login=current_user.is_multi_login

View File

@ -20,7 +20,7 @@ class DeptService:
@staticmethod
async def get_dept_tree(
*, name: str | None = None, leader: str | None = None, phone: str | None = None, status: bool | None = None
*, name: str | None = None, leader: str | None = None, phone: str | None = None, status: int | None = None
):
async with async_db_session() as db:
dept_select = await DeptDao.get_all(db=db, name=name, leader=leader, phone=phone, status=status)

View File

@ -16,12 +16,12 @@ from backend.app.schemas.login_log import CreateLoginLog
class LoginLogService:
@staticmethod
async def get_select(*, username: str, status: bool, ip: str) -> Select:
async def get_select(*, username: str, status: int, ip: str) -> Select:
return await LoginLogDao.get_all(username=username, status=status, ip=ip)
@staticmethod
async def create(
*, db: AsyncSession, request: Request, user: User, login_time: datetime, status: bool, msg: str
*, db: AsyncSession, request: Request, user: User, login_time: datetime, status: int, msg: str
) -> NoReturn:
try:
# request.state 来自 opera log 中间件定义的扩展参数,详见 opera_log_middleware.py

View File

@ -18,7 +18,7 @@ class MenuService:
return menu
@staticmethod
async def get_menu_tree(*, name: str | None = None, status: bool | None = None):
async def get_menu_tree(*, name: str | None = None, status: int | None = None):
async with async_db_session() as db:
menu_select = await MenuDao.get_all(db, name=name, status=status)
menu_tree = await get_tree_data(menu_select)

View File

@ -7,7 +7,7 @@ from backend.app.schemas.opera_log import CreateOperaLog
class OperaLogService:
@staticmethod
async def get_select(*, username: str | None = None, status: bool | None = None, ip: str | None = None):
async def get_select(*, username: str | None = None, status: int | None = None, ip: str | None = None):
return await OperaLogDao.get_all(username=username, status=status, ip=ip)
@staticmethod

View File

@ -94,7 +94,7 @@ class UserService:
return count
@staticmethod
async def get_select(*, username: str = None, phone: str = None, status: bool = None) -> Select:
async def get_select(*, username: str = None, phone: str = None, status: int = None) -> Select:
return await UserDao.get_all(username=username, phone=phone, status=status)
@staticmethod
@ -110,7 +110,7 @@ class UserService:
return count
@staticmethod
async def update_active(*, request: Request, pk: int) -> int:
async def update_status(*, request: Request, pk: int) -> int:
async with async_db_session.begin() as db:
await jwt.superuser_verify(request)
if not await UserDao.get(db, pk):
@ -118,7 +118,7 @@ class UserService:
else:
if pk == request.user.id:
raise errors.ForbiddenError(msg='禁止修改自身状态')
count = await UserDao.set_active(db, pk)
count = await UserDao.set_status(db, pk)
return count
@staticmethod