use of de.tum.in.www1.artemis.domain.participation.StudentParticipation in project Artemis by ls1intum.
the class ProgrammingSubmissionIntegrationTest method triggerFailedBuildEmptyLatestPendingSubmission.
@Test
@WithMockUser(username = "student1", roles = "USER")
void triggerFailedBuildEmptyLatestPendingSubmission() throws Exception {
bambooRequestMockProvider.enableMockingOfRequests();
doReturn(COMMIT_HASH_OBJECT_ID).when(gitService).getLastCommitHash(any());
String login = "student1";
StudentParticipation participation = database.addStudentParticipationForProgrammingExercise(exercise, login);
bambooRequestMockProvider.mockTriggerBuild((ProgrammingExerciseParticipation) participation);
doReturn(Optional.empty()).when(programmingSubmissionService).getLatestPendingSubmission(anyLong(), anyBoolean());
String url = "/api/programming-submissions/" + participation.getId() + "/trigger-failed-build";
request.postWithoutLocation(url, null, HttpStatus.NOT_FOUND, new HttpHeaders());
}
use of de.tum.in.www1.artemis.domain.participation.StudentParticipation in project Artemis by ls1intum.
the class ProgrammingSubmissionIntegrationTest method triggerBuildInstructorTutorForbidden.
@Test
@WithMockUser(username = "tutor1", roles = "TA")
void triggerBuildInstructorTutorForbidden() throws Exception {
String login = "student1";
StudentParticipation participation = database.addStudentParticipationForProgrammingExercise(exercise, login);
String url = "/api/programming-submissions/" + participation.getId() + "/trigger-build?submissionType=INSTRUCTOR";
request.postWithoutLocation(url, null, HttpStatus.FORBIDDEN, new HttpHeaders());
}
use of de.tum.in.www1.artemis.domain.participation.StudentParticipation in project Artemis by ls1intum.
the class AssessmentService method cancelAssessmentOfSubmission.
/**
* Cancel an assessment of a given submission for the current user, i.e. delete the corresponding result / release the lock. Then the submission is available for assessment
* again.
*
* @param submission the submission for which the current assessment should be canceled
*/
// NOTE: As we use delete methods with underscores, we need a transactional context here!
@Transactional
public void cancelAssessmentOfSubmission(Submission submission) {
StudentParticipation participation = studentParticipationRepository.findWithEagerResultsById(submission.getParticipation().getId()).orElseThrow(() -> new BadRequestAlertException("Participation could not be found", "participation", "notfound"));
// cancel is only possible for the latest result.
Result result = submission.getLatestResult();
// We only want to be able to cancel a result if it is not of the AUTOMATIC AssessmentType
if (result != null && result.getAssessmentType() != null && result.getAssessmentType() != AssessmentType.AUTOMATIC) {
participation.removeResult(result);
feedbackRepository.deleteByResult_Id(result.getId());
resultRepository.deleteById(result.getId());
}
}
use of de.tum.in.www1.artemis.domain.participation.StudentParticipation in project Artemis by ls1intum.
the class ExerciseDeletionService method cleanup.
/**
* Delete student build plans (except BASE/SOLUTION) and optionally git repositories of all exercise student participations.
*
* @param exerciseId programming exercise for which build plans in respective student participations are deleted
* @param deleteRepositories if true, the repositories gets deleted
*/
public void cleanup(Long exerciseId, boolean deleteRepositories) {
Exercise exercise = exerciseRepository.findByIdWithStudentParticipationsElseThrow(exerciseId);
log.info("Request to cleanup all participations for Exercise : {}", exercise.getTitle());
if (exercise instanceof ProgrammingExercise) {
for (StudentParticipation participation : exercise.getStudentParticipations()) {
participationService.cleanupBuildPlan((ProgrammingExerciseStudentParticipation) participation);
}
if (!deleteRepositories) {
// in this case, we are done
return;
}
for (StudentParticipation participation : exercise.getStudentParticipations()) {
participationService.cleanupRepository((ProgrammingExerciseStudentParticipation) participation);
}
} else {
log.warn("Exercise with exerciseId {} is not an instance of ProgrammingExercise. Ignoring the request to cleanup repositories and build plan", exerciseId);
}
}
use of de.tum.in.www1.artemis.domain.participation.StudentParticipation in project Artemis by ls1intum.
the class ProgrammingExerciseExportService method exportProgrammingExerciseRepositories.
/**
* Export instructor repositories and optionally students' repositories in a zip file.
*
* The outputDir is used to store the zip file and temporary files used for zipping so make
* sure to delete it if it's no longer used.
*
* @param exercise the programming exercise
* @param includingStudentRepos flag for including the students repos as well
* @param outputDir the path to a directory that will be used to store the zipped programming exercise.
* @param exportErrors List of failures that occurred during the export
* @param reportData List of all exercises and their statistics
* @return the path to the zip file
*/
public Path exportProgrammingExerciseRepositories(ProgrammingExercise exercise, Boolean includingStudentRepos, Path outputDir, List<String> exportErrors, List<ArchivalReportEntry> reportData) {
log.info("Exporting programming exercise {} with title {}", exercise.getId(), exercise.getTitle());
// List to add paths of files that should be contained in the zip folder of exported programming exercise repositories:
// i.e., student repositories (if `includingStudentRepos` is true), instructor repositories template, solution and tests
var pathsToBeZipped = new ArrayList<Path>();
if (includingStudentRepos) {
// Lazy load student participation, sort by id, and set the export options
var studentParticipations = studentParticipationRepository.findByExerciseId(exercise.getId()).stream().map(studentParticipation -> (ProgrammingExerciseStudentParticipation) studentParticipation).sorted(Comparator.comparing(DomainObject::getId)).collect(Collectors.toList());
var exportOptions = new RepositoryExportOptionsDTO();
exportOptions.setHideStudentNameInZippedFolder(false);
// Export student repositories and add them to list
var exportedStudentRepositoryFiles = exportStudentRepositories(exercise, studentParticipations, exportOptions, outputDir, exportErrors).stream().filter(Objects::nonNull).toList();
pathsToBeZipped.addAll(exportedStudentRepositoryFiles);
}
// Export the template, solution, and tests repositories and add them to list
pathsToBeZipped.add(exportInstructorRepositoryForExercise(exercise.getId(), RepositoryType.TEMPLATE, outputDir, exportErrors).map(File::toPath).orElse(null));
pathsToBeZipped.add(exportInstructorRepositoryForExercise(exercise.getId(), RepositoryType.SOLUTION, outputDir, exportErrors).map(File::toPath).orElse(null));
pathsToBeZipped.add(exportInstructorRepositoryForExercise(exercise.getId(), RepositoryType.TESTS, outputDir, exportErrors).map(File::toPath).orElse(null));
List<AuxiliaryRepository> auxiliaryRepositories = auxiliaryRepositoryRepository.findByExerciseId(exercise.getId());
// Export the auxiliary repositories and add them to list
auxiliaryRepositories.forEach(auxiliaryRepository -> {
pathsToBeZipped.add(exportInstructorAuxiliaryRepositoryForExercise(exercise.getId(), auxiliaryRepository, outputDir, exportErrors).map(File::toPath).orElse(null));
});
// Setup path to store the zip file for the exported repositories
var timestamp = ZonedDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd-Hmss"));
String filename = exercise.getCourseViaExerciseGroupOrCourseMember().getShortName() + "-" + exercise.getTitle() + "-" + exercise.getId() + "-" + timestamp + ".zip";
String cleanFilename = fileService.removeIllegalCharacters(filename);
Path pathToZippedExercise = Path.of(outputDir.toString(), cleanFilename);
// Remove null elements and get the file path of each file to be included, i.e. each entry in the pathsToBeZipped list
List<Path> includedFilePathsNotNull = pathsToBeZipped.stream().filter(Objects::nonNull).collect(Collectors.toList());
String cleanProjectName = fileService.removeIllegalCharacters(exercise.getProjectName());
// Add report entry, programming repositories cannot be skipped
reportData.add(new ArchivalReportEntry(exercise, cleanProjectName, pathsToBeZipped.size(), includedFilePathsNotNull.size(), 0));
try {
// Only create zip file if there's files to zip
if (includedFilePathsNotNull.isEmpty()) {
String info = "Will not export programming exercise " + exercise.getId() + " with title " + exercise.getTitle() + " because it's empty";
log.info(info);
exportErrors.add(info);
return null;
}
// Create the zip folder of the exported programming exercise and return the path to the created folder
zipFileService.createZipFile(pathToZippedExercise, includedFilePathsNotNull, false);
return pathToZippedExercise;
} catch (Exception e) {
var error = "Failed to export programming exercise because the zip file " + pathToZippedExercise + " could not be created: " + e.getMessage();
log.info(error);
exportErrors.add(error);
return null;
}
}
Aggregations