Skip to content

Commit

Permalink
Merge branch 'dev' into user-endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
xerbalind committed Mar 13, 2024
2 parents 525e46d + ba6c214 commit d2972c0
Show file tree
Hide file tree
Showing 12 changed files with 46 additions and 52 deletions.
3 changes: 1 addition & 2 deletions backend/src/auth/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
from cas import CASClient
from fastapi import APIRouter, Depends, Request
from fastapi.responses import RedirectResponse
from sqlalchemy.orm import Session
from src import config
from src.auth.schemas import Authority, Token, TokenRequest
from src.dependencies import get_db, get_async_db
from src.dependencies import get_async_db
from src.user.schemas import UserCreate

from .exceptions import UnAuthenticated
Expand Down
13 changes: 7 additions & 6 deletions backend/src/database.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
from sqlalchemy import MetaData, create_engine
from sqlalchemy import create_engine
from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
from sqlalchemy.orm import declarative_base
from sqlalchemy.orm import sessionmaker

from src import config

SQLALCHEMY_DATABASE_URL = config.CONFIG.database_uri

# TODO: migrate full codebase to async
engine = create_engine(SQLALCHEMY_DATABASE_URL)
async_engine = create_async_engine(SQLALCHEMY_DATABASE_URL[:len(
"postgresql")] + "+asyncpg" + SQLALCHEMY_DATABASE_URL[len("postgresql"):])
async_engine = create_async_engine(
SQLALCHEMY_DATABASE_URL[: len("postgresql")]
+ "+asyncpg"
+ SQLALCHEMY_DATABASE_URL[len("postgresql"):]
)

SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
AsyncSessionLocal = async_sessionmaker(async_engine, autoflush=False)

Base = declarative_base()
16 changes: 2 additions & 14 deletions backend/src/dependencies.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,6 @@
from typing import Any, AsyncGenerator, Generator

from typing import Any, AsyncGenerator
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import Session

from .database import AsyncSessionLocal, SessionLocal


def get_db() -> Generator[Session, Any, None]:
"""Creates new database session per request, which is closed afterwards"""
db = SessionLocal()
try:
yield db
finally:
db.close()
from .database import AsyncSessionLocal


async def get_async_db() -> AsyncGenerator[AsyncSession, Any]:
Expand Down
5 changes: 2 additions & 3 deletions backend/src/project/dependencies.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from fastapi import Depends
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import Session
from src.dependencies import get_db
from src.dependencies import get_async_db
from src.user.dependencies import get_authenticated_user
from src.user.schemas import User

Expand All @@ -12,7 +11,7 @@
async def user_permission_validation(
subject_id: int,
user: User = Depends(get_authenticated_user),
db: AsyncSession = Depends(get_db),
db: AsyncSession = Depends(get_async_db),
):
if not user.is_admin:
teachers = await get_teachers(db, subject_id)
Expand Down
43 changes: 24 additions & 19 deletions backend/src/project/router.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
from fastapi import APIRouter, Depends
from sqlalchemy.ext.asyncio import AsyncSession
from src.dependencies import get_async_db
from src.subject.dependencies import user_permission_validation
from src.dependencies import get_async_db, get_db

from .exceptions import ProjectNotFoundException
from .schemas import ProjectCreate, ProjectResponse, ProjectUpdate
from .service import create_project, get_project, delete_project, update_project, get_projects_for_subject
from .service import (
create_project,
delete_project,
get_project,
get_projects_for_subject,
update_project,
)

