167 lines
5.2 KiB
Python
167 lines
5.2 KiB
Python
from typing import List, Optional
|
|
from fastapi import APIRouter, Depends, HTTPException, status
|
|
from pydantic import BaseModel
|
|
from api.dependency import get_dao
|
|
from api.endpoints.auth import get_current_user
|
|
from models.Project import Project
|
|
from repos.dao import DAO
|
|
|
|
router = APIRouter(prefix="/api/projects", tags=["Projects"])
|
|
|
|
class ProjectCreate(BaseModel):
|
|
name: str
|
|
description: Optional[str] = None
|
|
|
|
class ProjectResponse(BaseModel):
|
|
id: str
|
|
name: str
|
|
description: Optional[str] = None
|
|
owner_id: str
|
|
members: List[str]
|
|
is_owner: bool = False
|
|
|
|
@router.post("", response_model=ProjectResponse)
|
|
async def create_project(
|
|
project_data: ProjectCreate,
|
|
dao: DAO = Depends(get_dao),
|
|
current_user: dict = Depends(get_current_user)
|
|
):
|
|
user_id = str(current_user["_id"])
|
|
new_project = Project(
|
|
name=project_data.name,
|
|
description=project_data.description,
|
|
owner_id=user_id,
|
|
members=[user_id]
|
|
)
|
|
project_id = await dao.projects.create_project(new_project)
|
|
|
|
# Add project to user's project list
|
|
# Assuming user_repo has a method to add project or we do it directly?
|
|
# UserRepo doesn't have add_project method yet.
|
|
# But since UserRepo is just a wrapper around collection, lets add it here or update UserRepo later?
|
|
# Better to update UserRepo. For now, let's just return success.
|
|
# But user needs to see it in list.
|
|
# Update user in DB
|
|
await dao.users.collection.update_one(
|
|
{"_id": current_user["_id"]},
|
|
{"$addToSet": {"project_ids": project_id}}
|
|
)
|
|
|
|
return ProjectResponse(
|
|
id=project_id,
|
|
name=new_project.name,
|
|
description=new_project.description,
|
|
owner_id=new_project.owner_id,
|
|
members=new_project.members,
|
|
is_owner=True
|
|
)
|
|
|
|
@router.get("", response_model=List[ProjectResponse])
|
|
async def get_my_projects(
|
|
dao: DAO = Depends(get_dao),
|
|
current_user: dict = Depends(get_current_user)
|
|
):
|
|
user_id = str(current_user["_id"])
|
|
projects = await dao.projects.get_projects_by_user(user_id)
|
|
|
|
responses = []
|
|
for p in projects:
|
|
responses.append(ProjectResponse(
|
|
id=p.id,
|
|
name=p.name,
|
|
description=p.description,
|
|
owner_id=p.owner_id,
|
|
members=p.members,
|
|
is_owner=(p.owner_id == user_id)
|
|
))
|
|
return responses
|
|
|
|
class MemberAdd(BaseModel):
|
|
username: str
|
|
|
|
@router.post("/{project_id}/members", dependencies=[Depends(get_current_user)])
|
|
async def add_member(
|
|
project_id: str,
|
|
member_data: MemberAdd,
|
|
dao: DAO = Depends(get_dao),
|
|
current_user: dict = Depends(get_current_user)
|
|
):
|
|
user_id = str(current_user["_id"])
|
|
project = await dao.projects.get_project(project_id)
|
|
if not project:
|
|
raise HTTPException(status_code=404, detail="Project not found")
|
|
|
|
if project.owner_id != user_id:
|
|
raise HTTPException(status_code=403, detail="Only owner can add members")
|
|
|
|
target_user = await dao.users.get_user_by_username(member_data.username)
|
|
if not target_user:
|
|
raise HTTPException(status_code=404, detail="User not found")
|
|
|
|
target_user_id = str(target_user["_id"])
|
|
|
|
if target_user_id in project.members:
|
|
return {"message": "User already in project"}
|
|
|
|
await dao.projects.add_member(project_id, target_user_id)
|
|
|
|
# Update target user's project list
|
|
await dao.users.collection.update_one(
|
|
{"_id": target_user["_id"]},
|
|
{"$addToSet": {"project_ids": project_id}}
|
|
)
|
|
|
|
return {"message": "Member added"}
|
|
|
|
@router.post("/{project_id}/join", dependencies=[Depends(get_current_user)])
|
|
async def join_project(
|
|
project_id: str,
|
|
dao: DAO = Depends(get_dao),
|
|
current_user: dict = Depends(get_current_user)
|
|
):
|
|
# Retrieve project to verify it exists
|
|
project = await dao.projects.get_project(project_id)
|
|
if not project:
|
|
raise HTTPException(status_code=404, detail="Project not found")
|
|
|
|
user_id = str(current_user["_id"])
|
|
|
|
# Check if user is ALREADY in project
|
|
if user_id in project.members:
|
|
return {"message": "Already a member"}
|
|
|
|
# Add member
|
|
await dao.projects.add_member(project_id, user_id)
|
|
|
|
# Update user's project list
|
|
await dao.users.collection.update_one(
|
|
{"_id": current_user["_id"]},
|
|
{"$addToSet": {"project_ids": project_id}}
|
|
)
|
|
|
|
return {"message": "Joined project"}
|
|
|
|
|
|
@router.delete("/{project_id}", dependencies=[Depends(get_current_user)] )
|
|
async def delete_project(
|
|
project_id: str,
|
|
dao: DAO = Depends(get_dao),
|
|
current_user: dict = Depends(get_current_user)
|
|
):
|
|
user_id = str(current_user["_id"])
|
|
project = await dao.projects.get_project(project_id)
|
|
if not project:
|
|
raise HTTPException(status_code=404, detail="Project not found")
|
|
|
|
if project.owner_id != user_id:
|
|
raise HTTPException(status_code=403, detail="Only owner can delete project")
|
|
|
|
await dao.projects.delete_project(project_id)
|
|
|
|
# Remove project from user's project list
|
|
await dao.users.collection.update_one(
|
|
{"_id": current_user["_id"]},
|
|
{"$pull": {"project_ids": project_id}}
|
|
)
|
|
|
|
return {"message": "Project deleted"} |