diff --git a/.idea/CostEvalPlatform.iml b/.idea/CostEvalPlatform.iml index d0876a7..909438d 100644 --- a/.idea/CostEvalPlatform.iml +++ b/.idea/CostEvalPlatform.iml @@ -2,7 +2,7 @@ - + \ No newline at end of file diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml index 11cdf89..1de88be 100644 --- a/.idea/dataSources.xml +++ b/.idea/dataSources.xml @@ -38,5 +38,26 @@ + + sqlite.xerial + true + org.sqlite.JDBC + jdbc:sqlite:C:\Users\15089\PycharmProjects\CostEvalPlatform\test.db + $ProjectFileDir$ + + + 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 + + + file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar + + + 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 + + + file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 63337c1..2f33712 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -28,5 +28,5 @@ - + \ No newline at end of file diff --git a/api/manage_project.py b/api/manage_project.py index c6426f6..804faa4 100644 --- a/api/manage_project.py +++ b/api/manage_project.py @@ -2,9 +2,188 @@ # @Time : 2024/11/19 下午8:05 # @FileName: manage_project.py # @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 typing import List + 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"} diff --git a/api/manage_tanant.py b/api/manage_tanant.py index 04404e9..ad4240b 100644 --- a/api/manage_tanant.py +++ b/api/manage_tanant.py @@ -3,6 +3,145 @@ # @FileName: manage_tanant.py # @Software: PyCharm 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() +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"} \ No newline at end of file