Skip to content

Commit 8d1d782

Browse files
Merge pull request #14 from C216-Distribuid-System-Project/feat/MF-project_routes
Project Routes Implementation
2 parents 062f45c + 358dcbf commit 8d1d782

File tree

5 files changed

+267
-3
lines changed

5 files changed

+267
-3
lines changed

src/models/project_model.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
from sqlalchemy.orm import relationship
2+
from src.modules.database_conection import Base
3+
from sqlalchemy import Column, Integer, String, Text, ForeignKey, TIMESTAMP, func
4+
5+
6+
class Project(Base):
7+
"""
8+
Represents a project entity in the to-do list application.
9+
10+
Attributes:
11+
id (int): Primary key identifier for the project.
12+
user_id (int): Foreign key referencing the user who owns the project.
13+
title (str): Title of the project.
14+
description (str): Detailed description of the project.
15+
created_at (datetime): Timestamp when the project was created.
16+
updated_at (datetime): Timestamp when the project was last updated.
17+
user (User): Relationship to the User model, representing the owner of the project.
18+
"""
19+
20+
__tablename__ = "projects"
21+
22+
id = Column(Integer, primary_key=True, index=True)
23+
user_id = Column(
24+
Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False
25+
)
26+
title = Column(String(255), nullable=False)
27+
description = Column(Text)
28+
created_at = Column(TIMESTAMP, server_default=func.now())
29+
updated_at = Column(TIMESTAMP, server_default=func.now(), onupdate=func.now())
30+
31+
user = relationship("User", back_populates="projects")

src/models/user_model.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
from sqlalchemy import Column, Integer, String, Date, TIMESTAMP
21
from sqlalchemy.sql import func
2+
from sqlalchemy.orm import relationship
33
from src.modules.database_conection import Base
4+
from sqlalchemy import Column, Integer, String, Date, TIMESTAMP
45

