diff --git a/backend/secfit/requirements.txt b/backend/secfit/requirements.txt index 9feb375bde1e8fb7befe6c102dd29beeee7c6940..8b27b412c9eabd959f379c66d60bd3c29b753db4 100644 Binary files a/backend/secfit/requirements.txt and b/backend/secfit/requirements.txt differ diff --git a/backend/secfit/users/tests.py b/backend/secfit/users/tests.py index 7ce503c2dd97ba78597f6ff6e4393132753573f6..0b703f37f804d08bddb474c0a2855e71499dbc54 100644 --- a/backend/secfit/users/tests.py +++ b/backend/secfit/users/tests.py @@ -1,3 +1,216 @@ +from django.contrib.auth import get_user_model from django.test import TestCase -# Create your tests here. +from rest_framework.request import Request +from rest_framework.test import APIRequestFactory + +import users.permissions +from users import models +from users.serializers import UserSerializer +from passlib.hash import django_pbkdf2_sha256 + + +class UserSerializerTest(TestCase): + + def setUp(self): + factory = APIRequestFactory() + request = factory.get('/') + + serializer_context = { + 'request': Request(request), + } + + self.user_attributes = { + 'email': 'hawk@hawk.no', + 'username': 'hawky', + 'password': 'hawkyboi', + 'phone_number': '123', + 'country': '123', + 'city': '123', + 'street_address': '123' + } + + self.user = models.User.objects.create(**self.user_attributes) + self.serializer = UserSerializer(data=self.user_attributes, instance=self.user, context=serializer_context) + self.serializer.is_valid() + + def test_validate_password(self): + user_serializer = self.serializer + + password = user_serializer.get_initial().get("password") + password1 = user_serializer.get_initial().get("password1") # password =/= password1 + + # The validate_password class validates the first password field against itself, meaning it does not valid + # the 2 inputs making it "impossible" to test + self.assertEqual(UserSerializer.validate_password(self.serializer, password), password) + self.assertEqual(UserSerializer.validate_password(self.serializer, password1), password1) + self.assertNotEqual(UserSerializer.validate_password(self.serializer, password), password1) + + def test_create_user(self): + user_serializer = UserSerializer() + + expected = { + 'username': 'hawk', + 'email': 'hawkyy@hawk.hawk', + 'password': 'hawk', + 'phone_number': '12345678', + 'country': 'Norway', + 'city': 'Leknes', + 'street_address': '107' + } + + actual = UserSerializer.create(user_serializer, expected) + self.assertEquals(expected.get('username'), actual.username, "assert username are equal") + self.assertEquals(expected.get('email'), actual.email, "assert email are equal") + self.assertTrue(django_pbkdf2_sha256.verify(expected.get("password"), actual.password), + "Password is hashed correctly") + self.assertEquals(expected.get('phone_number'), actual.phone_number, "assert phone number are equal") + self.assertEquals(expected.get('country'), actual.country, "assert country are equal") + self.assertEquals(expected.get('city'), actual.city, "assert city are equal") + self.assertEquals(expected.get('street_address'), actual.street_address, "assert street address are equal") + + +class PermissionsTest(TestCase): + + def test_IsCurrentUser(self): + + class test_request: + def __init__(self, method): + self.method = method + self.user = get_user_model().objects.create_user("test", "testpass") + + test_request = test_request("POST") + + is_CurrentUser = users.permissions.IsCurrentUser() + + self.assertTrue( + is_CurrentUser.has_object_permission( + test_request, + None, + test_request.user), + "has_object_permission assert test_request and created user as parameters return True") + + self.assertFalse( + is_CurrentUser.has_object_permission( + test_request, + None, + "different_user"), + "has_object_permission assert test_request and random string as parameters return false") + + def test_IsAthlete(self): + + class test_request: + def __init__(self, method, username, athlete): + self.method = method + self.user = get_user_model().objects.create_user(username, "testpass") + if athlete: + self.data = {"athlete": "hawk/" + str(self.user.id) + "/workout"} + else: + self.data = {} + + test_request_1 = test_request("GET", "user1", False) + + is_Athlete = users.permissions.IsAthlete() + + self.assertTrue( + is_Athlete.has_permission(test_request_1, None), + "has permission to GET athlete data returns True") + + test_request_2 = test_request("POST", "user2", False) + + self.assertFalse( + is_Athlete.has_permission(test_request_2, None), + "Has permission to POST athlete data, returns false" + ) + + test_request_3 = test_request("POST", "user3", True) + + # The permission class checks string value to int, which means it is always false + hasPermission = is_Athlete.has_permission(test_request_3, None) + self.assertFalse( + hasPermission, + "Has permission to POST athlete data, returns true" + ) + + class test_obj: + def __init__(self, athlete): + self.athlete = athlete + + obj = test_obj(test_request_3.user) + obj2 = test_obj("random_user") + + self.assertTrue( + is_Athlete.has_object_permission(test_request_3, None, obj), + "assert request user and obj has the same user as obj athlete returns True" + ) + + self.assertFalse( + is_Athlete.has_object_permission(test_request_3, None, obj2), + "assert requesting user and obj with random data returns False" + ) + + def test_IsCoach(self): + + class test_request: + def __init__(self, method, username, athlete, coach): + self.method = method + self.user = get_user_model().objects.create_user(username, "testpass") + + if coach: + self.user.coach = get_user_model().objects.get(pk=self.user.id) + self.user.save() + + if athlete: + self.data = {"athlete": "hawk/" + str(self.user.id) + "/workout"} + else: + self.data = {} + + test_request_1 = test_request("GET", "user1", False, False) + + is_Coach = users.permissions.IsCoach() + + self.assertTrue( + is_Coach.has_permission(test_request_1, None), + "has_permission assert GET request returns True") + + test_request_2 = test_request("POST", "user2", False, False) + + self.assertFalse( + is_Coach.has_permission(test_request_2, None), + "has_permission assert POST request without athlete data returns False" + ) + + test_request_3 = test_request("POST", "user3", True, True) + + self.assertTrue( + is_Coach.has_permission(test_request_3, None), + "has_permission assert POST request with athlete data and correct id returns True" + ) + + test_request_4 = test_request("POST", "user4", True, False) + + self.assertFalse( + is_Coach.has_permission(test_request_4, None), + "has_permission assert POST request with athlete data and invalid id returns False" + ) + + class test_obj: + def __init__(self, athlete): + class test_athlete: + def __init__(self, coach): + self.coach = coach + + self.athlete = test_athlete(athlete) + + obj = test_obj(test_request_3.user) + obj2 = test_obj("random_user") + + self.assertTrue( + is_Coach.has_object_permission(test_request_3, None, obj), + "assert requesting user and obj has the same user as obj athlete returns True" + ) + + self.assertFalse( + is_Coach.has_object_permission(test_request_3, None, obj2), + "assert requesting user and obj has the same user as obj athlete returns True" + ) diff --git a/frontend/www/scripts/workout.js b/frontend/www/scripts/workout.js index 012c019966026e68e39e0a946ba405f83cd9ea95..0b32d386930c518d696fb80b887b7ac8efab4a05 100644 --- a/frontend/www/scripts/workout.js +++ b/frontend/www/scripts/workout.js @@ -335,18 +335,22 @@ function removeAthleteRow(event) { event.currentTarget.parentElement.remove(); } -async function displayCurrentRoster() { +async function displayCurrentRoster(currentUser, workoutid) { let templateFilledAthlete = document.querySelector("#template-filled-member"); let templateEmptyAthlete = document.querySelector("#template-empty-member"); let controls = document.querySelector("#controls"); - - /*let currentUser = await getCurrentUser(); - for (let athleteUrl of currentUser.athletes) { + let body = {workout: `${HOST}/api/workouts/${workoutid}/`}; + console.log(body); + console.log(workout); + + + + for (let member of workout.members) { let response = await sendRequest("GET", athleteUrl); let athlete = await response.json(); createFilledRow(templateFilledAthlete, athlete.username, controls, false); - }*/ + } let emptyClone = templateEmptyAthlete.content.cloneNode(true); let emptyDiv = emptyClone.querySelector("div"); @@ -371,7 +375,6 @@ window.addEventListener("DOMContentLoaded", async () => { galleryButton.addEventListener("click", handleGalleryButtonClick); - await displayCurrentRoster(); const urlParams = new URLSearchParams(window.location.search); let currentUser = await getCurrentUser(); @@ -381,13 +384,15 @@ window.addEventListener("DOMContentLoaded", async () => { let workoutData = await retrieveWorkout(id); await retrieveComments(id); - if (workoutData["owner"] == currentUser.url) { + if (workoutData["owner"] == currentUser.url || workoutData["members"].includes(currentUser.url)) { editWorkoutButton.classList.remove("hide"); editWorkoutButton.addEventListener("click", handleEditWorkoutButtonClick); deleteWorkoutButton.addEventListener("click", (async (id) => await deleteWorkout(id)).bind(undefined, id)); okWorkoutButton.addEventListener("click", (async (id) => await updateWorkout(id)).bind(undefined, id)); postCommentButton.addEventListener("click", (async (id) => await createComment(id)).bind(undefined, id)); divCommentRow.className = divCommentRow.className.replace(" hide", ""); + await displayCurrentRoster(currentUser, id); + } } else { await createBlankExercise();