0
This commit is contained in:
parent
3b662873c7
commit
4c15ded189
@ -1,6 +1,10 @@
|
|||||||
from fastapi import APIRouter
|
from fastapi import APIRouter
|
||||||
from api.api_v1.endpoints import login
|
from api.api_v1.endpoints import login
|
||||||
|
from api.api_v1.endpoints import project
|
||||||
|
from api.api_v1.endpoints import dashboard
|
||||||
|
|
||||||
api_router = APIRouter()
|
api_router = APIRouter()
|
||||||
|
|
||||||
api_router.include_router(login.router, tags=["登录接口"])
|
api_router.include_router(login.router, tags=["登录接口"], prefix='/user')
|
||||||
|
api_router.include_router(project.router, tags=["项目管理"], prefix='/project')
|
||||||
|
api_router.include_router(dashboard.router, tags=["看板管理"], prefix='/dashboard')
|
||||||
|
@ -1,31 +1,68 @@
|
|||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from typing import Any
|
from typing import Any, List
|
||||||
|
|
||||||
from fastapi import APIRouter, Body, Depends, HTTPException, Request
|
from fastapi import APIRouter, Body, Depends, HTTPException, Request
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
import crud, models, schemas
|
import crud, models, schemas
|
||||||
from api import deps
|
from api import deps
|
||||||
from core import security
|
|
||||||
from core.config import settings
|
|
||||||
from core.security import get_password_hash
|
|
||||||
from utils import (
|
|
||||||
verify_password_reset_token,
|
|
||||||
)
|
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
|
@router.get('/')
|
||||||
|
def read_dashboard(project_id: int = Depends(deps.check_project),
|
||||||
|
db: Session = Depends(deps.get_db),
|
||||||
|
current_user: models.User = Depends(deps.get_current_active_user)
|
||||||
|
):
|
||||||
|
dashboard = crud.authority.get_my_dashboard(db=db, project_id=project_id, user_id=current_user.id)
|
||||||
|
return dashboard
|
||||||
|
|
||||||
|
|
||||||
|
# 新建看板
|
||||||
|
@router.post("/create-dashboard")
|
||||||
|
def create_dashboard(dashboard_in: schemas.DashboardCreate,
|
||||||
|
project_id: int = Depends(deps.check_project),
|
||||||
|
db: Session = Depends(deps.get_db),
|
||||||
|
current_user: models.User = Depends(deps.get_current_active_user)) -> Any:
|
||||||
|
dashboard = crud.dashboard.create_with_dashboard(db=db, obj_in=dashboard_in, user_id=current_user.id)
|
||||||
|
|
||||||
|
# 自己创建的拥有权限
|
||||||
|
crud.authority.create_with_authority(db=db, obj_in=schemas.AuthorityCreate(
|
||||||
|
dashboard_id=dashboard.id,
|
||||||
|
project_id=project_id,
|
||||||
|
authority='rw',
|
||||||
|
space_id=dashboard.space_id,
|
||||||
|
folder_id=dashboard.folder_id
|
||||||
|
), user_id=current_user.id)
|
||||||
|
|
||||||
|
return {"msg": "新建成功", 'code': 0}
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/create-folder")
|
||||||
|
def create_folder(folder_in: schemas.FolderCreate, project_id: int = Depends(deps.check_project),
|
||||||
|
db: Session = Depends(deps.get_db),
|
||||||
|
current_user: models.User = Depends(deps.get_current_active_user)) -> Any:
|
||||||
|
folder = crud.folder.create_with_folder(db=db, obj_in=folder_in, user_id=current_user.id, project_id=project_id)
|
||||||
|
# 自己创建的拥有权限
|
||||||
|
crud.authority.create_with_authority(db=db, obj_in=schemas.AuthorityCreate(
|
||||||
|
project_id=project_id,
|
||||||
|
authority='rw',
|
||||||
|
space_id=folder.space_id,
|
||||||
|
folder_id=folder.id
|
||||||
|
), user_id=current_user.id)
|
||||||
|
return {"msg": "新建成功", 'code': 0}
|
||||||
|
|
||||||
|
|
||||||
@router.post("/create-space")
|
@router.post("/create-space")
|
||||||
def create_space() -> Any:
|
def create_space(space_in: schemas.SpaceCreate, project_id: int = Depends(deps.check_project),
|
||||||
pass
|
db: Session = Depends(deps.get_db),
|
||||||
|
current_user: models.User = Depends(deps.get_current_active_user)) -> Any:
|
||||||
|
space = crud.space.create_with_space(db=db, obj_in=space_in, user_id=current_user.id,project_id=project_id)
|
||||||
@router.post("/create-folder")
|
# 自己创建的拥有权限
|
||||||
def create_folder() -> Any:
|
crud.authority.create_with_authority(db=db, obj_in=schemas.AuthorityCreate(
|
||||||
pass
|
project_id=project_id,
|
||||||
|
authority='rw',
|
||||||
|
space_id=space.id,
|
||||||
@router.post("/create-folder")
|
), user_id=current_user.id)
|
||||||
def create_folder() -> Any:
|
return {"msg": "新建成功", 'code': 0}
|
||||||
pass
|
|
||||||
|
@ -40,7 +40,7 @@ def login(
|
|||||||
'name': user.name,
|
'name': user.name,
|
||||||
'email': user.email,
|
'email': user.email,
|
||||||
'token': security.create_access_token(
|
'token': security.create_access_token(
|
||||||
expires_delta=access_token_expires, user_id=user.id, email=user.email, is_active=user.is_active,
|
expires_delta=access_token_expires, id=user.id, email=user.email, is_active=user.is_active,
|
||||||
is_superuser=user.is_superuser, name=user.name
|
is_superuser=user.is_superuser, name=user.name
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@ -50,13 +50,12 @@ def login(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@router.post("/me", response_model=schemas.UserBase)
|
@router.get("/me", response_model=schemas.UserDBBase)
|
||||||
# @router.post("/me/")
|
def me(current_user: models.User = Depends(deps.get_current_active_user)) -> Any:
|
||||||
def me(request: Request) -> Any:
|
|
||||||
"""
|
"""
|
||||||
Test access token
|
Test access token
|
||||||
"""
|
"""
|
||||||
return request.state.user
|
return current_user
|
||||||
|
|
||||||
|
|
||||||
@router.post("/reset-password", response_model=schemas.Msg)
|
@router.post("/reset-password", response_model=schemas.Msg)
|
||||||
|
@ -1,22 +0,0 @@
|
|||||||
from datetime import timedelta
|
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
from fastapi import APIRouter, Body, Depends, HTTPException, Request
|
|
||||||
from sqlalchemy.orm import Session
|
|
||||||
|
|
||||||
import crud, models, schemas
|
|
||||||
from api import deps
|
|
||||||
from core import security
|
|
||||||
from core.config import settings
|
|
||||||
from core.security import get_password_hash
|
|
||||||
from utils import (
|
|
||||||
verify_password_reset_token,
|
|
||||||
)
|
|
||||||
|
|
||||||
router = APIRouter()
|
|
||||||
|
|
||||||
|
|
||||||
@router.post("/create-project")
|
|
||||||
def create_project() -> Any:
|
|
||||||
pass
|
|
||||||
|
|
35
api/api_v1/endpoints/project.py
Normal file
35
api/api_v1/endpoints/project.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
from datetime import timedelta
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from fastapi import APIRouter, Body, Depends, HTTPException, Request
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
import crud, models, schemas
|
||||||
|
from api import deps
|
||||||
|
|
||||||
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/create-project", response_model=schemas.Project)
|
||||||
|
def create_project(project_in: schemas.ProjectCreate, db: Session = Depends(deps.get_db),
|
||||||
|
current_user: models.User = Depends(deps.get_current_active_user)
|
||||||
|
) -> Any:
|
||||||
|
project = crud.project.create_with_project(db=db, obj_in=project_in, user_id=current_user.id)
|
||||||
|
# 我的看板 新建 未分组 和 共享给我的 文件夹
|
||||||
|
kanban = crud.kanban.create(db=db, obj_in=schemas.KanBanCreate(project_id=project.id, user_id=current_user.id))
|
||||||
|
unknown_folder = schemas.FolderCreate(
|
||||||
|
project_id=project.id,
|
||||||
|
user_id=current_user.id,
|
||||||
|
kanban_id=kanban.id,
|
||||||
|
name='未分组的'
|
||||||
|
)
|
||||||
|
share_folder = schemas.FolderCreate(
|
||||||
|
project_id=project.id,
|
||||||
|
|
||||||
|
kanban_id=kanban.id,
|
||||||
|
name='共享给我的'
|
||||||
|
)
|
||||||
|
crud.folder.create_with_folder(db=db, obj_in=unknown_folder, user_id=current_user.id, )
|
||||||
|
crud.folder.create_with_folder(db=db, obj_in=share_folder, user_id=current_user.id)
|
||||||
|
|
||||||
|
return project
|
14
api/deps.py
14
api/deps.py
@ -25,13 +25,15 @@ def get_db() -> Generator:
|
|||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
|
|
||||||
def get_current_user(token:str
|
# def get_current_user(token: str = Depends(reusable_oauth2)
|
||||||
) -> schemas.UserBase:
|
# ) -> schemas.UserDBBase:
|
||||||
|
def get_current_user(token: str
|
||||||
|
) -> schemas.UserDBBase:
|
||||||
try:
|
try:
|
||||||
payload = jwt.decode(
|
payload = jwt.decode(
|
||||||
token, settings.SECRET_KEY, algorithms=[security.ALGORITHM]
|
token, settings.SECRET_KEY, algorithms=[security.ALGORITHM]
|
||||||
)
|
)
|
||||||
user = schemas.UserBase(**payload)
|
user = schemas.UserDBBase(**payload)
|
||||||
except (jwt.JWTError, ValidationError):
|
except (jwt.JWTError, ValidationError):
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_403_FORBIDDEN,
|
status_code=status.HTTP_403_FORBIDDEN,
|
||||||
@ -58,3 +60,9 @@ def get_current_active_superuser(
|
|||||||
status_code=400, detail="The user doesn't have enough privileges"
|
status_code=400, detail="The user doesn't have enough privileges"
|
||||||
)
|
)
|
||||||
return current_user
|
return current_user
|
||||||
|
|
||||||
|
|
||||||
|
def check_project(project_id: int, db: Session = Depends(get_db)):
|
||||||
|
if not crud.project.get(db, id=project_id):
|
||||||
|
raise HTTPException(status_code=404, detail="没有这个项目")
|
||||||
|
return project_id
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
from .crud_user import user
|
from .crud_user import user
|
||||||
|
from .curd_project import project
|
||||||
|
from .curd_kanban import kanban
|
||||||
|
from .curd_folder import folder
|
||||||
|
from .curd_dashboard import dashboard
|
||||||
|
from .curd_space import space
|
||||||
|
from .curd_authority import authority
|
||||||
|
70
crud/curd_authority.py
Normal file
70
crud/curd_authority.py
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
from typing import Any, Dict, Optional, Union
|
||||||
|
|
||||||
|
from fastapi.encoders import jsonable_encoder
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
from crud.base import CRUDBase
|
||||||
|
from models.authority import Authority
|
||||||
|
from schemas import AuthorityCreate, AuthorityUpdate
|
||||||
|
|
||||||
|
|
||||||
|
class CRUDAuthority(CRUDBase[Authority, AuthorityCreate, AuthorityUpdate]):
|
||||||
|
def create_with_authority(
|
||||||
|
self, db: Session, *, obj_in: AuthorityCreate, user_id: int
|
||||||
|
) -> Authority:
|
||||||
|
obj_in_data = jsonable_encoder(obj_in)
|
||||||
|
db_obj = self.model(**obj_in_data, user_id=user_id)
|
||||||
|
db.add(db_obj)
|
||||||
|
db.commit()
|
||||||
|
db.refresh(db_obj)
|
||||||
|
return db_obj
|
||||||
|
|
||||||
|
def get_my_dashboard(self, db: Session, project_id: int, user_id: int):
|
||||||
|
dashboards = db.query(Authority).filter(Authority.project_id == project_id, Authority.user_id == user_id).all()
|
||||||
|
res = {'kanban': dict(), 'space': dict()}
|
||||||
|
for item in dashboards:
|
||||||
|
# 是空间的
|
||||||
|
dashboard = item.dashboard
|
||||||
|
folder = item.folder
|
||||||
|
space = item.space
|
||||||
|
if space:
|
||||||
|
s = res['space'].setdefault(space.id, {'dashboard': [], 'folder': {}})
|
||||||
|
s['name'] = space.name
|
||||||
|
s['id'] = space.id
|
||||||
|
if folder:
|
||||||
|
f = s['folder'].setdefault(folder.id, {'dashboard': []})
|
||||||
|
f['name'] = folder.name
|
||||||
|
f['id'] = folder.id
|
||||||
|
if dashboard:
|
||||||
|
f['dashboard'].append({
|
||||||
|
'name': dashboard.name,
|
||||||
|
'id': dashboard.id
|
||||||
|
})
|
||||||
|
elif dashboard:
|
||||||
|
d = s['dashboard']
|
||||||
|
d.append({
|
||||||
|
'name': dashboard.name,
|
||||||
|
'id': dashboard.id
|
||||||
|
})
|
||||||
|
|
||||||
|
else:
|
||||||
|
# 是看板的文件夹
|
||||||
|
folder = item.folder
|
||||||
|
f = res['kanban'].setdefault(folder.id, {'dashboard': []})
|
||||||
|
f['name'] = folder.name
|
||||||
|
f['id'] = folder.id
|
||||||
|
if dashboard:
|
||||||
|
f['dashboard'].append({
|
||||||
|
'name': dashboard.name,
|
||||||
|
'id': dashboard.id
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
# return {
|
||||||
|
# 'kanban': list(res['kanban'].values()),
|
||||||
|
# 'space': list(res['space'].values())
|
||||||
|
# }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
authority = CRUDAuthority(Authority)
|
28
crud/curd_dashboard.py
Normal file
28
crud/curd_dashboard.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
from typing import Any, Dict, Optional, Union
|
||||||
|
|
||||||
|
from fastapi import HTTPException
|
||||||
|
from fastapi.encoders import jsonable_encoder
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
from crud.base import CRUDBase
|
||||||
|
from models.dashboard import Dashboard
|
||||||
|
from models.folders import Folder
|
||||||
|
from models.space import Space
|
||||||
|
from schemas import DashboardCreate, DashboardUpdate
|
||||||
|
|
||||||
|
|
||||||
|
class CRUDDashboard(CRUDBase[Dashboard, DashboardCreate, DashboardUpdate]):
|
||||||
|
def create_with_dashboard(
|
||||||
|
self, db: Session, *, obj_in: DashboardCreate, user_id: int
|
||||||
|
) -> Dashboard:
|
||||||
|
obj_in_data = jsonable_encoder(obj_in)
|
||||||
|
db_obj = self.model(**obj_in_data, user_id=user_id)
|
||||||
|
db.add(db_obj)
|
||||||
|
db.commit()
|
||||||
|
db.refresh(db_obj)
|
||||||
|
return db_obj
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
dashboard = CRUDDashboard(Dashboard)
|
31
crud/curd_folder.py
Normal file
31
crud/curd_folder.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
from typing import Any, Dict, Optional, Union
|
||||||
|
|
||||||
|
from fastapi import HTTPException
|
||||||
|
from fastapi.encoders import jsonable_encoder
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
from crud.base import CRUDBase
|
||||||
|
from models.folders import Folder
|
||||||
|
from models.kanban import KanBan
|
||||||
|
from models.space import Space
|
||||||
|
from schemas import FolderUpdate, FolderCreate
|
||||||
|
|
||||||
|
|
||||||
|
class CRUDFolder(CRUDBase[Folder, FolderCreate, FolderUpdate]):
|
||||||
|
def create_with_folder(
|
||||||
|
self, db: Session, *, obj_in: FolderCreate, user_id: int, project_id: int
|
||||||
|
) -> Folder:
|
||||||
|
|
||||||
|
if (not (obj_in.space_id and db.query(Space).get(obj_in.space_id))) ^ \
|
||||||
|
(not (obj_in.kanban_id and db.query(KanBan).get(obj_in.kanban_id))):
|
||||||
|
obj_in_data = jsonable_encoder(obj_in)
|
||||||
|
db_obj = self.model(**obj_in_data, user_id=user_id, project_id=project_id)
|
||||||
|
db.add(db_obj)
|
||||||
|
db.commit()
|
||||||
|
db.refresh(db_obj)
|
||||||
|
return db_obj
|
||||||
|
else:
|
||||||
|
raise HTTPException(status_code=404, detail="找不到上级")
|
||||||
|
|
||||||
|
|
||||||
|
folder = CRUDFolder(Folder)
|
15
crud/curd_kanban.py
Normal file
15
crud/curd_kanban.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
from typing import Any, Dict, Optional, Union
|
||||||
|
|
||||||
|
from fastapi.encoders import jsonable_encoder
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
from crud.base import CRUDBase
|
||||||
|
from models.kanban import KanBan
|
||||||
|
from schemas import KanBanUpdate,KanBanCreate
|
||||||
|
|
||||||
|
|
||||||
|
class CRUDKanBan(CRUDBase[KanBan, KanBanCreate, KanBanUpdate]):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
kanban = CRUDKanBan(KanBan)
|
27
crud/curd_project.py
Normal file
27
crud/curd_project.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
from typing import Any, Dict, Optional, Union
|
||||||
|
|
||||||
|
from fastapi.encoders import jsonable_encoder
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
from crud.base import CRUDBase
|
||||||
|
|
||||||
|
from models.project import Project
|
||||||
|
|
||||||
|
from schemas.project import ProjectCreate, ProjectUpdate
|
||||||
|
|
||||||
|
|
||||||
|
class CRUDProject(CRUDBase[Project, ProjectCreate, ProjectUpdate]):
|
||||||
|
def create_with_project(
|
||||||
|
self, db: Session, *, obj_in: ProjectCreate, user_id: int
|
||||||
|
) -> Project:
|
||||||
|
obj_in_data = jsonable_encoder(obj_in)
|
||||||
|
db_obj = self.model(**obj_in_data, user_id=user_id)
|
||||||
|
db.add(db_obj)
|
||||||
|
db.commit()
|
||||||
|
db.refresh(db_obj)
|
||||||
|
return db_obj
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
project = CRUDProject(Project)
|
23
crud/curd_space.py
Normal file
23
crud/curd_space.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
from typing import Any, Dict, Optional, Union
|
||||||
|
|
||||||
|
from fastapi.encoders import jsonable_encoder
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
from crud.base import CRUDBase
|
||||||
|
from models.space import Space
|
||||||
|
from schemas import SpaceCreate, SpaceUpdate
|
||||||
|
|
||||||
|
|
||||||
|
class CRUDSpace(CRUDBase[Space, SpaceCreate, SpaceUpdate]):
|
||||||
|
def create_with_space(
|
||||||
|
self, db: Session, *, obj_in: SpaceCreate, user_id: int, project_id: int
|
||||||
|
) -> Space:
|
||||||
|
obj_in_data = jsonable_encoder(obj_in)
|
||||||
|
db_obj = self.model(**obj_in_data, user_id=user_id, project_id=project_id)
|
||||||
|
db.add(db_obj)
|
||||||
|
db.commit()
|
||||||
|
db.refresh(db_obj)
|
||||||
|
return db_obj
|
||||||
|
|
||||||
|
|
||||||
|
space = CRUDSpace(Space)
|
@ -0,0 +1 @@
|
|||||||
|
from .base_class import Base # noqa
|
17
main.py
17
main.py
@ -13,23 +13,6 @@ app = FastAPI(title=settings.PROJECT_NAME, openapi_url=f"{settings.API_V1_STR}/o
|
|||||||
allow_anonymous = [f'{settings.API_V1_STR}/{page}' for page in settings.ALLOW_ANONYMOUS]
|
allow_anonymous = [f'{settings.API_V1_STR}/{page}' for page in settings.ALLOW_ANONYMOUS]
|
||||||
allow_anonymous.extend(['/docs'])
|
allow_anonymous.extend(['/docs'])
|
||||||
|
|
||||||
|
|
||||||
@app.middleware("http")
|
|
||||||
async def add_jwt_auth(request: Request, call_next):
|
|
||||||
fail = {'code': -1, 'msg': '身份验证失败'}
|
|
||||||
if request.scope.get('path') not in allow_anonymous:
|
|
||||||
token = request.headers.get("Authorization")
|
|
||||||
try:
|
|
||||||
user = get_current_user(token)
|
|
||||||
except:
|
|
||||||
return JSONResponse(fail)
|
|
||||||
#
|
|
||||||
# request.state.user = user
|
|
||||||
|
|
||||||
response = await call_next(request)
|
|
||||||
return response
|
|
||||||
|
|
||||||
|
|
||||||
if settings.BACKEND_CORS_ORIGINS:
|
if settings.BACKEND_CORS_ORIGINS:
|
||||||
app.add_middleware(
|
app.add_middleware(
|
||||||
CORSMiddleware,
|
CORSMiddleware,
|
||||||
|
20
models/authority.py
Normal file
20
models/authority.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import datetime
|
||||||
|
|
||||||
|
from sqlalchemy import Boolean, Column, Integer, String, ForeignKey, DateTime, Enum
|
||||||
|
from sqlalchemy.orm import relationship, backref
|
||||||
|
|
||||||
|
from db.base_class import Base
|
||||||
|
|
||||||
|
|
||||||
|
class Authority(Base):
|
||||||
|
id = Column(Integer, primary_key=True, index=True)
|
||||||
|
user_id = Column(Integer, ForeignKey('user.id'))
|
||||||
|
project_id = Column(Integer, ForeignKey('project.id'))
|
||||||
|
dashboard_id = Column(Integer, ForeignKey('dashboard.id'))
|
||||||
|
folder_id = Column(Integer, ForeignKey('folder.id'))
|
||||||
|
space_id = Column(Integer, ForeignKey('space.id'))
|
||||||
|
authority = Column(Enum('rw', 'r'))
|
||||||
|
create_date = Column(DateTime, default=datetime.datetime.now())
|
||||||
|
dashboard = relationship('Dashboard', backref="authority")
|
||||||
|
folder = relationship('Folder', backref="authority")
|
||||||
|
space = relationship('Space', backref="authority")
|
@ -1,15 +1,21 @@
|
|||||||
from sqlalchemy import Boolean, Column, Integer, String, ForeignKey
|
import datetime
|
||||||
from sqlalchemy.orm import relationship
|
|
||||||
|
from sqlalchemy import Boolean, Column, Integer, String, ForeignKey, DateTime
|
||||||
|
from sqlalchemy.orm import relationship, backref
|
||||||
|
|
||||||
from db.base_class import Base
|
from db.base_class import Base
|
||||||
|
|
||||||
|
|
||||||
class Dashboard(Base):
|
class Dashboard(Base):
|
||||||
id = Column(Integer, primary_key=True, index=True)
|
id = Column(Integer, primary_key=True, index=True)
|
||||||
folder_type = Column(String)
|
name = Column(String)
|
||||||
pid = Column(Integer, ForeignKey('dashboard.id'))
|
|
||||||
parent = relationship('Dashboard', remote_side=[id])
|
|
||||||
children = relationship('Dashboard', remote_side=[pid])
|
|
||||||
name = Column(String, nullable=False)
|
|
||||||
user_id = Column(Integer, ForeignKey('user.id'))
|
user_id = Column(Integer, ForeignKey('user.id'))
|
||||||
project_id = Column(Integer, ForeignKey('project.id'))
|
folder_id = Column(Integer, ForeignKey('folder.id'))
|
||||||
|
space_id = Column(Integer, ForeignKey('space.id'))
|
||||||
|
create_date = Column(DateTime, default=datetime.datetime.now())
|
||||||
|
|
||||||
|
folder = relationship('Folder', backref="dashboard")
|
||||||
|
space = relationship('Space', backref="dashboard")
|
||||||
|
|
||||||
|
# authority = relationship('Authority', backref=backref("dashboard", lazy="joined"))
|
||||||
|
|
||||||
|
21
models/folders.py
Normal file
21
models/folders.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import datetime
|
||||||
|
|
||||||
|
from sqlalchemy import Boolean, Column, Integer, String, ForeignKey, DateTime
|
||||||
|
from sqlalchemy.orm import relationship, backref
|
||||||
|
|
||||||
|
from db.base_class import Base
|
||||||
|
|
||||||
|
|
||||||
|
class Folder(Base):
|
||||||
|
id = Column(Integer, primary_key=True, index=True)
|
||||||
|
name = Column(String)
|
||||||
|
user_id = Column(Integer, ForeignKey('user.id'))
|
||||||
|
kanban_id = Column(Integer, ForeignKey('kanban.id'))
|
||||||
|
project_id = Column(Integer, ForeignKey('project.id'))
|
||||||
|
space_id = Column(Integer, ForeignKey('space.id'))
|
||||||
|
create_date = Column(DateTime, default=datetime.datetime.now())
|
||||||
|
|
||||||
|
kanban = relationship('KanBan', backref='folder')
|
||||||
|
space = relationship('Space', backref='folder')
|
||||||
|
|
||||||
|
# dashboard = relationship('Dashboard', backref=backref("folder", lazy="joined"))
|
18
models/kanban.py
Normal file
18
models/kanban.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import datetime
|
||||||
|
|
||||||
|
from sqlalchemy import Boolean, Column, Integer, String, ForeignKey, DateTime
|
||||||
|
from sqlalchemy.orm import relationship, backref
|
||||||
|
|
||||||
|
from db.base_class import Base
|
||||||
|
|
||||||
|
|
||||||
|
class KanBan(Base):
|
||||||
|
id = Column(Integer, primary_key=True, index=True)
|
||||||
|
project_id = Column(Integer, ForeignKey('project.id'))
|
||||||
|
user_id = Column(Integer, ForeignKey('user.id'))
|
||||||
|
create_date = Column(DateTime, default=datetime.datetime.now())
|
||||||
|
|
||||||
|
project = relationship('Project', backref='kanban')
|
||||||
|
|
||||||
|
# folder = relationship('Folder', backref=backref("kanban", lazy="joined"))
|
||||||
|
|
@ -1,8 +1,15 @@
|
|||||||
from sqlalchemy import Boolean, Column, Integer, String, ForeignKey
|
import datetime
|
||||||
|
|
||||||
|
from sqlalchemy import Boolean, Column, Integer, String, ForeignKey, DateTime
|
||||||
from sqlalchemy.orm import relationship
|
from sqlalchemy.orm import relationship
|
||||||
|
|
||||||
from db.base_class import Base
|
from db.base_class import Base
|
||||||
|
|
||||||
|
|
||||||
class Dashboard(Base):
|
class Project(Base):
|
||||||
id = Column(Integer, primary_key=True, index=True)
|
id = Column(Integer, primary_key=True, index=True)
|
||||||
|
game = Column(String, unique=True)
|
||||||
|
name = Column(String)
|
||||||
|
user_id = Column(Integer, ForeignKey('user.id'))
|
||||||
|
create_date = Column(DateTime, default=datetime.datetime.now())
|
||||||
|
|
||||||
|
21
models/space.py
Normal file
21
models/space.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import datetime
|
||||||
|
|
||||||
|
from sqlalchemy import Boolean, Column, Integer, String, ForeignKey, DateTime
|
||||||
|
from sqlalchemy.orm import relationship, backref
|
||||||
|
|
||||||
|
from db.base_class import Base
|
||||||
|
|
||||||
|
|
||||||
|
class Space(Base):
|
||||||
|
id = Column(Integer, primary_key=True, index=True)
|
||||||
|
name = Column(String)
|
||||||
|
user_id = Column(Integer, ForeignKey('user.id'))
|
||||||
|
project_id = Column(Integer, ForeignKey('project.id'))
|
||||||
|
create_date = Column(DateTime, default=datetime.datetime.now())
|
||||||
|
|
||||||
|
project = relationship('Project', backref='space')
|
||||||
|
|
||||||
|
# dashboard = relationship('Dashboard', backref=backref("space", lazy="joined"))
|
||||||
|
# folder = relationship('Folder', backref=backref("space", lazy="joined"))
|
||||||
|
|
||||||
|
|
@ -10,4 +10,4 @@ class User(Base):
|
|||||||
hashed_password = Column(String, nullable=False)
|
hashed_password = Column(String, nullable=False)
|
||||||
is_active = Column(Boolean(), default=True)
|
is_active = Column(Boolean(), default=True)
|
||||||
is_superuser = Column(Boolean(), default=False)
|
is_superuser = Column(Boolean(), default=False)
|
||||||
dashboard = relationship('Dashboard', back_populates='user')
|
# dashboard = relationship('Dashboard', back_populates='user')
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
from .user import User, UserCreate, UserInDB, UserUpdate,UserLogin,UserBase
|
from .user import User, UserCreate, UserInDB, UserUpdate, UserLogin, UserBase, UserDBBase
|
||||||
from .token import Token, TokenPayload
|
from .token import Token, TokenPayload
|
||||||
from .msg import Msg
|
from .msg import Msg
|
||||||
|
|
||||||
|
from .project import ProjectCreate, Project
|
||||||
|
from .kanban import KanBanCreate, KanBanUpdate
|
||||||
|
from .folders import FolderCreate, FolderUpdate
|
||||||
|
from .dashboard import Dashboard,DashboardCreate, DashboardUpdate
|
||||||
|
from .space import SpaceCreate, SpaceUpdate
|
||||||
|
from .authority import AuthorityCreate, AuthorityUpdate
|
||||||
|
38
schemas/authority.py
Normal file
38
schemas/authority.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
from enum import Enum
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
class AuthorityBase(BaseModel):
|
||||||
|
project_id: int = None
|
||||||
|
dashboard_id: int = None
|
||||||
|
authority: str = None
|
||||||
|
space_id: str = None
|
||||||
|
folder_id: str = None
|
||||||
|
|
||||||
|
|
||||||
|
class AuthorityCreate(AuthorityBase):
|
||||||
|
project_id: int
|
||||||
|
authority: str
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class AuthorityUpdate(AuthorityBase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class AuthorityEnum(str, Enum):
|
||||||
|
write = 'rw'
|
||||||
|
read = 'r'
|
||||||
|
|
||||||
|
|
||||||
|
class Authority(AuthorityBase):
|
||||||
|
id = int
|
||||||
|
user_id = int
|
||||||
|
project_id = int
|
||||||
|
dashboard_id = int
|
||||||
|
authority = AuthorityEnum
|
||||||
|
create_date = datetime
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
orm_mode = True
|
35
schemas/dashboard.py
Normal file
35
schemas/dashboard.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from pydantic import BaseModel, root_validator, Field
|
||||||
|
|
||||||
|
|
||||||
|
class DashboardBase(BaseModel):
|
||||||
|
name: str = None
|
||||||
|
folder_id: int = None
|
||||||
|
space_id: int = None
|
||||||
|
|
||||||
|
|
||||||
|
class DashboardCreate(DashboardBase):
|
||||||
|
name: str
|
||||||
|
|
||||||
|
# @root_validator(pre=True)
|
||||||
|
# def check_parent(cls, values):
|
||||||
|
# if (values.get('folder_id') is None) ^ (values.get('space_id') is None):
|
||||||
|
# return values
|
||||||
|
# else:
|
||||||
|
# raise ValueError('看板必须有一个上级')
|
||||||
|
|
||||||
|
|
||||||
|
class DashboardUpdate(DashboardBase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Dashboard(DashboardBase):
|
||||||
|
name: str=None
|
||||||
|
user_id: int=None
|
||||||
|
folder_id: int=None
|
||||||
|
space_id: int=None
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
orm_mode = True
|
36
schemas/folders.py
Normal file
36
schemas/folders.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from pydantic import BaseModel, root_validator
|
||||||
|
|
||||||
|
|
||||||
|
class FolderBase(BaseModel):
|
||||||
|
kanban_id: int = None
|
||||||
|
name: str = None
|
||||||
|
space_id: int = None
|
||||||
|
|
||||||
|
|
||||||
|
class FolderCreate(FolderBase):
|
||||||
|
name: str
|
||||||
|
|
||||||
|
@root_validator(pre=True)
|
||||||
|
def check_parent(cls, values):
|
||||||
|
if (values.get('kanban_id') is None) ^ (values.get('space_id') is None):
|
||||||
|
return values
|
||||||
|
else:
|
||||||
|
raise ValueError('必须只有一个上级')
|
||||||
|
|
||||||
|
|
||||||
|
class FolderUpdate(FolderBase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Folder(FolderBase):
|
||||||
|
id: int
|
||||||
|
name: str
|
||||||
|
kanban_id: str
|
||||||
|
user_id: int
|
||||||
|
project_id: int
|
||||||
|
create_date: datetime
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
orm_mode = True
|
28
schemas/kanban.py
Normal file
28
schemas/kanban.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
class KanBanBase(BaseModel):
|
||||||
|
project_id: int = None
|
||||||
|
user_id: int = None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class KanBanCreate(KanBanBase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class KanBanUpdate(KanBanBase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class KanBan(KanBanBase):
|
||||||
|
id: int
|
||||||
|
game: str
|
||||||
|
name: str
|
||||||
|
user_id: int
|
||||||
|
create_date: datetime
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
orm_mode = True
|
29
schemas/project.py
Normal file
29
schemas/project.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
# 创建项目请求
|
||||||
|
class ProjectBase(BaseModel):
|
||||||
|
game: str = None
|
||||||
|
name: str = None
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectCreate(ProjectBase):
|
||||||
|
game: str
|
||||||
|
name: str
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectUpdate(ProjectBase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Project(ProjectBase):
|
||||||
|
id: int
|
||||||
|
game: str
|
||||||
|
name: str
|
||||||
|
user_id: int
|
||||||
|
create_date: datetime
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
orm_mode = True
|
26
schemas/space.py
Normal file
26
schemas/space.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
class SpaceBase(BaseModel):
|
||||||
|
name: str = None
|
||||||
|
|
||||||
|
|
||||||
|
class SpaceCreate(SpaceBase):
|
||||||
|
name: str
|
||||||
|
|
||||||
|
|
||||||
|
class SpaceUpdate(SpaceBase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Space(SpaceBase):
|
||||||
|
id: int
|
||||||
|
name: str
|
||||||
|
user_id: int
|
||||||
|
project_id: int
|
||||||
|
create_date: datetime
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
orm_mode = True
|
@ -27,7 +27,7 @@ class UserUpdate(UserBase):
|
|||||||
password: Optional[str] = None
|
password: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
class UserInDBBase(UserBase):
|
class UserDBBase(UserBase):
|
||||||
id: Optional[int] = None
|
id: Optional[int] = None
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
@ -35,10 +35,10 @@ class UserInDBBase(UserBase):
|
|||||||
|
|
||||||
|
|
||||||
# Additional properties to return via API
|
# Additional properties to return via API
|
||||||
class User(UserInDBBase):
|
class User(UserDBBase):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
# Additional properties stored in DB
|
# Additional properties stored in DB
|
||||||
class UserInDB(UserInDBBase):
|
class UserInDB(UserDBBase):
|
||||||
hashed_password: str
|
hashed_password: str
|
||||||
|
Loading…
Reference in New Issue
Block a user