56
class User(Base):
67
"""
@@ -25,3 +26,6 @@ class User(Base):
2526
password_hash = Column(String(255), nullable=False)
2627
created_at = Column(TIMESTAMP, server_default=func.now(), nullable=False)
2728
updated_at = Column(TIMESTAMP, server_default=func.now(), onupdate=func.now(), nullable=False)
29+
30+
# Relationship to projects
31+
projects = relationship("Project", back_populates="user", cascade="all, delete-orphan")

src/modules/modules_api.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
from fastapi import APIRouter
2-
from src.routes.authentication_routes import authentication_router
2+
33
from src.routes.user_routes import user_router
4+
from src.routes.project_routes import project_router
5+
from src.routes.authentication_routes import authentication_router
46

57
# -------------------- API ROUTES -------------------- #
68
router = APIRouter()
79

810
router.include_router(authentication_router)
9-
router.include_router(user_router)
11+
router.include_router(user_router)
12+
router.include_router(project_router)

src/routes/project_routes.py

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
from typing import List
2+
3+
from sqlalchemy.orm import Session
4+
from fastapi import APIRouter, Depends, HTTPException, status
5+
6+
from src.utils.utils import get_db
7+
from src.models.user_model import User
8+
from src.models.project_model import Project
9+
from src.utils.security import get_current_user
10+
from src.schemas.projects.projects_schema import ProjectCreate, ProjectResponse
11+
12+
project_router = APIRouter(prefix="/projects", tags=["projects"])
13+
14+
15+
@project_router.post(
16+
"/", response_model=ProjectResponse, status_code=status.HTTP_201_CREATED
17+
)
18+
def create_project(
19+
project: ProjectCreate,
20+
db: Session = Depends(get_db),
21+
current_user: User = Depends(get_current_user),
22+
):
23+
"""
24+
Create a new project for the authenticated user.
25+
26+
This endpoint allows the current authenticated user to create a new project
27+
by providing the required project data. The project will be associated with
28+
the user who is currently authenticated.
29+
30+
Args:
31+
project (ProjectCreate): The project data to be created, including title and description.
32+
db (Session): SQLAlchemy database session dependency.
33+
current_user (User): The currently authenticated user, injected by dependency.
34+
35+
Returns:
36+
ProjectResponse: The newly created project data.
37+
38+
Raises:
39+
HTTPException: If the user is not authenticated or if there is a database error.
40+
41+
Status Codes:
42+
201 CREATED: Project was successfully created.
43+
"""
44+
new_project = Project(
45+
user_id=current_user.id, title=project.title, description=project.description
46+
)
47+
db.add(new_project)
48+
db.commit()
49+
db.refresh(new_project)
50+
return new_project
51+
52+
53+
@project_router.get("/", response_model=List[ProjectResponse])
54+
def list_projects(
55+
db: Session = Depends(get_db), current_user: User = Depends(get_current_user)
56+
):
57+
"""
58+
List all projects for the authenticated user.
59+
60+
This endpoint allows the current authenticated user to retrieve a list of all
61+
projects associated with their account.
62+
63+
Args:
64+
db (Session): SQLAlchemy database session dependency.
65+
current_user (User): The currently authenticated user, injected by dependency.
66+
67+
Returns:
68+
List[ProjectResponse]: A list of projects associated with the authenticated user.
69+
70+
Raises:
71+
HTTPException: If the user is not authenticated.
72+
73+
Status Codes:
74+
200 OK: Projects were successfully retrieved.
75+
"""
76+
return db.query(Project).filter(Project.user_id == current_user.id).all()
77+
78+
79+
@project_router.get("/{project_id}", response_model=ProjectResponse)
80+
def get_project(
81+
project_id: int,
82+
db: Session = Depends(get_db),
83+
current_user: User = Depends(get_current_user),
84+
):
85+
"""
86+
Get a specific project for the authenticated user.
87+
88+
This endpoint allows the current authenticated user to retrieve a specific
89+
project associated with their account by providing the project ID.
90+
91+
Args:
92+
project_id (int): The ID of the project to retrieve.
93+
db (Session): SQLAlchemy database session dependency.
94+
current_user (User): The currently authenticated user, injected by dependency.
95+
96+
Returns:
97+
ProjectResponse: The project data for the specified project ID.
98+
99+
Raises:
100+
HTTPException: If the user is not authenticated or if the project is not found.
101+
102+
Status Codes:
103+
200 OK: Project was successfully retrieved.
104+
404 NOT FOUND: Project was not found.
105+
"""
106+
project = (
107+
db.query(Project)
108+
.filter(Project.id == project_id, Project.user_id == current_user.id)
109+
.first()
110+
)
111+
if not project:
112+
raise HTTPException(status_code=404, detail="Projeto não encontrado.")
113+
return project
114+
115+
116+
@project_router.put("/{project_id}", response_model=ProjectResponse)
117+
def update_project(
118+
project_id: int,
119+
updated: ProjectCreate,
120+
db: Session = Depends(get_db),
121+
current_user: User = Depends(get_current_user),
122+
):
123+
"""
124+
Update a specific project for the authenticated user.
125+
126+
This endpoint allows the current authenticated user to update a specific
127+
project associated with their account by providing the project ID and the
128+
updated project data.
129+
130+
Args:
131+
project_id (int): The ID of the project to update.
132+
updated (ProjectCreate): The updated project data, including title and description.
133+
db (Session): SQLAlchemy database session dependency.
134+
current_user (User): The currently authenticated user, injected by dependency.
135+
136+
Returns:
137+
ProjectResponse: The updated project data.
138+
139+
Raises:
140+
HTTPException: If the user is not authenticated or if the project is not found.
141+
142+
Status Codes:
143+
200 OK: Project was successfully updated.
144+
404 NOT FOUND: Project was not found.
145+
"""
146+
project = (
147+
db.query(Project)
148+
.filter(Project.id == project_id, Project.user_id == current_user.id)
149+
.first()
150+
)
151+
if not project:
152+
raise HTTPException(status_code=404, detail="Projeto não encontrado.")
153+
project.title = updated.title
154+
project.description = updated.description
155+
db.commit()
156+
db.refresh(project)
157+
return project
158+
159+
160+
@project_router.delete("/{project_id}", status_code=status.HTTP_204_NO_CONTENT)
161+
def delete_project(
162+
project_id: int,
163+
db: Session = Depends(get_db),
164+
current_user: User = Depends(get_current_user),
165+
):
166+
"""
167+
Delete a specific project for the authenticated user.
168+
This endpoint allows the current authenticated user to delete a specific
169+
project associated with their account by providing the project ID.
170+
171+
Args:
172+
project_id (int): The ID of the project to delete.
173+
db (Session): SQLAlchemy database session dependency.
174+
current_user (User): The currently authenticated user, injected by dependency.
175+
176+
Raises:
177+
HTTPException: If the user is not authenticated or if the project is not found.
178+
179+
Status Codes:
180+
204 NO CONTENT: Project was successfully deleted.
181+
"""
182+
project = (
183+
db.query(Project)
184+
.filter(Project.id == project_id, Project.user_id == current_user.id)
185+
.first()
186+
)
187+
if not project:
188+
raise HTTPException(status_code=404, detail="Projeto não encontrado.")
189+
db.delete(project)
190+
db.commit()
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
from typing import Optional
2+
from datetime import datetime
3+
from pydantic import BaseModel
4+
5+
class ProjectCreate(BaseModel):
6+
"""
7+
ProjectCreate schema for creating new projects.
8+
9+
Attributes:
10+
title (str): Title of the project.
11+
description (Optional[str]): Description of the project.
12+
"""
13+
title: str
14+
description: Optional[str] = None
15+
16+
class ProjectResponse(ProjectCreate):
17+
"""
18+
ProjectResponse schema for API responses.
19+
20+
Inherits from ProjectCreate and adds additional fields for the project ID,
21+
creation timestamp, and last update timestamp.
22+
23+
Attributes:
24+
id (int): Unique identifier for the project.
25+
created_at (datetime): Timestamp when the project was created.
26+
updated_at (datetime): Timestamp when the project was last updated.
27+
28+
Config:
29+
from_attributes (bool): Enables population of the model from ORM objects.
30+
"""
31+
id: int
32+
created_at: datetime
33+
updated_at: datetime
34+
35+
class Config:
36+
from_attributes = True

0 commit comments

Comments
 (0)