Skip to content
This repository has been archived by the owner on Sep 27, 2024. It is now read-only.

Commit

Permalink
Add initial user routes
Browse files Browse the repository at this point in the history
  • Loading branch information
msathieu committed Mar 3, 2024
1 parent a3d9c96 commit 1a4c5a3
Show file tree
Hide file tree
Showing 12 changed files with 106 additions and 42 deletions.
4 changes: 2 additions & 2 deletions backend/app.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import uvicorn
from fastapi import FastAPI

from routes.teachers import teachers_router
from routes.users import users_router

app = FastAPI()

# Koppel routes uit andere modules.
app.include_router(teachers_router)
app.include_router(users_router, prefix="/api")

if __name__ == "__main__":
uvicorn.run("app:app")
5 changes: 5 additions & 0 deletions backend/db/implementation/SqlAdminDAO.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,8 @@ def create_admin(self, name: str, email: str) -> AdminDataclass:
session.add(new_admin)
session.commit()
return new_admin.to_domain_model()

def is_user_admin(self, user_id: int) -> bool:
with Session(engine) as session:
admin = session.get(Admin, user_id)
return admin is not None
5 changes: 5 additions & 0 deletions backend/db/implementation/SqlStudentDAO.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,8 @@ def create_student(self, name: str, email: str) -> StudentDataclass:
session.add(new_student)
session.commit()
return new_student.to_domain_model()

def is_user_student(self, user_id: int) -> bool:
with Session(engine) as session:
student = session.get(Student, user_id)
return student is not None
5 changes: 5 additions & 0 deletions backend/db/implementation/SqlTeacherDAO.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,8 @@ def create_teacher(self, name: str, email: str) -> TeacherDataclass:
session.add(new_teacher)
session.commit()
return new_teacher.to_domain_model()

def is_user_teacher(self, user_id: int) -> bool:
with Session(engine) as session:
teacher = session.get(Teacher, user_id)
return teacher is not None
4 changes: 4 additions & 0 deletions backend/db/interface/AdminDAO.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,7 @@ def create_admin(self, name: str, email: str) -> AdminDataclass:
:return: De nieuwe admin
"""
raise NotImplementedError

@abstractmethod
def is_user_admin(self, user_id: int) -> bool:
raise NotImplementedError
4 changes: 4 additions & 0 deletions backend/db/interface/StudentDAO.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,7 @@ def create_student(self, name: str, email: str) -> StudentDataclass:
:returns: De nieuw aangemaakte student
"""
raise NotImplementedError

@abstractmethod
def is_user_student(self, user_id: int) -> bool:
raise NotImplementedError
4 changes: 4 additions & 0 deletions backend/db/interface/TeacherDAO.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,7 @@ def create_teacher(self, name: str, email: str) -> TeacherDataclass:
:returns: De nieuw aangemaakte teacher.
"""
raise NotImplementedError

@abstractmethod
def is_user_teacher(self, user_id: int) -> bool:
raise NotImplementedError
27 changes: 27 additions & 0 deletions backend/domain/models/APIUser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from pydantic import BaseModel, EmailStr

from db.implementation.SqlAdminDAO import SqlAdminDAO
from db.implementation.SqlStudentDAO import SqlStudentDAO
from db.implementation.SqlTeacherDAO import SqlTeacherDAO
from domain.models.UserDataclass import UserDataclass


class APIUser(BaseModel):
id: int
name: str
email: EmailStr
roles: list[str]


def convert_user(user: UserDataclass) -> APIUser:
result = APIUser(id=user.id, name=user.name, email=user.email, roles=[])
teacher_dao = SqlTeacherDAO()
admin_dao = SqlAdminDAO()
student_dao = SqlStudentDAO()
if teacher_dao.is_user_teacher(user.id):
result.roles.append("teacher")
if admin_dao.is_user_admin(user.id):
result.roles.append("admin")
if student_dao.is_user_student(user.id):
result.roles.append("student")
return result
6 changes: 4 additions & 2 deletions backend/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ ignore = [
"TCH001", # Move application import `...` into a type-checking block (dit is enkel voor performance)
"RUF009", # Do not perform function call `...` in dataclass defaults but needed for sql alchemy
"PLR0913", # Too many arguments in function
"FBT001" # Boolean-typed positional argument in function dfinition
"FBT001", # Boolean-typed positional argument in function dfinition
"FBT002",
"B008"
]

# Allow fix for all enabled rules (when `--fix`) is provided.
Expand Down Expand Up @@ -125,4 +127,4 @@ docstring-code-format = false
#
# This only has an effect when the `docstring-code-format` setting is
# enabled.
docstring-code-line-length = "dynamic"
docstring-code-line-length = "dynamic"
13 changes: 13 additions & 0 deletions backend/routes/login.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from fastapi import Depends

from db.implementation.SqlAdminDAO import SqlAdminDAO
from db.implementation.SqlUserDAO import SqlUserDAO
from domain.models.UserDataclass import UserDataclass


def get_authenticated_user() -> UserDataclass:
return SqlUserDAO().get(1) # Actually authenticate user


def is_user_admin(user: UserDataclass = Depends(get_authenticated_user)) -> bool:
return SqlAdminDAO().is_user_admin(user.id)
38 changes: 0 additions & 38 deletions backend/routes/teachers.py

This file was deleted.

33 changes: 33 additions & 0 deletions backend/routes/users.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from fastapi import APIRouter, Depends, HTTPException

from db.errors.database_errors import ItemNotFoundError
from db.implementation.SqlUserDAO import SqlUserDAO
from domain.models.APIUser import APIUser, convert_user
from domain.models.UserDataclass import UserDataclass
from routes.login import get_authenticated_user, is_user_admin

users_router = APIRouter()


@users_router.get("/user")
def get_current_user(user: UserDataclass = Depends(get_authenticated_user)) -> APIUser:
return convert_user(user)


@users_router.get("/users")
def get_users(admin: bool = Depends(is_user_admin)) -> list[APIUser]:
if not admin:
raise HTTPException(status_code=403)
users = SqlUserDAO().get_all()
return [convert_user(user) for user in users]


@users_router.get("/users/{uid}")
def get_user(uid: int, admin: bool = Depends(is_user_admin)) -> APIUser:
if not admin:
raise HTTPException(status_code=403)
try:
user = SqlUserDAO().get(uid)
except ItemNotFoundError as err:
raise HTTPException(status_code=404) from err
return convert_user(user)

0 comments on commit 1a4c5a3

Please sign in to comment.