Compare commits

..

6 commits

5 changed files with 38 additions and 19 deletions

View file

@ -28,6 +28,13 @@ It allows users to manage projects, tasks, and user assignments with proper auth
## Source Code ## Source Code
The source code for this API can be found on [GitHub](https://github.com/a-mayb3/Kanban_clone_backend) or [my forgejo instance](https://git.vollex.cc/a-mayb3/Kanban_clone_backend). The source code for this API can be found on [GitHub](https://github.com/a-mayb3/Kanban_clone_backend) or [my forgejo instance](https://git.vollex.cc/a-mayb3/Kanban_clone_backend).
## Other projects
Here are some frontend implementations for this API:
- [KanbanCloneAngular](https://github.com/a-mayb3/KanbanCloneAngular) - Angular frontend
- [KanbanCloneAndroid](https://github.com/a-mayb3/KanbanCloneAndroid) - Android frontend
""" """
global_logger = logging.getLogger() global_logger = logging.getLogger()

View file

@ -4,12 +4,15 @@ from jose import JWTError, jwt
import models import models
from routers import auth from routers import auth
import schemas.users as user_schemas
import schemas.projects_users as projects_users_schemas from schemas.users import UserBase
from schemas.projects import ProjectBase
from schemas.projects_users import ProjectUserBase
router = APIRouter(prefix="/me", tags=["me"]) router = APIRouter(prefix="/me", tags=["me"])
@router.get("/", response_model=projects_users_schemas.ProjectUserBase, tags=["me", "users"]) @router.get("/", response_model=ProjectUserBase, tags=["me", "users"])
def get_me(request: Request, db: db_dependency): def get_me(request: Request, db: db_dependency):
"""Get current authenticated user""" """Get current authenticated user"""
user = auth.get_user_from_jwt(request, db) user = auth.get_user_from_jwt(request, db)

View file

@ -4,7 +4,7 @@ from typing import List, Annotated
from database import db_dependency from database import db_dependency
from schemas.tasks import TaskBase, TaskCreate, TaskUpdate from schemas.tasks import TaskBase, TaskCreate, TaskUpdate
from schemas.projects import ProjectBase, ProjectCreate, ProjectUpdate, ProjectAddUsers, ProjectRemoveUsers, ProjectFull from schemas.projects import ProjectBase, ProjectCreate, ProjectUpdate, ProjectAddUser, ProjectRemoveUsers, ProjectFull
from schemas.users import UserBase from schemas.users import UserBase
from schemas.projects_users import ProjectUserBase from schemas.projects_users import ProjectUserBase
from schemas.projects_tasks import ProjectTaskBase, ProjectTaskCreate from schemas.projects_tasks import ProjectTaskBase, ProjectTaskCreate
@ -80,7 +80,7 @@ def get_project_user(project_id: int, user_id: int, db: db_dependency, request:
db_project : ProjectBase = get_project_by_id_for_user(user, project_id, db) db_project : ProjectBase = get_project_by_id_for_user(user, project_id, db)
db_user = db.query(UserBase).filter(getattr(UserBase, "id") == user_id).first() db_user = db.query(User).filter(User.id == user_id).first()
if db_user is None or db_user not in db_project.users: if db_user is None or db_user not in db_project.users:
raise HTTPException(status_code=404, detail="User not found in the specified project") raise HTTPException(status_code=404, detail="User not found in the specified project")
return db_user return db_user
@ -91,7 +91,7 @@ def get_project_tasks(project_id: int, request:Request, db: db_dependency):
user = get_user_from_jwt(request, db) user = get_user_from_jwt(request, db)
db_project = get_project_by_id_for_user(user, project_id, db) db_project = get_project_by_id_for_user(user, project_id, db)
db_tasks = db.query(TaskBase).filter(getattr(TaskBase, "project_id") == project_id).all() db_tasks = db.query(Task).filter(Task.project_id == project_id).all()
return db_tasks return db_tasks
@router.post("/", response_model=ProjectCreate) @router.post("/", response_model=ProjectCreate)
@ -115,14 +115,14 @@ def create_project(project: ProjectCreate, request:Request, db: db_dependency):
return db_project return db_project
@router.post("/{project_id}/tasks", response_model=ProjectTaskCreate, tags=["tasks"]) @router.post("/{project_id}/tasks", response_model=ProjectTaskBase, tags=["tasks"])
def create_project_task(project_id: int, task: TaskCreate, db: db_dependency, request: Request): def create_project_task(project_id: int, task: TaskCreate, db: db_dependency, request: Request):
"""Create a new task in a specified project""" """Create a new task in a specified project"""
user = get_user_from_jwt(request, db) user = get_user_from_jwt(request, db)
db_project = get_project_by_id_for_user(user, project_id, db) db_project = get_project_by_id_for_user(user, project_id, db)
db_task = ProjectTaskCreate( db_task = Task(
title=task.title, title=task.title,
description=task.description, description=task.description,
status=task.status, status=task.status,
@ -134,17 +134,22 @@ def create_project_task(project_id: int, task: TaskCreate, db: db_dependency, re
db.refresh(db_task) db.refresh(db_task)
return db_task return db_task
@router.post("/{project_id}/users", response_model=ProjectAddUsers, tags=["users"]) @router.post("/{project_id}/users", response_model=ProjectFull, tags=["users"])
def add_project_user(project_id: int, user_data: ProjectAddUsers, db: db_dependency, request: Request): def add_project_user(project_id: int, user_data: ProjectAddUser, db: db_dependency, request: Request):
"""Add users to a specified project using their IDs""" """Add a user to a specified project using their email address"""
user = get_user_from_jwt(request, db) user = get_user_from_jwt(request, db)
db_project = get_project_by_id_for_user(user, project_id, db) db_project = get_project_by_id_for_user(user, project_id, db)
for user_id in user_data.user_ids: db_user = db.query(User).filter(User.email == user_data.user_email).first()
db_user = db.query(UserBase).filter(getattr(UserBase, "id") == user_id).first()
if db_user: if not db_user:
raise HTTPException(status_code=404, detail="User with the specified email not found")
if db_user not in db_project.users:
db_project.users.append(db_user) db_project.users.append(db_user)
else:
raise HTTPException(status_code=400, detail="User is already a member of the project")
db.commit() db.commit()
db.refresh(db_project) db.refresh(db_project)
return db_project return db_project
@ -156,7 +161,7 @@ def remove_user_from_project(project_id: int, user_id: int, db: db_dependency, r
db_project = get_project_by_id_for_user(user, project_id, db) db_project = get_project_by_id_for_user(user, project_id, db)
db_user = db.query(UserBase).filter(getattr(UserBase, "id") == user_id).first() db_user = db.query(User).filter(User.id == user_id).first()
if db_user is None or db_user not in db_project.users: if db_user is None or db_user not in db_project.users:
raise HTTPException(status_code=404, detail="User not found in the specified project") raise HTTPException(status_code=404, detail="User not found in the specified project")

View file

@ -26,6 +26,9 @@ class ProjectUpdate(BaseModel):
name: Optional[str] = None name: Optional[str] = None
description: Optional[str] = None description: Optional[str] = None
class ProjectAddUser(BaseModel):
user_email: str
class ProjectAddUsers(BaseModel): class ProjectAddUsers(BaseModel):
user_ids: List[int] = [] user_ids: List[int] = []

View file

@ -1,10 +1,11 @@
from typing import List from typing import List
from pydantic import ConfigDict from pydantic import ConfigDict
from schemas.projects import ProjectBase from schemas.projects import ProjectFull
from schemas.users import UserBase from schemas.users import UserBase
class ProjectUserBase(UserBase): class ProjectUserBase(UserBase):
model_config = ConfigDict(from_attributes=True) model_config = ConfigDict(from_attributes=True)
projects: List[ProjectBase] projects: List[ProjectFull]