Skip to content

Commit fcc874b

Browse files
authored
add api module Interfaces (#79)
* Add api module related interfaces * Add filter to user paging query interface
1 parent 16b25c7 commit fcc874b

File tree

7 files changed

+151
-19
lines changed

7 files changed

+151
-19
lines changed

backend/app/api/v1/api.py

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,55 @@
11
#!/usr/bin/env python3
22
# -*- coding: utf-8 -*-
3-
from fastapi import APIRouter
3+
from typing import Annotated
4+
5+
from fastapi import APIRouter, Query
6+
7+
from backend.app.common.casbin_rbac import DependsRBAC
8+
from backend.app.common.jwt import DependsUser, CurrentUser
9+
from backend.app.common.pagination import PageDepends, paging_data
10+
from backend.app.common.response.response_schema import response_base
11+
from backend.app.database.db_mysql import CurrentSession
12+
from backend.app.schemas.api import GetAllApi, CreateApi, UpdateApi
13+
from backend.app.services.api_service import ApiService
414

515
router = APIRouter()
616

7-
# TODO: 添加 api 相关接口
17+
18+
@router.get('/{pk}', summary='获取接口详情', dependencies=[DependsUser])
19+
async def get_api(pk: int):
20+
api = await ApiService.get(pk=pk)
21+
return response_base.success(data=api)
22+
23+
24+
@router.get('', summary='(模糊条件)分页获取所有接口', dependencies=[DependsUser, PageDepends])
25+
async def get_all_apis(
26+
db: CurrentSession,
27+
name: Annotated[str | None, Query()] = None,
28+
method: Annotated[str | None, Query()] = None,
29+
path: Annotated[str | None, Query()] = None,
30+
):
31+
api_select = await ApiService.get_select(name=name, method=method, path=path)
32+
page_data = await paging_data(db, api_select, GetAllApi)
33+
return response_base.success(data=page_data)
34+
35+
36+
@router.post('', summary='创建接口', dependencies=[DependsRBAC])
37+
async def create_api(obj: CreateApi, user: CurrentUser):
38+
await ApiService.create(obj=obj, user_id=user.id)
39+
return response_base.success()
40+
41+
42+
@router.put('/{pk}', summary='更新接口', dependencies=[DependsRBAC])
43+
async def update_api(pk: int, obj: UpdateApi, user: CurrentUser):
44+
count = await ApiService.update(pk=pk, obj=obj, user_id=user.id)
45+
if count > 0:
46+
return response_base.success()
47+
return response_base.fail()
48+
49+
50+
@router.delete('', summary='(批量)删除接口', dependencies=[DependsRBAC])
51+
async def delete_api(pk: Annotated[list[int], Query(...)]):
52+
count = await ApiService.delete(pk=pk)
53+
if count > 0:
54+
return response_base.success()
55+
return response_base.fail()

backend/app/api/v1/user.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#!/usr/bin/env python3
22
# -*- coding: utf-8 -*-
3-
from fastapi import APIRouter
3+
from typing import Annotated
4+
5+
from fastapi import APIRouter, Query
46

57
from backend.app.common.jwt import DependsUser, CurrentUser, DependsSuperUser
68
from backend.app.common.pagination import paging_data, PageDepends
@@ -28,7 +30,7 @@ async def password_reset(obj: ResetPassword):
2830

2931

3032
@router.get('/{username}', summary='查看用户信息', dependencies=[DependsUser])
31-
async def userinfo(username: str):
33+
async def get_user(username: str):
3234
current_user = await UserService.get_userinfo(username)
3335
data = GetAllUserInfo(**select_to_json(current_user))
3436
return response_base.success(data=data)
@@ -50,9 +52,14 @@ async def update_avatar(username: str, avatar: Avatar, current_user: CurrentUser
5052
return response_base.fail()
5153

5254

53-
@router.get('', summary='获取所有用户', dependencies=[DependsUser, PageDepends])
54-
async def get_all_users(db: CurrentSession):
55-
user_select = await UserService.get_select()
55+
@router.get('', summary='(模糊条件)分页获取所有用户', dependencies=[DependsUser, PageDepends])
56+
async def get_all_users(
57+
db: CurrentSession,
58+
username: Annotated[str | None, Query()] = None,
59+
phone: Annotated[str | None, Query()] = None,
60+
status: Annotated[int | None, Query()] = None,
61+
):
62+
user_select = await UserService.get_select(username=username, phone=phone, status=status)
5663
page_data = await paging_data(db, user_select, GetAllUserInfo)
5764
return response_base.success(data=page_data)
5865

backend/app/crud/crud_api.py

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,45 @@
11
#!/usr/bin/env python3
22
# -*- coding: utf-8 -*-
3+
from typing import NoReturn
4+
5+
from sqlalchemy import Select, select, desc, delete, and_
6+
from sqlalchemy.ext.asyncio import AsyncSession
7+
38
from backend.app.crud.base import CRUDBase
49
from backend.app.models import Api
510
from backend.app.schemas.api import CreateApi, UpdateApi
611

712

813
class CRUDApi(CRUDBase[Api, CreateApi, UpdateApi]):
9-
# TODO: 添加 api 相关数据库操作
10-
pass
14+
async def get(self, db: AsyncSession, pk: int) -> Api | None:
15+
return await self.get_(db, pk)
16+
17+
async def get_all(self, name: str = None, method: str = None, path: str = None) -> Select:
18+
se = select(self.model).order_by(desc(self.model.created_time))
19+
where_list = []
20+
if name:
21+
where_list.append(self.model.name.like(f'%{name}%'))
22+
if method:
23+
where_list.append(self.model.method == method)
24+
if path:
25+
where_list.append(self.model.path.like(f'%{path}%', escape='/'))
26+
if where_list:
27+
se = se.where(and_(*where_list))
28+
return se
29+
30+
async def get_by_name(self, db: AsyncSession, name: str) -> Api | None:
31+
api = await db.execute(select(self.model).where(self.model.name == name))
32+
return api.scalars().first()
33+
34+
async def create(self, db: AsyncSession, obj_in: CreateApi, user_id: int) -> NoReturn:
35+
await self.create_(db, obj_in, user_id)
36+
37+
async def update(self, db: AsyncSession, pk: int, obj_in: UpdateApi, user_id: int) -> int:
38+
return await self.update_(db, pk, obj_in, user_id)
39+
40+
async def delete(self, db: AsyncSession, pk: list[int]) -> int:
41+
apis = await db.execute(delete(self.model).where(self.model.id.in_(pk)))
42+
return apis.rowcount
1143

1244

1345
ApiDao: CRUDApi = CRUDApi(Api)

backend/app/crud/crud_user.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from datetime import datetime
44
from typing import NoReturn
55

6-
from sqlalchemy import select, update, desc
6+
from sqlalchemy import select, update, desc, and_
77
from sqlalchemy.ext.asyncio import AsyncSession
88
from sqlalchemy.orm import selectinload
99
from sqlalchemy.sql import Select
@@ -66,12 +66,22 @@ async def reset_password(self, db: AsyncSession, pk: int, password: str) -> int:
6666
)
6767
return user.rowcount
6868

69-
def get_all(self) -> Select:
70-
return (
69+
async def get_all(self, username: str = None, phone: str = None, status: int = None) -> Select:
70+
se = (
7171
select(self.model)
7272
.options(selectinload(self.model.roles).selectinload(Role.menus))
7373
.order_by(desc(self.model.time_joined))
7474
)
75+
where_list = []
76+
if username:
77+
where_list.append(self.model.username.like(f'%{username}%'))
78+
if phone:
79+
where_list.append(self.model.phone.like(f'%{phone}%'))
80+
if status is not None:
81+
where_list.append(self.model.is_active == bool(status))
82+
if where_list:
83+
se = se.where(and_(*where_list))
84+
return se
7585

7686
async def get_super(self, db: AsyncSession, user_id: int) -> bool:
7787
user = await self.get(db, user_id)

backend/app/schemas/api.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#!/usr/bin/env python3
22
# -*- coding: utf-8 -*-
3-
from curses.ascii import isupper
43
from datetime import datetime
54

65
from pydantic import BaseModel, Field, validator
@@ -10,13 +9,13 @@
109

1110
class ApiBase(BaseModel):
1211
name: str
13-
method: str = Field(default=MethodType.GET, description='请求方法')
12+
method: str = Field(..., description='请求方法')
1413
path: str = Field(..., description='api路径')
1514
remark: str | None = None
1615

1716
@validator('method')
1817
def check_method(cls, v):
19-
if not isupper(v):
18+
if not v.isupper():
2019
raise ValueError('请求方式必须大写')
2120
allow_method = MethodType.get_member_values()
2221
if v not in allow_method:

backend/app/services/api_service.py

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,43 @@
11
#!/usr/bin/env python3
22
# -*- coding: utf-8 -*-
3+
from sqlalchemy import Select
4+
5+
from backend.app.common.exception import errors
6+
from backend.app.crud.crud_api import ApiDao
7+
from backend.app.database.db_mysql import async_db_session
8+
from backend.app.models import Api
9+
from backend.app.schemas.api import CreateApi, UpdateApi
310

411

512
class ApiService:
6-
# TODO: 添加 api 相关服务
7-
pass
13+
@staticmethod
14+
async def get(*, pk: int) -> Api:
15+
async with async_db_session.begin() as db:
16+
api = await ApiDao.get(db, pk)
17+
if not api:
18+
raise errors.NotFoundError(msg='接口不存在')
19+
return api
20+
21+
@staticmethod
22+
async def get_select(*, name: str = None, method: str = None, path: str = None) -> Select:
23+
return await ApiDao.get_all(name=name, method=method, path=path)
24+
25+
@staticmethod
26+
async def create(*, obj: CreateApi, user_id: int) -> None:
27+
async with async_db_session.begin() as db:
28+
api = await ApiDao.get_by_name(db, obj.name)
29+
if api:
30+
raise errors.ForbiddenError(msg='接口已存在')
31+
await ApiDao.create(db, obj, user_id)
32+
33+
@staticmethod
34+
async def update(*, pk: int, obj: UpdateApi, user_id: int) -> int:
35+
async with async_db_session.begin() as db:
36+
count = await ApiDao.update(db, pk, obj, user_id)
37+
return count
38+
39+
@staticmethod
40+
async def delete(*, pk: list[int]) -> int:
41+
async with async_db_session.begin() as db:
42+
count = await ApiDao.delete(db, pk)
43+
return count

backend/app/services/user_service.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,8 @@ async def update_avatar(*, username: str, current_user: User, avatar: Avatar) ->
187187
return count
188188

189189
@staticmethod
190-
async def get_select() -> Select:
191-
return UserDao.get_all()
190+
async def get_select(*, username: str = None, phone: str = None, status: bool = None) -> Select:
191+
return await UserDao.get_all(username=username, phone=phone, status=status)
192192

193193
@staticmethod
194194
async def update_permission(pk: int) -> int:

0 commit comments

Comments
 (0)