Skip to content

Commit

Permalink
Programming exercises: Fix an issue with access tokens for team exerc…
Browse files Browse the repository at this point in the history
…ises (#9802)
  • Loading branch information
SimonEntholzer authored Nov 24, 2024
1 parent 31bd52c commit 0fc8adb
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@

import de.tum.cit.aet.artemis.core.domain.User;
import de.tum.cit.aet.artemis.core.exception.AccessForbiddenException;
import de.tum.cit.aet.artemis.exercise.domain.Team;
import de.tum.cit.aet.artemis.exercise.domain.participation.StudentParticipation;
import de.tum.cit.aet.artemis.exercise.repository.TeamRepository;
import de.tum.cit.aet.artemis.programming.domain.ParticipationVCSAccessToken;
import de.tum.cit.aet.artemis.programming.repository.ParticipationVCSAccessTokenRepository;
import de.tum.cit.aet.artemis.programming.repository.ProgrammingExerciseStudentParticipationRepository;
Expand All @@ -25,10 +27,13 @@ public class ParticipationVcsAccessTokenService {

private final ProgrammingExerciseStudentParticipationRepository programmingExerciseStudentParticipationRepository;

private final TeamRepository teamRepository;

public ParticipationVcsAccessTokenService(ParticipationVCSAccessTokenRepository participationVCSAccessTokenRepository,
ProgrammingExerciseStudentParticipationRepository programmingExerciseStudentParticipationRepository) {
ProgrammingExerciseStudentParticipationRepository programmingExerciseStudentParticipationRepository, TeamRepository teamRepository) {
this.participationVcsAccessTokenRepository = participationVCSAccessTokenRepository;
this.programmingExerciseStudentParticipationRepository = programmingExerciseStudentParticipationRepository;
this.teamRepository = teamRepository;
}

/**
Expand All @@ -55,6 +60,7 @@ public ParticipationVCSAccessToken createParticipationVCSAccessToken(User user,
*/
public ParticipationVCSAccessToken findByUserAndParticipationIdOrElseThrow(User user, long participationId) {
var participation = programmingExerciseStudentParticipationRepository.findByIdElseThrow(participationId);
loadTeamStudentsForTeamExercise(participation);
if (participation.isOwnedBy(user)) {
return participationVcsAccessTokenRepository.findByUserIdAndParticipationIdOrElseThrow(user.getId(), participationId);
}
Expand All @@ -73,6 +79,7 @@ public ParticipationVCSAccessToken findByUserAndParticipationIdOrElseThrow(User
public ParticipationVCSAccessToken createVcsAccessTokenForUserAndParticipationIdOrElseThrow(User user, long participationId) {
participationVcsAccessTokenRepository.findByUserIdAndParticipationIdAndThrowIfExists(user.getId(), participationId);
var participation = programmingExerciseStudentParticipationRepository.findByIdElseThrow(participationId);
loadTeamStudentsForTeamExercise(participation);
if (participation.isOwnedBy(user)) {
return createParticipationVCSAccessToken(user, participation);
}
Expand All @@ -81,6 +88,19 @@ public ParticipationVCSAccessToken createVcsAccessTokenForUserAndParticipationId
}
}

/**
* Loads the team students of a participation's team, if it has a team
*
* @param participation the participation which team's students are not loaded yet
*/
private void loadTeamStudentsForTeamExercise(StudentParticipation participation) {
if (participation.getTeam().isPresent()) {
Team team = participation.getTeam().get();
Team teamWithStudents = teamRepository.findWithStudentsByIdElseThrow(team.getId());
participation.getTeam().get().setStudents(teamWithStudents.getStudents());
}
}

/**
* Deletes the token connected to a participation
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ void getAndCreateParticipationVcsAccessTokenByUser() throws Exception {
userTestService.getAndCreateParticipationVcsAccessToken();
}

@Test
@WithMockUser(username = TEST_PREFIX + "student1", roles = "USER")
void getParticipationVcsAccessTokenByUserForTeamExercise() throws Exception {
userTestService.getAndCreateParticipationVcsAccessTokenForTeamExercise();
}

@Test
@WithMockUser(username = TEST_PREFIX + "student1", roles = "USER")
void createAndDeleteUserVcsAccessTokenByUser() throws Exception {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,11 @@
import de.tum.cit.aet.artemis.core.test_repository.UserTestRepository;
import de.tum.cit.aet.artemis.core.util.CourseUtilService;
import de.tum.cit.aet.artemis.core.util.RequestUtilService;
import de.tum.cit.aet.artemis.exercise.domain.ExerciseMode;
import de.tum.cit.aet.artemis.exercise.domain.SubmissionType;
import de.tum.cit.aet.artemis.exercise.domain.Team;
import de.tum.cit.aet.artemis.exercise.repository.ExerciseTestRepository;
import de.tum.cit.aet.artemis.exercise.team.TeamUtilService;
import de.tum.cit.aet.artemis.exercise.test_repository.ParticipationTestRepository;
import de.tum.cit.aet.artemis.exercise.test_repository.SubmissionTestRepository;
import de.tum.cit.aet.artemis.lti.service.LtiService;
Expand Down Expand Up @@ -91,6 +95,9 @@ public class UserTestService {
@Autowired
private UserUtilService userUtilService;

@Autowired
private TeamUtilService teamUtilService;

@Autowired
private CourseUtilService courseUtilService;

Expand Down Expand Up @@ -128,6 +135,9 @@ public class UserTestService {
@Autowired
private SubmissionTestRepository submissionRepository;

@Autowired
private ExerciseTestRepository exerciseTestRepository;

public void setup(String testPrefix, MockDelegate mockDelegate) throws Exception {
this.TEST_PREFIX = testPrefix;
this.mockDelegate = mockDelegate;
Expand Down Expand Up @@ -915,6 +925,36 @@ public void getAndCreateParticipationVcsAccessToken() throws Exception {
participationRepository.deleteById(submission.getParticipation().getId());
}

// Test
public void getAndCreateParticipationVcsAccessTokenForTeamExercise() throws Exception {
User user = userUtilService.getUserByLogin(TEST_PREFIX + "student1");
var course = courseUtilService.addEmptyCourse();
var exercise = programmingExerciseUtilService.addProgrammingExerciseToCourse(course);
exercise.setMode(ExerciseMode.TEAM);
exerciseTestRepository.save(exercise);
courseRepository.save(course);
User tutor1 = userTestRepository.findOneByLogin(TEST_PREFIX + "tutor1").orElseThrow();
Team team = teamUtilService.createTeam(Set.of(user), tutor1, exercise, "team1");

var submission = (ProgrammingSubmission) new ProgrammingSubmission().commitHash("abc").type(SubmissionType.MANUAL).submitted(true);
submission = programmingExerciseUtilService.addProgrammingSubmissionToTeamExercise(exercise, submission, team);

// request existing token
request.get("/api/account/participation-vcs-access-token?participationId=" + submission.getParticipation().getId(), HttpStatus.NOT_FOUND, String.class);

var token = request.putWithResponseBody("/api/account/participation-vcs-access-token?participationId=" + submission.getParticipation().getId(), null, String.class,
HttpStatus.OK);
assertThat(token).isNotNull();

var token2 = request.get("/api/account/participation-vcs-access-token?participationId=" + submission.getParticipation().getId(), HttpStatus.OK, String.class);
assertThat(token2).isEqualTo(token);

submissionRepository.delete(submission);
participationVCSAccessTokenRepository.deleteAll();
participationRepository.deleteById(submission.getParticipation().getId());
teamUtilService.deleteTeam(team);
}

// Test
public void createAndDeleteUserVcsAccessToken() throws Exception {
User user = userUtilService.getUserByLogin(TEST_PREFIX + "student1");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,4 +244,8 @@ public Team createTeam(Set<User> students, User owner, Exercise exercise, String
team.setExercise(exercise);
return teamRepo.saveAndFlush(team);
}

public void deleteTeam(Team team) {
teamRepo.delete(team);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import de.tum.cit.aet.artemis.exam.util.ExamUtilService;
import de.tum.cit.aet.artemis.exercise.domain.InitializationState;
import de.tum.cit.aet.artemis.exercise.domain.SubmissionType;
import de.tum.cit.aet.artemis.exercise.domain.Team;
import de.tum.cit.aet.artemis.exercise.domain.participation.Participation;
import de.tum.cit.aet.artemis.exercise.domain.participation.StudentParticipation;
import de.tum.cit.aet.artemis.exercise.participation.util.ParticipationFactory;
Expand Down Expand Up @@ -741,6 +742,21 @@ public ProgrammingSubmission addProgrammingSubmission(ProgrammingExercise exerci
return submission;
}

/**
* Adds programming submission to provided programming exercise. The provided login is used to access or create a participation.
*
* @param exercise The exercise to which the submission should be added.
* @param submission The submission which should be added to the programming exercise.
* @param team The login of the user used to access or create an exercise participation.
* @return The created programming submission.
*/
public ProgrammingSubmission addProgrammingSubmissionToTeamExercise(ProgrammingExercise exercise, ProgrammingSubmission submission, Team team) {
StudentParticipation participation = participationUtilService.addTeamParticipationForProgrammingExercise(exercise, team);
submission.setParticipation(participation);
submission = programmingSubmissionRepo.save(submission);
return submission;
}

/**
* Adds a submission with a result to the given programming exercise. The submission will be assigned to the corresponding participation of the given login (if exists or
* create a new participation).
Expand Down

0 comments on commit 0fc8adb

Please sign in to comment.