Skip to content
This repository has been archived by the owner on Jan 22, 2025. It is now read-only.

Commit

Permalink
Merge branch 'development' into enhancement/frontend/navbar_link
Browse files Browse the repository at this point in the history
  • Loading branch information
warreprovoost authored Apr 28, 2024
2 parents 6fb631d + eb6767c commit 4c46188
Show file tree
Hide file tree
Showing 21 changed files with 393 additions and 192 deletions.
1 change: 1 addition & 0 deletions backend/project/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def create_app():
"""

app = Flask(__name__)
app.config['PROPAGATE_EXCEPTIONS'] = True
app.config["JWT_COOKIE_SECURE"] = True
app.config["JWT_COOKIE_CSRF_PROTECT"] = True
app.config["JWT_TOKEN_LOCATION"] = ["cookies"]
Expand Down
61 changes: 25 additions & 36 deletions backend/project/endpoints/authentication/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,17 @@
from flask import Blueprint, request, redirect, abort, make_response
from flask_jwt_extended import create_access_token, set_access_cookies
from flask_restful import Resource, Api
from sqlalchemy.exc import SQLAlchemyError

from project import db

from project.models.user import User, Role
from project.models.user import Role
from project.utils.user import get_or_make_user

auth_bp = Blueprint("auth", __name__)
auth_api = Api(auth_bp)

load_dotenv()
API_URL = getenv("API_HOST")
AUTH_METHOD = getenv("AUTH_METHOD")
AUTHENTICATION_URL = getenv("AUTHENTICATION_URL")
TEST_AUTHENTICATION_URL = getenv("TEST_AUTHENTICATION_URL")
CLIENT_ID = getenv("CLIENT_ID")
CLIENT_SECRET = getenv("CLIENT_SECRET")
HOMEPAGE_URL = getenv("HOMEPAGE_URL")
Expand Down Expand Up @@ -57,37 +55,11 @@ def microsoft_authentication():
timeout=5)
except TimeoutError:
return {"message":"Request to Microsoft timed out"}, 500
if not profile_res or profile_res.status_code != 200:
if profile_res is None or profile_res.status_code != 200:
abort(make_response(({"message":
"An error occured while trying to authenticate your access token"},
500)))
auth_user_id = profile_res.json()["id"]
try:
user = db.session.get(User, auth_user_id)
except SQLAlchemyError:
db.session.rollback()
abort(make_response(({"message":
"An unexpected database error occured while fetching the user"},
500)))

if not user:
role = Role.STUDENT
if profile_res.json()["jobTitle"] is not None:
role = Role.TEACHER

# add user if not yet in database
try:
new_user = User(uid=auth_user_id,
role=role,
display_name=profile_res.json()["displayName"])
db.session.add(new_user)
db.session.commit()
user = new_user
except SQLAlchemyError:
db.session.rollback()
abort(make_response(({"message":
"""An unexpected database error occured
while creating the user during authentication"""}, 500)))
user = get_or_make_user(profile_res)
resp = redirect(HOMEPAGE_URL, code=303)
additional_claims = {"is_teacher":user.role == Role.TEACHER,
"is_admin":user.role == Role.ADMIN}
Expand All @@ -104,10 +76,27 @@ def test_authentication():
"""
code = request.args.get("code")
if code is None:
return {"message":"Not yet"}, 500
profile_res = requests.get(AUTHENTICATION_URL, headers={"Authorization":f"{code}"}, timeout=5)
abort(make_response(({"message":
"No code"},
400)))
profile_res = requests.get(TEST_AUTHENTICATION_URL,
headers={"Authorization":f"{code}"},
timeout=5)
if profile_res is None:
abort(make_response(({"message":
"An error occured while trying to authenticate your access token"},
500)))
if profile_res.status_code != 200:
abort(make_response(({"message":
"Something was wrong with your code"},
401)))
user = get_or_make_user(profile_res)
resp = redirect(HOMEPAGE_URL, code=303)
set_access_cookies(resp, create_access_token(identity=profile_res.json()["id"]))
additional_claims = {"is_teacher":user.role == Role.TEACHER,
"is_admin":user.role == Role.ADMIN}
set_access_cookies(resp,
create_access_token(identity=profile_res.json()["id"],
additional_claims=additional_claims))
return resp