router = APIRouter(
prefix="/api/subjects/{subject_id}/projects",
Expand All @@ -16,30 +22,28 @@

@router.get("/", response_model=list[ProjectResponse])
async def list_projects_for_subject(
subject_id: int,
db: AsyncSession = Depends(get_async_db)
subject_id: int, db: AsyncSession = Depends(get_async_db)
):
projects = await get_projects_for_subject(db, subject_id)
return projects


@router.post("/",
response_model=ProjectResponse,
dependencies=[Depends(user_permission_validation)],
status_code=201)
@router.post(
"/",
response_model=ProjectResponse,
dependencies=[Depends(user_permission_validation)],
status_code=201,
)
async def create_project_for_subject(
subject_id: int,
project_in: ProjectCreate,
db: AsyncSession = Depends(get_async_db)
subject_id: int, project_in: ProjectCreate, db: AsyncSession = Depends(get_async_db)
):
project = await create_project(db, project_in, subject_id)
return project


@router.get("/{project_id}", response_model=ProjectResponse)
async def get_project_for_subject(
project_id: int,
db: AsyncSession = Depends(get_async_db)
project_id: int, db: AsyncSession = Depends(get_async_db)
):
project = await get_project(db, project_id)
if not project:
Expand All @@ -49,19 +53,20 @@ async def get_project_for_subject(

@router.delete("/{project_id}", dependencies=[Depends(user_permission_validation)])
async def delete_project_for_subject(
project_id: int,
db: AsyncSession = Depends(get_async_db)
project_id: int, db: AsyncSession = Depends(get_async_db)
):
await delete_project(db, project_id)
return {"message": "Project deleted successfully"}


@router.patch("/{project_id}",
response_model=ProjectResponse,
dependencies=[Depends(user_permission_validation)])
@router.patch(
"/{project_id}",
response_model=ProjectResponse,
dependencies=[Depends(user_permission_validation)],
)
async def patch_project_for_subject(
project_id: int,
project_update: ProjectUpdate,
db: AsyncSession = Depends(get_async_db)
db: AsyncSession = Depends(get_async_db),
):
return await update_project(db, project_id, project_update)
2 changes: 1 addition & 1 deletion backend/src/subject/dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ async def retrieve_subject(
if not subject:
raise SubjectNotFound()

return Subject.model_validate(subject)
return subject


async def retrieve_subjects(
Expand Down
7 changes: 5 additions & 2 deletions backend/src/subject/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ async def get_subjects_by_user(
)
students_subjects = await db.execute(
select(Subject).join(StudentSubject).filter(StudentSubject.c.uid == user_id)

)
return teachers_subjects.scalars().all(), students_subjects.scalars().all()

Expand Down Expand Up @@ -53,11 +54,13 @@ async def create_subject_teacher(db: AsyncSession, subject_id: int, user_id: str

async def delete_subject_teacher(db: AsyncSession, subject_id: int, user_id: str):
await db.execute(
delete(TeacherSubject).filter_by(subject_id=subject_id, uid=user_id)
delete(TeacherSubject)
.where(TeacherSubject.c.subject_id == subject_id)
.where(TeacherSubject.c.uid == user_id)
)
await db.commit()


async def delete_subject(db: AsyncSession, subject_id: int):
await db.execute(delete(Subject).filter_by(id=subject_id))
await db.execute(delete(Subject).where(Subject.id == subject_id))
await db.commit()
2 changes: 1 addition & 1 deletion frontend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<link rel="icon" href="/favicon.png">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Apollo</title>
</head>
Expand Down
Binary file removed frontend/public/favicon.ico
Binary file not shown.
Binary file added frontend/public/favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 2 additions & 3 deletions frontend/src/stores/auth-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,10 @@ export const useAuthStore = defineStore("auth", () => {
return null;
}

function logout() {
async function logout() {
token.value = null;
localStorage.removeItem("token");
// FIXME: somehow does not work
router.replace("/");
await router.replace({ name: "login" });
}
return { token, isLoggedIn, login, logout, setNext };
});
2 changes: 1 addition & 1 deletion frontend/src/views/UserView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import { useAuthStore } from "@/stores/auth-store";
import { ref, onMounted } from "vue";
const apiUrl = import.meta.env.VITE_API_URL;
const user = ref<string>("");
const user = ref<string | null>(null);
const { token, logout } = useAuthStore();
onMounted(async () => {
await fetchUser();
Expand Down

0 comments on commit d2972c0

Please sign in to comment.