-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Backend project #36
Merged
Merged
Backend project #36
Changes from 8 commits
Commits
Show all changes
36 commits
Select commit
Hold shift + click to select a range
d4507f8
adds project schemes,routes,services into backend (not complete)
DRIESASTER a0181e2
router + services, added create delete, get not yet update
DRIESASTER eaac905
cleanup + all projects for certain subject overview added
DRIESASTER 448fe6d
project update
DRIESASTER 53fd83f
Merge remote-tracking branch 'origin/main' into backend_project
DRIESASTER e68320f
Merge remote-tracking branch 'origin/dev' into backend_project
DRIESASTER c2ee3ff
exceptions split up, cleanup
DRIESASTER 2ed95d5
actual patches/fixes now that im running on linux
DRIESASTER d87943a
api voor router gezet
DRIESASTER 4f44ee3
Merge remote-tracking branch 'origin/dev' into backend_project
DRIESASTER b0635bf
Merge branch 'dev' into backend_project
xerbalind 43520c9
alembic added
DRIESASTER b4d5047
Merge remote-tracking branch 'origin/backend_project' into backend_pr…
DRIESASTER 2a1ff7c
alembic added
DRIESASTER ecbfa62
autopep8
DRIESASTER 6ae0215
adds project schemes,routes,services into backend (not complete)
DRIESASTER edf2606
router + services, added create delete, get not yet update
DRIESASTER 278024e
cleanup + all projects for certain subject overview added
DRIESASTER 56d35db
project update
DRIESASTER c7df7b9
exceptions split up, cleanup
DRIESASTER 96ce5cc
actual patches/fixes now that im running on linux
DRIESASTER 6a3373e
api voor router gezet
DRIESASTER c5bd3b5
alembic added
DRIESASTER 6cee923
alembic added
DRIESASTER 7a37a92
autopep8
DRIESASTER 2ac848e
Merge remote-tracking branch 'origin/backend_project' into backend_pr…
DRIESASTER bb5adea
Merge remote-tracking branch 'origin/dev' into backend_project
DRIESASTER 91e701f
style
DRIESASTER 31bf4b5
alembic import op ignore (style error)
DRIESASTER d73dfa7
pyright fixes
DRIESASTER 366a7a8
pyright fixes
DRIESASTER e5b4010
style fixes
DRIESASTER 009962a
style fixes
DRIESASTER 25afa96
linterrrrrrrrrrr
DRIESASTER 9137de1
requirements.txt
xerbalind 74787fe
Fix problems with project
xerbalind File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
from fastapi import Depends | ||
from sqlalchemy.orm import Session | ||
from src.dependencies import get_db | ||
from src.user.dependencies import get_authenticated_user | ||
from src.user.exceptions import NotAuthorized | ||
from src.user.schemas import User | ||
from src.subject.schemas import Subject | ||
from src.subject.schemas import SubjectList | ||
|
||
|
||
from . import service | ||
|
||
|
||
async def retrieve_subjects( | ||
user: User = Depends(get_authenticated_user), db: Session = Depends(get_db) | ||
) -> SubjectList: | ||
teacher_subjects, student_subjects = await service.get_subjects(db, user.uid) | ||
return SubjectList(as_teacher=teacher_subjects, as_student=student_subjects) | ||
|
||
|
||
async def user_permission_validation( | ||
subject_id: int, | ||
user: User = Depends(get_authenticated_user), | ||
db: Session = Depends(get_db), | ||
): | ||
if not user.is_admin: | ||
teachers = await service.get_teachers(db, subject_id) | ||
if not list(filter(lambda teacher: teacher.id == user.uid, teachers)): | ||
raise NotAuthorized() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# exceptions.py | ||
|
||
from fastapi import HTTPException | ||
|
||
|
||
def NoProjectsFoundException(subject_id: int): | ||
return HTTPException(status_code=404, detail=f"No projects found for subject {subject_id}") | ||
|
||
|
||
def UnauthorizedToCreateProjectException(): | ||
return HTTPException(status_code=403, detail="User is not authorized to create projects for this subject") | ||
|
||
|
||
def ProjectNotFoundException(): | ||
return HTTPException(status_code=404, detail="Project not found") | ||
|
||
|
||
def UnauthorizedToDeleteProjectException(): | ||
return HTTPException(status_code=403, detail="User is not authorized to delete this project") | ||
|
||
|
||
def UnauthorizedToUpdateProjectException(): | ||
return HTTPException(status_code=403, detail="User is not authorized to update projects for this subject") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
from sqlalchemy import Column, BigInteger, String, Date, ForeignKey | ||
from sqlalchemy.orm import relationship | ||
from src.database import Base | ||
|
||
|
||
class Project(Base): | ||
__tablename__ = 'project' | ||
|
||
id = Column(BigInteger, primary_key=True, autoincrement=True, index=True) | ||
deadline = Column(Date, nullable=False, check_constraint='deadline >= CURRENT_DATE') | ||
name = Column(String, nullable=False) | ||
subjectId = Column(String, ForeignKey( | ||
'Subject.subjectId', ondelete="SET NULL"), nullable=True) | ||
description = Column(String, nullable=True) | ||
|
||
# Relationships | ||
teams = relationship("Team", back_populates="project") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
from fastapi import APIRouter, Depends, HTTPException | ||
from sqlalchemy.ext.asyncio import AsyncSession | ||
from src.user.models import User | ||
from src.dependencies import get_db | ||
from src.user.dependencies import get_authenticated_user | ||
from .schemas import ProjectCreate, ProjectResponse, ProjectUpdate | ||
from .service import create_project, get_project, delete_project, update_project, get_projects_for_subject | ||
from ..subject.service import is_teacher_of_subject | ||
from . import exceptions | ||
|
||
router = APIRouter( | ||
prefix="/subjects/{subject_id}/projects", | ||
tags=["projects"], | ||
responses={404: {"description": "Not found"}}, | ||
) | ||
|
||
|
||
@router.get("/", response_model=list[ProjectResponse]) | ||
async def list_projects_for_subject( | ||
subject_id: int, | ||
user: User = Depends(get_authenticated_user), | ||
db: AsyncSession = Depends(get_db) | ||
): | ||
# Optional: You may want to check if the user has access to the subject (e.g., is a teacher or a student of the subject) | ||
projects = await get_projects_for_subject(db, subject_id) | ||
if not projects: | ||
raise NoProjectsFoundException(subject_id) | ||
return projects | ||
|
||
|
||
@router.post("/", response_model=ProjectResponse) | ||
async def create_project_for_subject( | ||
subject_id: int, | ||
project_in: ProjectCreate, | ||
user: User = Depends(get_authenticated_user), | ||
db: AsyncSession = Depends(get_db) | ||
): | ||
if not await is_teacher_of_subject(db, user.id, subject_id): | ||
raise UnauthorizedToCreateProjectException() | ||
|
||
project = await create_project(db=db, project_in=project_in, user_id=user.id) | ||
return project | ||
|
||
|
||
@router.get("/{project_id}", response_model=ProjectResponse) | ||
async def get_project_for_subject( | ||
project_id: int, | ||
db: AsyncSession = Depends(get_db) | ||
): | ||
project = await get_project(db, project_id) | ||
if not project: | ||
raise ProjectNotFoundException() | ||
return project | ||
|
||
|
||
@router.delete("/{project_id}") | ||
async def delete_project_for_subject( | ||
subject_id: int, | ||
project_id: int, | ||
user: User = Depends(get_authenticated_user), | ||
db: AsyncSession = Depends(get_db) | ||
): | ||
if not await is_teacher_of_subject(db, user.id, subject_id): | ||
raise UnauthorizedToUpdateProjectException() | ||
|
||
await delete_project(db, project_id) | ||
return {"message": "Project deleted successfully"} | ||
|
||
|
||
@router.patch("/{project_id}", response_model=ProjectResponse) | ||
async def patch_project_for_subject( | ||
subject_id: int, | ||
project_id: int, | ||
project_update: ProjectUpdate, | ||
user: User = Depends(get_authenticated_user), | ||
db: AsyncSession = Depends(get_db) | ||
): | ||
# Check if the user is authorized to update the project | ||
if not await is_teacher_of_subject(db, user.id, subject_id): | ||
raise UnauthorizedToUpdateProjectException() | ||
|
||
updated_project = await update_project(db, project_id, project_update) | ||
if not updated_project: | ||
raise ProjectNotFoundException() | ||
return updated_project |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
from datetime import date | ||
from typing import Optional | ||
|
||
from pydantic import BaseModel, Field, validator | ||
|
||
|
||
class ProjectCreate(BaseModel): | ||
name: str = Field(..., min_length=1) | ||
deadline: date | ||
subject_id: int | ||
description: str | ||
|
||
# Check if deadline is not in the past | ||
@validator('deadline', pre=True, always=True) | ||
def validate_deadline(cls, value): | ||
if value < date.today(): | ||
raise ValueError('The deadline cannot be in the past') | ||
return value | ||
|
||
|
||
class ProjectResponse(BaseModel): | ||
id: int | ||
name: str | ||
deadline: date | ||
subject_id: int | ||
description: str | ||
|
||
class Config: | ||
orm_mode = True | ||
|
||
|
||
class ProjectUpdate(BaseModel): | ||
name: Optional[str] = None | ||
deadline: Optional[date] = None | ||
description: Optional[str] = None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
from sqlalchemy.orm import Session | ||
from . import models, schemas | ||
from .models import Project | ||
from .schemas import ProjectCreate | ||
|
||
|
||
async def create_project(db: Session, project_in: ProjectCreate, user_id: str) -> Project: | ||
new_project = Project( | ||
name=project_in.name, | ||
deadline=project_in.deadline, | ||
subject_id=project_in.subject_id, | ||
description=project_in.description | ||
) | ||
db.add(new_project) | ||
db.commit() | ||
db.refresh(new_project) | ||
return new_project | ||
|
||
|
||
async def get_project(db: Session, project_id: int) -> Project: | ||
return db.query(Project).filter(Project.id == project_id).first() | ||
|
||
|
||
async def get_projects_for_subject(db: Session, subject_id: int) -> list[models.Project]: | ||
projects = ( | ||
db.query(models.Project) | ||
.filter(models.Project.subject_id == subject_id) | ||
.all() | ||
) | ||
return projects | ||
|
||
|
||
async def delete_project(db: Session, project_id: int): | ||
project = db.query(Project).filter(Project.id == project_id).first() | ||
if project: | ||
db.delete(project) | ||
db.commit() | ||
|
||
|
||
async def update_project(db: Session, project_id: int, project_update: ProjectCreate) -> Project: | ||
project = db.query(Project).filter(Project.id == project_id).first() | ||
if project: | ||
project.name = project_update.name | ||
project.deadline = project_update.deadline | ||
project.description = project_update.description | ||
db.commit() | ||
db.refresh(project) | ||
return project |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hier moet nog
/api
voor, zodat de endpoints zowel lokaal als op de server hetzelfde zijnThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in orde