Expand Down
6 changes: 5 additions & 1 deletion backend/project/utils/submissions/evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,12 @@
from project.db_in import db
from project.models.submission import Submission


EVALUATORS_FOLDER = path.join(path.dirname(__file__), "evaluators")

DOCKER_IMAGE_MAPPER = {
"PYTHON": path.join(path.dirname(__file__), "evaluators", "python"),
"PYTHON": path.join(EVALUATORS_FOLDER, "python"),
"GENERAL": path.join(EVALUATORS_FOLDER, "general")
}


Expand Down
32 changes: 32 additions & 0 deletions backend/project/utils/submissions/evaluators/general/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Use Ubuntu as the base image
FROM ubuntu:latest

# Avoiding user interaction with tzdata, etc.
ENV DEBIAN_FRONTEND=noninteractive

# Update and install basic dependencies
RUN apt-get update && apt-get install -y \
software-properties-common \
build-essential \
curl \
wget \
git \
cmake # Adding CMake for C/C++ project management

# Install Python
RUN apt-get install -y python3 python3-pip

# Install Node.js
RUN apt-get install -y nodejs
RUN apt-get install -y npm

# Install Java
RUN apt-get install -y openjdk-11-jdk

# Install Ruby
RUN apt-get install -y ruby-full

# Clean up to reduce the image size
RUN apt-get clean && rm -rf /var/lib/apt/lists/*

COPY . .
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash

bash /tests/run_test.sh
45 changes: 44 additions & 1 deletion backend/project/utils/user.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,51 @@
"""Utility functions for the user model"""

from typing import Tuple
from requests import Response

from flask import abort, make_response

from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.orm import Session
from project.models.user import User

from project import db
from project.models.user import User, Role

def get_or_make_user(profile_res: Response) -> User:
"""
Function to create a new User in the database or return
the user associated with the profile_res received from authentication
Returns either a database error or the User data.
"""
auth_user_id = profile_res.json()["id"]
try:
user = db.session.get(User, auth_user_id)
except SQLAlchemyError:
db.session.rollback()
abort(make_response(({"message":
"An unexpected database error occured while fetching the user"},
500)))

if not user:
role = Role.STUDENT
if profile_res.json()["jobTitle"] is not None:
role = Role.TEACHER

# add user if not yet in database
try:
new_user = User(uid=auth_user_id,
role=role,
display_name=profile_res.json()["displayName"])
db.session.add(new_user)
db.session.commit()
user = new_user
except SQLAlchemyError:
db.session.rollback()
abort(make_response(({"message":
"""An unexpected database error occured
while creating the user during authentication"""}, 500)))
return user

def is_valid_user(session: Session, uid: any) -> Tuple[bool, str]:
"""Check if a uid is valid
Expand Down
4 changes: 2 additions & 2 deletions backend/run_tests.sh
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
#!/bin/bash

# Run Docker Compose to build and start the services, and capture the exit code from the test runner service
docker-compose -f tests.yaml up --build --exit-code-from test-runner
docker compose -f tests.yaml up --build --exit-code-from test-runner

# Store the exit code in a variable
exit_code=$?

# After the tests are finished, stop and remove the containers
docker-compose -f tests.yaml down
docker compose -f tests.yaml down

# Check the exit code to determine whether the tests passed or failed
if [ $exit_code -eq 0 ]; then
Expand Down
48 changes: 32 additions & 16 deletions backend/test_auth_server/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,74 +11,90 @@
token_dict = {
"teacher1":{
"id":"Gunnar",
"jobTitle":"teacher"
"jobTitle":"teacher",
"displayName":"Gunnar Brinckmann"
},
"teacher2":{
"id":"Bart",
"jobTitle":"teacher"
"jobTitle":"teacher",
"displayName":"Bart Bart"
},
"student1":{
"id":"w_student",
"jobTitle":None
"jobTitle":None,
"displayName":"William Student"
},
"student01":{
"id":"student01",
"jobTitle":None
"jobTitle":None,
"displayName":"Student Nul Een"
},
"course_admin1":{
"id":"Rien",
"jobTitle":None
"jobTitle":None,
"displayName":"Rien Admien"
},
"del_user":{
"id":"del",
"jobTitle":None
"jobTitle":None,
"displayName":"Peter Deleter"
},
"ad3_teacher":{
"id":"brinkmann",
"jobTitle0":"teacher"
"jobTitle0":"teacher",
"displayName":"Gunnar Brinckmann"
},
"student02":{
"id":"student02",
"jobTitle":None
"jobTitle":None,
"displayName":"Student Nul Twee"
},
"admin1":{
"id":"admin_person",
"jobTitle":"admin"
"jobTitle":"admin",
"displayName":"Admin Man"
},
# Lowest authorized user to test login requirement
"login": {
"id": "login",
"jobTitle": None
"jobTitle": None,
"displayName":"Lotte Login"
},
# Student authorization access, associated with valid_...
"student": {
"id": "student",
"jobTitle": None
"jobTitle": None,
"displayName":"Student"
},
# Student authorization access, other
"student_other": {
"id": "student_other",
"jobTitle": None
"jobTitle": None,
"displayName":"Student Other"
},
# Teacher authorization access, associated with valid_...
"teacher": {
"id": "teacher",
"jobTitle": "teacher"
"jobTitle": "teacher",
"displayName":"Gieter Teacher"
},
# Teacher authorization access, other
"teacher_other": {
"id": "teacher_other",
"jobTitle": "teacher"
"jobTitle": "teacher",
"displayName":"Teacher Other"
},
# Admin authorization access, associated with valid_...
"admin": {
"id": "admin",
"jobTitle": "admin"
"jobTitle": "admin",
"displayName":"Admin Man"
},
# Admin authorization access, other
"admin_other": {
"id": "admin_other",
"jobTitle": "admin"
"jobTitle": "admin",
"displayName":"Admin Woman"
}
}

Expand Down
2 changes: 1 addition & 1 deletion backend/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ services:
POSTGRES_PASSWORD: test_password
POSTGRES_DB: test_database
API_HOST: http://api_is_here
AUTHENTICATION_URL: http://auth-server:5001 # Use the service name defined in Docker Compose
TEST_AUTHENTICATION_URL: http://auth-server:5001 # Use the service name defined in Docker Compose
AUTH_METHOD: test
JWT_SECRET_KEY: Test123
UPLOAD_URL: /data/assignments
Expand Down
16 changes: 8 additions & 8 deletions backend/tests/endpoints/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from flask.testing import FlaskClient
from sqlalchemy.orm import Session

from tests.utils.auth_login import get_csrf_from_login
from project.models.user import User,Role
from project.models.course import Course
from project.models.course_relation import CourseStudent, CourseAdmin
Expand All @@ -28,12 +29,12 @@ def data_map(course: Course) -> dict[str, Any]:
def auth_test(request: FixtureRequest, client: FlaskClient, data_map: dict[str, Any]) -> tuple:
"""Add concrete test data to auth"""
# endpoint, method, token, allowed
endpoint, method, *other = request.param
endpoint, method, token, *other = request.param

for k, v in data_map.items():
endpoint = endpoint.replace(k, str(v))

return endpoint, getattr(client, method), *other
csrf = get_csrf_from_login(client, token)
return endpoint, getattr(client, method), csrf, *other



Expand All @@ -47,14 +48,13 @@ def data_field_type_test(

for key, value in data_map.items():
endpoint = endpoint.replace(key, str(value))

for key, value in data.items():
if isinstance(value, list):
data[key] = [data_map.get(v,v) for v in value]
elif value in data_map.keys():
data[key] = data_map[value]

return endpoint, getattr(client, method), token, data
csrf = get_csrf_from_login(client, token)
return endpoint, getattr(client, method), csrf, data



Expand All @@ -66,8 +66,8 @@ def query_parameter_test(request: FixtureRequest, client: FlaskClient, data_map:

for key, value in data_map.items():
endpoint = endpoint.replace(key, str(value))

return endpoint, getattr(client, method), token, wrong_parameter
csrf = get_csrf_from_login(client, token)
return endpoint, getattr(client, method), csrf, wrong_parameter



Expand Down
Loading

0 comments on commit 4c46188

Please sign in to comment.