diff --git a/src/main/resources/templates/error/5xx.html b/src/main/resources/templates/error/5xx.html new file mode 100644 index 0000000..77563b2 --- /dev/null +++ b/src/main/resources/templates/error/5xx.html @@ -0,0 +1,24 @@ + + + + + +
+
+
+
+ +
+
+

Error code

+
+ Error message +
+
+
+
+
+ + -- 2.51.2 From d726d1b2f0e1f5286485bbca8071595a6707ba78 Mon Sep 17 00:00:00 2001 From: Julien WITTOUCK Date: Mon, 4 Sep 2023 15:27:01 +0200 Subject: [PATCH 2/6] =?UTF-8?q?=E2=9C=A8=20:=20add=20custom=20exception=20?= =?UTF-8?q?class?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gitlab/classrooms/gitlab/GitLabException.java | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/main/java/fr/univ_lille/gitlab/classrooms/gitlab/GitLabException.java diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/gitlab/GitLabException.java b/src/main/java/fr/univ_lille/gitlab/classrooms/gitlab/GitLabException.java new file mode 100644 index 0000000..b1c50a8 --- /dev/null +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/gitlab/GitLabException.java @@ -0,0 +1,9 @@ +package fr.univ_lille.gitlab.classrooms.gitlab; + +import org.gitlab4j.api.GitLabApiException; + +public class GitLabException extends Exception { + public GitLabException(String message, GitLabApiException cause) { + super(message, cause); + } +} -- 2.51.2 From 14619d5585916bd29cec1caf24bfbfdde1d0aa28 Mon Sep 17 00:00:00 2001 From: Julien WITTOUCK Date: Mon, 4 Sep 2023 15:28:35 +0200 Subject: [PATCH 3/6] =?UTF-8?q?=E2=9C=A8=20:=20do=20not=20create=20projet?= =?UTF-8?q?=20if=20it=20already=20exists?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit when accepting assignment twice --- .../assignments/AssignmentController.java | 3 +- .../assignments/AssignmentService.java | 3 +- .../assignments/AssignmentServiceImpl.java | 3 +- .../gitlab/classrooms/gitlab/Gitlab.java | 2 +- .../gitlab/classrooms/gitlab/GitlabImpl.java | 43 ++++++-- .../AssignmentServiceImplTest.java | 5 +- .../classrooms/gitlab/GitlabImplTest.java | 103 ++++++++++++++++-- 7 files changed, 140 insertions(+), 22 deletions(-) diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/AssignmentController.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/AssignmentController.java index 0be35ce..ad9285f 100644 --- a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/AssignmentController.java +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/AssignmentController.java @@ -1,6 +1,7 @@ package fr.univ_lille.gitlab.classrooms.assignments; import fr.univ_lille.gitlab.classrooms.classrooms.ClassroomService; +import fr.univ_lille.gitlab.classrooms.gitlab.GitLabException; import fr.univ_lille.gitlab.classrooms.gitlab.Gitlab; import fr.univ_lille.gitlab.classrooms.quiz.QuizService; import fr.univ_lille.gitlab.classrooms.users.ClassroomUser; @@ -85,7 +86,7 @@ class AssignmentController { try { this.assignmentService.acceptAssigment(assignment, student); } - catch (GitLabApiException e){ + catch (GitLabApiException | GitLabException e){ LOGGER.log(System.Logger.Level.ERROR, "Could not accept assignment"); throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Could not accept assignment", e); } diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/AssignmentService.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/AssignmentService.java index ff3f1f1..60c8455 100644 --- a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/AssignmentService.java +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/AssignmentService.java @@ -1,6 +1,7 @@ package fr.univ_lille.gitlab.classrooms.assignments; import fr.univ_lille.gitlab.classrooms.classrooms.Classroom; +import fr.univ_lille.gitlab.classrooms.gitlab.GitLabException; import fr.univ_lille.gitlab.classrooms.users.ClassroomUser; import jakarta.transaction.Transactional; import org.gitlab4j.api.GitLabApiException; @@ -13,7 +14,7 @@ public interface AssignmentService { Optional getAssignment(UUID id); @Transactional - void acceptAssigment(Assignment assignment, ClassroomUser student) throws GitLabApiException; + void acceptAssigment(Assignment assignment, ClassroomUser student) throws GitLabApiException, GitLabException; List getAssignmentResults(Assignment assignment); diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/AssignmentServiceImpl.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/AssignmentServiceImpl.java index cdfe497..66840f8 100644 --- a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/AssignmentServiceImpl.java +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/AssignmentServiceImpl.java @@ -2,6 +2,7 @@ package fr.univ_lille.gitlab.classrooms.assignments; import fr.univ_lille.gitlab.classrooms.classrooms.Classroom; import fr.univ_lille.gitlab.classrooms.classrooms.ClassroomService; +import fr.univ_lille.gitlab.classrooms.gitlab.GitLabException; import fr.univ_lille.gitlab.classrooms.gitlab.Gitlab; import fr.univ_lille.gitlab.classrooms.quiz.QuizService; import fr.univ_lille.gitlab.classrooms.users.ClassroomUser; @@ -43,7 +44,7 @@ class AssignmentServiceImpl implements AssignmentService { @Override @Transactional - public void acceptAssigment(Assignment assignment, ClassroomUser student) throws GitLabApiException { + public void acceptAssigment(Assignment assignment, ClassroomUser student) throws GitLabApiException, GitLabException { assignment.accept(student); this.assignmentRepository.save(assignment); diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/gitlab/Gitlab.java b/src/main/java/fr/univ_lille/gitlab/classrooms/gitlab/Gitlab.java index 62d4467..dc71230 100644 --- a/src/main/java/fr/univ_lille/gitlab/classrooms/gitlab/Gitlab.java +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/gitlab/Gitlab.java @@ -44,5 +44,5 @@ public interface Gitlab { * @param student the student who accepted the assignment * @return the Gitlab Project */ - Project createProject(ExerciseAssignment exerciseAssignment, ClassroomUser student) throws GitLabApiException; + Project createProject(ExerciseAssignment exerciseAssignment, ClassroomUser student) throws GitLabApiException, GitLabException; } diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/gitlab/GitlabImpl.java b/src/main/java/fr/univ_lille/gitlab/classrooms/gitlab/GitlabImpl.java index 4bfa963..8f2683c 100644 --- a/src/main/java/fr/univ_lille/gitlab/classrooms/gitlab/GitlabImpl.java +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/gitlab/GitlabImpl.java @@ -86,20 +86,26 @@ class GitlabImpl implements Gitlab { } @Override - public Project createProject(ExerciseAssignment exerciseAssignment, ClassroomUser student) throws GitLabApiException { + public Project createProject(ExerciseAssignment exerciseAssignment, ClassroomUser student) throws GitLabApiException, GitLabException { var classroom = exerciseAssignment.getClassroom(); var teacher = classroom.getTeacher(); // get a gitlab api client ith the teacher's rights var teacherGitlabApi = this.gitlabApiFactory.userGitlabApi(teacher); - Project project; + Project project = null; + // get gitlab group info + var group = teacherGitlabApi.getGroupApi().getGroup(exerciseAssignment.getGitlabGroupId()); var projectName = exerciseAssignment.getName() + "-" + student.getName(); - if (exerciseAssignment.getGitlabRepositoryTemplateId() != null && !exerciseAssignment.getGitlabRepositoryTemplateId().isBlank()) { - // get gitlab group info - var group = teacherGitlabApi.getGroupApi().getGroup(exerciseAssignment.getGitlabGroupId()); + try { + project = teacherGitlabApi.getProjectApi().getProject(group.getFullPath(), projectName); + } + catch (GitLabApiException ignore){ + // ignoring the 404 exception, meaning that the project doesn't exists yet + } + if (project == null && (exerciseAssignment.getGitlabRepositoryTemplateId() != null && !exerciseAssignment.getGitlabRepositoryTemplateId().isBlank())) { var path = slugify(projectName); // fork the template project project = teacherGitlabApi.getProjectApi().forkProject( @@ -109,16 +115,37 @@ class GitlabImpl implements Gitlab { projectName); // remove the fork link teacherGitlabApi.getProjectApi().deleteForkedFromRelationship(project.getId()); - } else { + } else if (project == null) { // create a blank project var projectParams = new Project() .withName(projectName) - .withNamespaceId(exerciseAssignment.getGitlabGroupId()); + .withNamespaceId(group.getId()); project = teacherGitlabApi.getProjectApi().createProject(projectParams); } + // grant the student access to its project - teacherGitlabApi.getProjectApi().addMember(project.getId(), student.getGitlabUserId(), AccessLevel.MAINTAINER); + this.ensureStudentCanAccessItsProject(teacherGitlabApi, project, student); return project; } + + private void ensureStudentCanAccessItsProject(GitLabApi gitlabApi, Project project, ClassroomUser student) throws GitLabException { + try { + var member = gitlabApi.getProjectApi().getMember(project.getId(), student.getGitlabUserId(), true); + if(member != null){ + // found, student has access + return; + } + } catch (GitLabApiException ignore) { + // ignoring the 404 exception, meaning that the student doesn't have access to its repository + } + // grant the student access to its project + try { + gitlabApi.getProjectApi().addMember(project.getId(), student.getGitlabUserId(), AccessLevel.MAINTAINER); + } catch (GitLabApiException e) { + var message = String.format("Unable to give student %s access to its GitLab project %s", student.getGitlabUserId(), project.getId()); + throw new GitLabException(message, e); + } + + } } diff --git a/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/AssignmentServiceImplTest.java b/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/AssignmentServiceImplTest.java index fa30c31..f2f5d06 100644 --- a/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/AssignmentServiceImplTest.java +++ b/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/AssignmentServiceImplTest.java @@ -2,6 +2,7 @@ package fr.univ_lille.gitlab.classrooms.assignments; import fr.univ_lille.gitlab.classrooms.classrooms.Classroom; import fr.univ_lille.gitlab.classrooms.classrooms.ClassroomService; +import fr.univ_lille.gitlab.classrooms.gitlab.GitLabException; import fr.univ_lille.gitlab.classrooms.gitlab.Gitlab; import fr.univ_lille.gitlab.classrooms.quiz.QuizEntity; import fr.univ_lille.gitlab.classrooms.quiz.QuizService; @@ -50,7 +51,7 @@ class AssignmentServiceImplTest { } @Test - void acceptAssignment_shouldAssociateTheStudentWithTheAssignment_andSave() throws GitLabApiException { + void acceptAssignment_shouldAssociateTheStudentWithTheAssignment_andSave() throws GitLabApiException, GitLabException { var assignment = new QuizAssignment(); var student = new ClassroomUser(); @@ -63,7 +64,7 @@ class AssignmentServiceImplTest { } @Test - void acceptExerciceAssignment_shouldCreateAGitlabProject() throws GitLabApiException { + void acceptExerciceAssignment_shouldCreateAGitlabProject() throws GitLabApiException, GitLabException { var teacher = new ClassroomUser(); var classroom = new Classroom(); diff --git a/src/test/java/fr/univ_lille/gitlab/classrooms/gitlab/GitlabImplTest.java b/src/test/java/fr/univ_lille/gitlab/classrooms/gitlab/GitlabImplTest.java index 3d4452b..f71888b 100644 --- a/src/test/java/fr/univ_lille/gitlab/classrooms/gitlab/GitlabImplTest.java +++ b/src/test/java/fr/univ_lille/gitlab/classrooms/gitlab/GitlabImplTest.java @@ -6,10 +6,7 @@ import fr.univ_lille.gitlab.classrooms.users.ClassroomRole; import fr.univ_lille.gitlab.classrooms.users.ClassroomUser; import org.gitlab4j.api.GitLabApi; import org.gitlab4j.api.GitLabApiException; -import org.gitlab4j.api.models.AccessLevel; -import org.gitlab4j.api.models.Group; -import org.gitlab4j.api.models.GroupParams; -import org.gitlab4j.api.models.Project; +import org.gitlab4j.api.models.*; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Answers; @@ -117,7 +114,7 @@ class GitlabImplTest { } @Test - void createProject_shouldCreateAProject_andGiveAccessToTheStudent() throws GitLabApiException { + void createProject_shouldCreateAProject_andGiveAccessToTheStudent() throws GitLabApiException, GitLabException { var student = new ClassroomUser("luke.skywalker", List.of(ClassroomRole.STUDENT)); student.setGitlabUserId(8L); var teacher = new ClassroomUser("obiwan.kenobi", List.of(ClassroomRole.TEACHER)); @@ -126,6 +123,11 @@ class GitlabImplTest { assignment.setName("Exercice 1"); assignment.setGitlabGroupId(72L); + var group = new Group(); + group.setId(72L); + group.setFullPath("my-group/path"); + when(gitLabApi.getGroupApi().getGroup(72L)).thenReturn(group); + var classroom = new Classroom(); classroom.setTeacher(teacher); classroom.addAssignment(assignment); @@ -134,8 +136,13 @@ class GitlabImplTest { var projectMock = new Project(); projectMock.setId(125L); + // project non existing + when(gitLabApi.getProjectApi().getProject("my-group/path", "Exercice 1-luke.skywalker")).thenThrow(new GitLabApiException("Not Member")); when(gitLabApi.getProjectApi().createProject(any(Project.class))).thenReturn(projectMock); + // no rights on project yet + when(gitLabApi.getProjectApi().getMember(125L, 8L, true)).thenThrow(new GitLabApiException("Not Member")); + gitlab.createProject(assignment, student); var projectCaptor = ArgumentCaptor.forClass(Project.class); @@ -152,7 +159,77 @@ class GitlabImplTest { } @Test - void createProject_withTemplate_shouldForkAProject_andGiveAccessToTheStudent() throws GitLabApiException { + void createProject_shouldNotCreateAProject_ifProjectAlreadyExists() throws GitLabApiException, GitLabException { + var student = new ClassroomUser("luke.skywalker", List.of(ClassroomRole.STUDENT)); + student.setGitlabUserId(8L); + var teacher = new ClassroomUser("obiwan.kenobi", List.of(ClassroomRole.TEACHER)); + + var assignment = new ExerciseAssignment(); + assignment.setName("Exercice 1"); + assignment.setGitlabGroupId(72L); + + var group = new Group(); + group.setId(72L); + group.setFullPath("my-group/path"); + when(gitLabApi.getGroupApi().getGroup(72L)).thenReturn(group); + + var classroom = new Classroom(); + classroom.setTeacher(teacher); + classroom.addAssignment(assignment); + + when(gitlabApiFactory.userGitlabApi(teacher)).thenReturn(gitLabApi); + + // project already exists + var projectMock = new Project(); + projectMock.setId(125L); + when(gitLabApi.getProjectApi().getProject("my-group/path", "Exercice 1-luke.skywalker")).thenReturn(projectMock); + + // no rights on project + when(gitLabApi.getProjectApi().getMember(125L, 8L, true)).thenThrow(new GitLabApiException("Not Member")); + + gitlab.createProject(assignment, student); + + verify(gitLabApi.getProjectApi()).addMember(125L, 8L, AccessLevel.MAINTAINER); + + verifyNoMoreInteractions(gitLabApi.getProjectApi()); + } + + @Test + void createProject_shouldNotCreateAProject_ifProjectAlreadyExistsAndStudentAlreadyHasRights() throws GitLabApiException, GitLabException { + var student = new ClassroomUser("luke.skywalker", List.of(ClassroomRole.STUDENT)); + student.setGitlabUserId(8L); + var teacher = new ClassroomUser("obiwan.kenobi", List.of(ClassroomRole.TEACHER)); + + var assignment = new ExerciseAssignment(); + assignment.setName("Exercice 1"); + assignment.setGitlabGroupId(72L); + + var group = new Group(); + group.setId(72L); + group.setFullPath("my-group/path"); + when(gitLabApi.getGroupApi().getGroup(72L)).thenReturn(group); + + var classroom = new Classroom(); + classroom.setTeacher(teacher); + classroom.addAssignment(assignment); + + when(gitlabApiFactory.userGitlabApi(teacher)).thenReturn(gitLabApi); + + // project already exists + var projectMock = new Project(); + projectMock.setId(125L); + when(gitLabApi.getProjectApi().getProject("my-group/path", "Exercice 1-luke.skywalker")).thenReturn(projectMock); + + // rights on project + when(gitLabApi.getProjectApi().getMember(125L, 8L, true)).thenReturn(new Member()); + + gitlab.createProject(assignment, student); + + verifyNoMoreInteractions(gitLabApi.getProjectApi()); + } + + @Test + void createProject_withTemplate_shouldForkAProject_andGiveAccessToTheStudent() throws GitLabApiException, GitLabException { var student = new ClassroomUser("luke.skywalker", List.of(ClassroomRole.STUDENT)); student.setGitlabUserId(8L); var teacher = new ClassroomUser("obiwan.kenobi", List.of(ClassroomRole.TEACHER)); @@ -162,6 +239,11 @@ class GitlabImplTest { assignment.setGitlabGroupId(72L); assignment.setGitlabRepositoryTemplateId("12"); + var group = new Group(); + group.setId(72L); + group.setFullPath("my-group/path"); + when(gitLabApi.getGroupApi().getGroup(72L)).thenReturn(group); + var classroom = new Classroom(); classroom.setTeacher(teacher); classroom.addAssignment(assignment); @@ -170,11 +252,16 @@ class GitlabImplTest { var projectMock = new Project(); projectMock.setId(125L); - when(gitLabApi.getProjectApi().forkProject("12", null, "Exercice_2_-_Template-luke.skywalker", "Exercice 2 - Template-luke.skywalker")).thenReturn(projectMock); + // project non existing + when(gitLabApi.getProjectApi().getProject("my-group/path", "Exercice 2 - Template-luke.skywalker")).thenThrow(new GitLabApiException("Not Member")); + when(gitLabApi.getProjectApi().forkProject("12", "my-group/path", "Exercice_2_-_Template-luke.skywalker", "Exercice 2 - Template-luke.skywalker")).thenReturn(projectMock); + + // no rights on project + when(gitLabApi.getProjectApi().getMember(125L, 8L, true)).thenThrow(new GitLabApiException("Not Member")); gitlab.createProject(assignment, student); - verify(gitLabApi.getProjectApi()).forkProject("12", null, "Exercice_2_-_Template-luke.skywalker", "Exercice 2 - Template-luke.skywalker"); + verify(gitLabApi.getProjectApi()).forkProject("12", "my-group/path", "Exercice_2_-_Template-luke.skywalker", "Exercice 2 - Template-luke.skywalker"); verify(gitLabApi.getProjectApi()).deleteForkedFromRelationship(125L); verify(gitLabApi.getProjectApi()).addMember(125L, 8L, AccessLevel.MAINTAINER); -- 2.51.2 From 76eb04ad9f2bb43966eaf3db9c0377f2399590e2 Mon Sep 17 00:00:00 2001 From: Julien WITTOUCK Date: Mon, 4 Sep 2023 15:43:03 +0200 Subject: [PATCH 4/6] =?UTF-8?q?=F0=9F=90=9B=20:=20do=20not=20create=20Stud?= =?UTF-8?q?entExerciseAssignment=20if=20already=20existing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../assignments/AssignmentServiceImpl.java | 10 ++++-- .../StudentAssignmentRepository.java | 2 ++ .../AssignmentServiceImplTest.java | 35 +++++++++++++++++++ 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/AssignmentServiceImpl.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/AssignmentServiceImpl.java index 66840f8..2b7302d 100644 --- a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/AssignmentServiceImpl.java +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/AssignmentServiceImpl.java @@ -51,7 +51,9 @@ class AssignmentServiceImpl implements AssignmentService { if (assignment instanceof ExerciseAssignment exerciseAssignment) { // create the project in gitlab var project = gitlab.createProject(exerciseAssignment, student); - + if (this.studentAssignmentRepository.existsByAssignmentAndStudent(exerciseAssignment, student)) { + return; + } // create the student exercise assignment var studentExercise = new StudentExerciseAssignment(); studentExercise.setAssignment(exerciseAssignment); @@ -59,8 +61,10 @@ class AssignmentServiceImpl implements AssignmentService { studentExercise.setGitlabProjectId(project.getId()); studentExercise.setGitlabProjectUrl(project.getWebUrl()); this.studentAssignmentRepository.save(studentExercise); - } - else if (assignment instanceof QuizAssignment quizAssignment) { + } else if (assignment instanceof QuizAssignment quizAssignment) { + if (this.studentAssignmentRepository.existsByAssignmentAndStudent(quizAssignment, student)) { + return; + } // create the student quiz assignment var studentExercise = new StudentQuizAssignment(); studentExercise.setAssignment(quizAssignment); diff --git a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/StudentAssignmentRepository.java b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/StudentAssignmentRepository.java index 5e50f88..638b4a2 100644 --- a/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/StudentAssignmentRepository.java +++ b/src/main/java/fr/univ_lille/gitlab/classrooms/assignments/StudentAssignmentRepository.java @@ -10,6 +10,8 @@ import java.util.UUID; interface StudentAssignmentRepository extends JpaRepository { List findAllByAssignment(Assignment assignment); + boolean existsByAssignmentAndStudent(Assignment assignment, ClassroomUser student); + StudentAssignment findByAssignmentAndStudent(Assignment assignment, ClassroomUser student); List findByAssignmentClassroomAndStudent(Classroom classroom, ClassroomUser student); diff --git a/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/AssignmentServiceImplTest.java b/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/AssignmentServiceImplTest.java index f2f5d06..1a9813f 100644 --- a/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/AssignmentServiceImplTest.java +++ b/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/AssignmentServiceImplTest.java @@ -63,6 +63,19 @@ class AssignmentServiceImplTest { verify(assignmentRepository).save(assignment); } + @Test + void acceptAssignment_shouldDoNothing_ifQuizAssignmentIsAlreadyAccepted() throws GitLabApiException, GitLabException { + var assignment = new QuizAssignment(); + + var student = new ClassroomUser(); + + when(studentAssignmentRepository.existsByAssignmentAndStudent(assignment, student)).thenReturn(true); + + this.assignmentService.acceptAssigment(assignment, student); + + verifyNoMoreInteractions(studentAssignmentRepository); + } + @Test void acceptExerciceAssignment_shouldCreateAGitlabProject() throws GitLabApiException, GitLabException { var teacher = new ClassroomUser(); @@ -98,6 +111,28 @@ class AssignmentServiceImplTest { assertThat(studentExercise.getGitlabProjectUrl()).isEqualTo("https://gitlab.univ-lille.fr/gitlab-classroom"); } + @Test + void acceptAssignment_shouldDoNothing_ifExerciseAssignmentIsAlreadyAccepted() throws GitLabApiException, GitLabException { + var teacher = new ClassroomUser(); + + var classroom = new Classroom(); + classroom.setTeacher(teacher); + + var assignment = new ExerciseAssignment(); + assignment.setName("Exercice 1"); + assignment.setGitlabGroupId(12L); + classroom.addAssignment(assignment); + + var student = new ClassroomUser(); + student.setName("luke.skywalker"); + + when(studentAssignmentRepository.existsByAssignmentAndStudent(assignment, student)).thenReturn(true); + + this.assignmentService.acceptAssigment(assignment, student); + + verifyNoMoreInteractions(studentAssignmentRepository); + } + @Test void createQuizAssignment_shouldAssociateTheAssignmentWithTheQuiz_andSaveTheClassroom(){ var quiz = new QuizEntity(); -- 2.51.2 From 95b43f2224a2dd16e684dccfa8668dfea1bada30 Mon Sep 17 00:00:00 2001 From: Julien WITTOUCK Date: Mon, 4 Sep 2023 15:55:18 +0200 Subject: [PATCH 5/6] =?UTF-8?q?=E2=9C=85=20:=20show=20error=20when=20accep?= =?UTF-8?q?ting=20assignment?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../assignments/AssignmentControllerMVCTest.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/AssignmentControllerMVCTest.java b/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/AssignmentControllerMVCTest.java index b72cf95..fabff56 100644 --- a/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/AssignmentControllerMVCTest.java +++ b/src/test/java/fr/univ_lille/gitlab/classrooms/assignments/AssignmentControllerMVCTest.java @@ -2,11 +2,13 @@ package fr.univ_lille.gitlab.classrooms.assignments; import fr.univ_lille.gitlab.classrooms.classrooms.Classroom; import fr.univ_lille.gitlab.classrooms.classrooms.ClassroomService; +import fr.univ_lille.gitlab.classrooms.gitlab.GitLabException; import fr.univ_lille.gitlab.classrooms.gitlab.Gitlab; import fr.univ_lille.gitlab.classrooms.quiz.*; import fr.univ_lille.gitlab.classrooms.users.ClassroomUserService; import fr.univ_lille.gitlab.classrooms.users.WithMockStudent; import fr.univ_lille.gitlab.classrooms.users.WithMockTeacher; +import org.gitlab4j.api.GitLabApiException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -22,8 +24,7 @@ import java.util.UUID; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; @@ -132,6 +133,17 @@ class AssignmentControllerMVCTest { verify(assignmentService).acceptAssigment(any(), any()); } + @Test + @WithMockStudent + void acceptAssignment_shouldShowAnError_whenGitLabException() throws Exception { + doThrow(new GitLabException("Could not create project", new GitLabApiException("500"))).when(this.assignmentService).acceptAssigment(any(), any()); + + mockMvc.perform(post("/assignments/"+ exerciseAssignmentId +"/accept").with(csrf())) + .andExpect(status().is5xxServerError()); + + verify(assignmentService).acceptAssigment(any(), any()); + } + @Test @WithMockTeacher void viewQuizAssignment_shouldShowTheAssignmentResults() throws Exception { -- 2.51.2 From a3d8574651cf0aa118d9157490f45ee3eebbefc5 Mon Sep 17 00:00:00 2001 From: Julien WITTOUCK Date: Mon, 4 Sep 2023 17:31:57 +0200 Subject: [PATCH 6/6] =?UTF-8?q?=F0=9F=94=96=20:=20version=200.0.7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 20 ++++++++++++++++++++ pom.xml | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d5ebbb..4d92f9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,25 @@ # Changelog + +## 0.0.7 (2023-09-04) + +### Added + +- ✅ : show error when accepting assignment [95b43f2] +- ✨ : do not create projet if it already exists [14619d5] +- ✨ : add custom exception class [d726d1b] +- ✨ : add error page for 5XX errors [8224af9] + +### Fixed + +- 🐛 : do not create StudentExerciseAssignment if already existing [76eb04a] + +### Miscellaneous + +- 🔀 : merge branch 'bugfix/existing-projects' into develop [8dfa3a8] +- 🔀 : merge tag '0.0.6' into develop [b210b03] + + ## 0.0.6 (2023-09-01) diff --git a/pom.xml b/pom.xml index 696a0ae..dc64fe7 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ fr.univ-lille gitlab-classrooms - 0.0.6 + 0.0.7 gitlab-classrooms GitLab Classroom is a modest clone of GitHub Classroom, aimed at GitLab.