Merge remote-tracking branch 'refs/remotes/origin/dev/pjq'
This commit is contained in:
commit
924b2864d3
@ -2,7 +2,7 @@
|
|||||||
<module type="PYTHON_MODULE" version="4">
|
<module type="PYTHON_MODULE" version="4">
|
||||||
<component name="NewModuleRootManager">
|
<component name="NewModuleRootManager">
|
||||||
<content url="file://$MODULE_DIR$" />
|
<content url="file://$MODULE_DIR$" />
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="jdk" jdkName="Python 3.11" jdkType="Python SDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
@ -38,5 +38,26 @@
|
|||||||
</library>
|
</library>
|
||||||
</libraries>
|
</libraries>
|
||||||
</data-source>
|
</data-source>
|
||||||
|
<data-source source="LOCAL" name="test [2]" uuid="13832c0f-6caa-4909-a819-f7b92b095c8f">
|
||||||
|
<driver-ref>sqlite.xerial</driver-ref>
|
||||||
|
<synchronize>true</synchronize>
|
||||||
|
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
|
||||||
|
<jdbc-url>jdbc:sqlite:C:\Users\15089\PycharmProjects\CostEvalPlatform\test.db</jdbc-url>
|
||||||
|
<working-dir>$ProjectFileDir$</working-dir>
|
||||||
|
<libraries>
|
||||||
|
<library>
|
||||||
|
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/xerial/sqlite-jdbc/3.45.1.0/sqlite-jdbc-3.45.1.0.jar</url>
|
||||||
|
</library>
|
||||||
|
<library>
|
||||||
|
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar</url>
|
||||||
|
</library>
|
||||||
|
<library>
|
||||||
|
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/xerial/sqlite-jdbc/3.45.1.0/sqlite-jdbc-3.45.1.0.jar</url>
|
||||||
|
</library>
|
||||||
|
<library>
|
||||||
|
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar</url>
|
||||||
|
</library>
|
||||||
|
</libraries>
|
||||||
|
</data-source>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
@ -28,5 +28,5 @@
|
|||||||
</profile-state>
|
</profile-state>
|
||||||
</entry>
|
</entry>
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" project-jdk-name="demo1" project-jdk-type="Python SDK" />
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11" project-jdk-type="Python SDK" />
|
||||||
</project>
|
</project>
|
||||||
@ -2,9 +2,188 @@
|
|||||||
# @Time : 2024/11/19 下午8:05
|
# @Time : 2024/11/19 下午8:05
|
||||||
# @FileName: manage_project.py
|
# @FileName: manage_project.py
|
||||||
# @Software: PyCharm
|
# @Software: PyCharm
|
||||||
|
from fastapi import HTTPException, Response, Depends, APIRouter
|
||||||
|
from typing import Optional, Annotated
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
from jose import JWTError, jwt
|
||||||
|
from sqlalchemy import delete
|
||||||
|
|
||||||
|
from sqlmodel import select
|
||||||
|
|
||||||
|
from models import Tenant, User, Project, ProjectUserLink
|
||||||
|
from dependencies import *
|
||||||
from fastapi import APIRouter
|
from fastapi import APIRouter
|
||||||
|
|
||||||
|
from typing import List
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
TenantRole = 1
|
||||||
|
|
||||||
|
|
||||||
|
# 列举所有项目
|
||||||
|
@router.get("/api/s1/project")
|
||||||
|
async def get_project(response: Response, session: SessionDep, current_user: User = Depends(get_current_user)):
|
||||||
|
# 只有角色为 0、1、2 或 3 的用户才可以访问
|
||||||
|
if current_user.role == 0:
|
||||||
|
# 角色为0,显示所有项目
|
||||||
|
projects = session.query(Project).all()
|
||||||
|
elif current_user.role == 1:
|
||||||
|
# 角色为1,显示tenant_id匹配的项目(即属于当前租户的项目)
|
||||||
|
projects = session.query(Project).filter(Project.owner_id == current_user.tenant_id).all()
|
||||||
|
elif current_user.role in [2, 3]:
|
||||||
|
# 角色为2或3,显示与当前用户相关联的项目
|
||||||
|
projects = (
|
||||||
|
session.query(Project)
|
||||||
|
.join(ProjectUserLink)
|
||||||
|
.filter(ProjectUserLink.user_id == current_user.id)
|
||||||
|
.all()
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise HTTPException(status_code=403, detail="You do not have permission to view projects.")
|
||||||
|
|
||||||
|
if not projects:
|
||||||
|
raise HTTPException(status_code=404, detail="Project not found or you have no projects.")
|
||||||
|
|
||||||
|
# 返回项目的基本信息
|
||||||
|
return {
|
||||||
|
"projects": [
|
||||||
|
{
|
||||||
|
"name": project.name,
|
||||||
|
"requirement": project.requirement,
|
||||||
|
"start_time": project.start_time,
|
||||||
|
"deadline": project.deadline
|
||||||
|
}
|
||||||
|
for project in projects
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# 新增与修改项目
|
||||||
|
@router.post("/api/s1/project")
|
||||||
|
async def create_project(data: dict, session: SessionDep, current_user: User = Depends(get_current_user)):
|
||||||
|
if current_user.role != 1:
|
||||||
|
raise HTTPException(status_code=403, detail="Only Tenant admin users can add or update projects.")
|
||||||
|
|
||||||
|
project_id = data.get("project_id")
|
||||||
|
name = data["name"]
|
||||||
|
requirement = data["requirement"]
|
||||||
|
start_time_str = data["start_time"]
|
||||||
|
deadline_str = data["deadline"]
|
||||||
|
estimators = data["estimators"]
|
||||||
|
auditors = data["auditors"]
|
||||||
|
|
||||||
|
# 验证是否缺少必要参数
|
||||||
|
if not name or not requirement or not start_time_str or not deadline_str:
|
||||||
|
raise HTTPException(status_code=400, detail="Need more name/requirement/start_time/deadline")
|
||||||
|
|
||||||
|
# 验证开始时间是否早于结束时间
|
||||||
|
start_time = datetime.strptime(start_time_str, "%Y-%m-%dT%H:%M:%S")
|
||||||
|
deadline = datetime.strptime(deadline_str, "%Y-%m-%dT%H:%M:%S")
|
||||||
|
if start_time > deadline:
|
||||||
|
raise HTTPException(status_code=400, detail="Start time must be before deadline")
|
||||||
|
|
||||||
|
# 验证评估审核员是否存在
|
||||||
|
query_estimators = select(User).where(User.username.in_(estimators))
|
||||||
|
users_estimators = session.exec(query_estimators).all()
|
||||||
|
query_auditors = select(User).where(User.username.in_(auditors))
|
||||||
|
users_auditors = session.exec(query_auditors).all()
|
||||||
|
# 提取出所有查询到的
|
||||||
|
existing_estimators = {user.username for user in users_estimators}
|
||||||
|
existing_auditors = {user.username for user in users_auditors}
|
||||||
|
|
||||||
|
# 验证是否所有的username都存在于数据库中
|
||||||
|
missing_usernames = (set(auditors) | set(estimators)) - existing_estimators - existing_auditors
|
||||||
|
|
||||||
|
if missing_usernames:
|
||||||
|
raise HTTPException(status_code=404, detail=f"Missing usernames:{missing_usernames}")
|
||||||
|
|
||||||
|
# 更新项目还是新增项目
|
||||||
|
if project_id:
|
||||||
|
# 查找现有项目
|
||||||
|
project = session.get(Project, project_id)
|
||||||
|
if not project:
|
||||||
|
raise HTTPException(status_code=404, detail="Project not found")
|
||||||
|
|
||||||
|
# 更新项目内容
|
||||||
|
project.name = name
|
||||||
|
project.requirement = requirement
|
||||||
|
project.start_time = start_time
|
||||||
|
project.deadline = deadline
|
||||||
|
else:
|
||||||
|
# 新增项目
|
||||||
|
exist_project = session.exec(select(Project).where(Project.name == name)).first()
|
||||||
|
print(exist_project) # 测试用
|
||||||
|
if exist_project:
|
||||||
|
raise HTTPException(status_code=404, detail="Project already exists")
|
||||||
|
|
||||||
|
project = Project(
|
||||||
|
name=name,
|
||||||
|
requirement=requirement,
|
||||||
|
start_time=start_time,
|
||||||
|
deadline=deadline,
|
||||||
|
owner_id=1 # 假设owner_id是1,之后应该是通过token获取owner_id吧
|
||||||
|
)
|
||||||
|
session.add(project)
|
||||||
|
|
||||||
|
# 处理项目和用户的关联
|
||||||
|
# 先清除现有的关联
|
||||||
|
# 生成删除语句并执行
|
||||||
|
print(project_id) # 测试用
|
||||||
|
stmt = delete(ProjectUserLink).where(ProjectUserLink.project_id == project.id)
|
||||||
|
session.execute(stmt)
|
||||||
|
session.commit() # 提交事务
|
||||||
|
|
||||||
|
# 重新建立与评估员和审核员的关系
|
||||||
|
for username in estimators:
|
||||||
|
user = next((user for user in users_estimators if user.username == username), None)
|
||||||
|
if user:
|
||||||
|
project_user_link = ProjectUserLink(project_id=project.id, user_id=user.id)
|
||||||
|
session.add(project_user_link)
|
||||||
|
|
||||||
|
for username in auditors:
|
||||||
|
user = next((user for user in users_auditors if user.username == username), None)
|
||||||
|
if user:
|
||||||
|
project_user_link = ProjectUserLink(project_id=project.id, user_id=user.id)
|
||||||
|
session.add(project_user_link)
|
||||||
|
|
||||||
|
# 提交事务
|
||||||
|
session.commit()
|
||||||
|
session.refresh(project)
|
||||||
|
|
||||||
|
return {"message": "Added or updated successfully",
|
||||||
|
"information": project,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# 删除项目
|
||||||
|
@router.delete("/api/s1/project")
|
||||||
|
async def delete_project(data: dict, session: SessionDep, current_user: User = Depends(get_current_user)):
|
||||||
|
if current_user.role != 1:
|
||||||
|
raise HTTPException(status_code=403, detail="Only Tenant admin users can delete projects.")
|
||||||
|
|
||||||
|
project_name = data.get("name")
|
||||||
|
|
||||||
|
# 权限检查:只有管理员才可以删除项目
|
||||||
|
# if current_user.role != 1:
|
||||||
|
# raise HTTPException(status_code=403, detail="Only admin users can delete projects")
|
||||||
|
|
||||||
|
if not project_name:
|
||||||
|
raise HTTPException(status_code=400, detail="Project name is required")
|
||||||
|
|
||||||
|
# 查找项目
|
||||||
|
project = session.exec(
|
||||||
|
select(Project).where(Project.name == project_name)).first()
|
||||||
|
|
||||||
|
if not project:
|
||||||
|
raise HTTPException(status_code=404, detail="Project not found")
|
||||||
|
|
||||||
|
# 删除与项目相关的用户链接
|
||||||
|
# 先清除现有的关联
|
||||||
|
stmt = delete(ProjectUserLink).where(ProjectUserLink.project_id == project.id)
|
||||||
|
session.execute(stmt)
|
||||||
|
|
||||||
|
# 删除项目
|
||||||
|
session.delete(project)
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
return {"detail": "Project deleted successfully"}
|
||||||
|
|||||||
@ -3,6 +3,145 @@
|
|||||||
# @FileName: manage_tanant.py
|
# @FileName: manage_tanant.py
|
||||||
# @Software: PyCharm
|
# @Software: PyCharm
|
||||||
from fastapi import APIRouter
|
from fastapi import APIRouter
|
||||||
|
from fastapi import HTTPException, Response, Depends, APIRouter
|
||||||
|
from typing import Optional, Annotated
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
from jose import JWTError, jwt
|
||||||
|
from sqlalchemy import delete
|
||||||
|
|
||||||
|
from sqlmodel import select
|
||||||
|
|
||||||
|
from models import Tenant, User, Project
|
||||||
|
from dependencies import *
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
from fastapi import HTTPException, Response
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
from models import Tenant, User # 假设你已导入 Tenant 和 User 模型
|
||||||
|
from dependencies import SessionDep # 假设 SessionDep 是数据库会话的依赖
|
||||||
|
|
||||||
|
#列举所有租户
|
||||||
|
@router.get("/api/s1/tenant")
|
||||||
|
async def get_tenant(response: Response, session: SessionDep, current_user: User = Depends(get_current_user)):
|
||||||
|
|
||||||
|
if current_user.role != 0:
|
||||||
|
raise HTTPException(status_code=403, detail="Only Superadmin can list all tenants.")
|
||||||
|
|
||||||
|
tenants = session.query(Tenant).all() # 获取所有租户
|
||||||
|
if not tenants:
|
||||||
|
raise HTTPException(status_code=404, detail="No tenants found")
|
||||||
|
|
||||||
|
tenant_data = []
|
||||||
|
for tenant in tenants:
|
||||||
|
# 获取该租户中 role=1 的第一个用户(如果存在)
|
||||||
|
tenant_user = next((user for user in tenant.users if user.role == 1), None)
|
||||||
|
|
||||||
|
# 获取该租户中除了 role=1 以外的用户数量
|
||||||
|
user_num = len([user for user in tenant.users if user.role != 1])
|
||||||
|
|
||||||
|
# 构建租户信息
|
||||||
|
tenant_info = {
|
||||||
|
"name": tenant.name,
|
||||||
|
"username": tenant_user.username if tenant_user else None, # 如果找到 role=1 的用户,返回其 username
|
||||||
|
"user_num": user_num # 除去 role=1 的用户数量
|
||||||
|
}
|
||||||
|
|
||||||
|
tenant_data.append(tenant_info)
|
||||||
|
|
||||||
|
return {"tenants": tenant_data}
|
||||||
|
|
||||||
|
# 新增和修改租户
|
||||||
|
@router.post("/api/s1/tenant")
|
||||||
|
async def create_or_update_tenant(data: dict, session: SessionDep, current_user: User = Depends(get_current_user)):
|
||||||
|
if current_user.role != 0:
|
||||||
|
raise HTTPException(status_code=403, detail="Only Superadmin can add or update tenants.")
|
||||||
|
|
||||||
|
name = data.get("name")
|
||||||
|
username = data.get("username")
|
||||||
|
password = data.get("password")
|
||||||
|
|
||||||
|
# 验证是否缺少必要参数
|
||||||
|
if not name:
|
||||||
|
raise HTTPException(status_code=400, detail="Need more name")
|
||||||
|
|
||||||
|
if username:
|
||||||
|
# 如果 username 不为空,判断为新建租户
|
||||||
|
# 检查租户名是否已存在
|
||||||
|
tenant_query = select(Tenant).where(Tenant.name == name)
|
||||||
|
existing_tenant = session.exec(tenant_query).first()
|
||||||
|
|
||||||
|
if existing_tenant:
|
||||||
|
raise HTTPException(status_code=409, detail="Tenant name already exists")
|
||||||
|
|
||||||
|
# 创建新租户
|
||||||
|
tenant = Tenant(name=name)
|
||||||
|
session.add(tenant)
|
||||||
|
session.commit()
|
||||||
|
session.refresh(tenant)
|
||||||
|
|
||||||
|
# 创建新用户
|
||||||
|
user = User(
|
||||||
|
username=username,
|
||||||
|
password=password, # 记得加密密码
|
||||||
|
role=1, # 默认role为1
|
||||||
|
tenant_id=tenant.id,
|
||||||
|
)
|
||||||
|
session.add(user)
|
||||||
|
|
||||||
|
# 提交事务
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
return {"message": "Tenant and User added successfully"}
|
||||||
|
|
||||||
|
else:
|
||||||
|
# 如果 username 为空,执行更新操作
|
||||||
|
# 根据租户名称查找 Tenant
|
||||||
|
tenant_query = select(Tenant).where(Tenant.name == name)
|
||||||
|
tenant = session.exec(tenant_query).first()
|
||||||
|
|
||||||
|
# 如果找不到对应的租户,抛出错误
|
||||||
|
if not tenant:
|
||||||
|
raise HTTPException(status_code=404, detail="Tenant not found")
|
||||||
|
|
||||||
|
# 找到租户后,根据 tenant_id 查找该租户下的所有用户
|
||||||
|
user_query = select(User).where(User.tenant_id == tenant.id)
|
||||||
|
|
||||||
|
user = session.exec(user_query).first()
|
||||||
|
|
||||||
|
#如果找不到对应的用户,抛出错误
|
||||||
|
if not user:
|
||||||
|
raise HTTPException(status_code=404, detail="User not found")
|
||||||
|
user.password = password
|
||||||
|
session.add(user)
|
||||||
|
session.commit()
|
||||||
|
print(user) #测试用
|
||||||
|
return {"message": "Tenant and User update successfully"}
|
||||||
|
|
||||||
|
#删除租户
|
||||||
|
@router.delete("/api/s1/tenant")
|
||||||
|
async def delete_tenant(data: dict, session: SessionDep, current_user: User = Depends(get_current_user)):
|
||||||
|
|
||||||
|
if current_user.role != 0:
|
||||||
|
raise HTTPException(status_code=403, detail="Only Superadmin can delete tenants.")
|
||||||
|
|
||||||
|
tenant_name = data.get("name")
|
||||||
|
|
||||||
|
if not tenant_name:
|
||||||
|
raise HTTPException(status_code=400, detail="Tenant name is required")
|
||||||
|
|
||||||
|
# 查找租户
|
||||||
|
tenant = session.exec(
|
||||||
|
select(Tenant).where(Tenant.name == tenant_name)).first()
|
||||||
|
if not tenant:
|
||||||
|
raise HTTPException(status_code=404, detail="Tenant not found")
|
||||||
|
|
||||||
|
# 删除与租户相关的用户
|
||||||
|
stmt = delete(User).where(User.tenant_id == tenant.id)
|
||||||
|
session.execute(stmt)
|
||||||
|
|
||||||
|
# 删除租户
|
||||||
|
session.delete(tenant)
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
return {"detail": "Tenant deleted successfully"}
|
||||||
Loading…
Reference in New Issue
Block a user