use of de.tum.in.www1.artemis.web.rest.errors.EntityNotFoundException in project ArTEMiS by ls1intum.
the class ProgrammingExerciseExportImportResource method importProgrammingExercise.
/**
* POST /programming-exercises/import: Imports an existing programming exercise into an existing course
* <p>
* This will import the whole exercise, including all base build plans (template, solution) and repositories
* (template, solution, test). Referenced entities, s.a. the test cases or the hints will get cloned and assigned
* a new id. For a concrete list of what gets copied and what not have a look
* at {@link ProgrammingExerciseImportService#importProgrammingExerciseBasis(ProgrammingExercise, ProgrammingExercise)}
*
* @param sourceExerciseId The ID of the original exercise which should get imported
* @param newExercise The new exercise containing values that should get overwritten in the imported exercise, s.a. the title or difficulty
* @param recreateBuildPlans Option determining whether the build plans should be copied or re-created from scratch
* @param updateTemplate Option determining whether the template files should be updated with the most recent template version
* @return The imported exercise (200), a not found error (404) if the template does not exist, or a forbidden error
* (403) if the user is not at least an instructor in the target course.
* @see ProgrammingExerciseImportService#importProgrammingExerciseBasis(ProgrammingExercise, ProgrammingExercise)
* @see ProgrammingExerciseImportService#importBuildPlans(ProgrammingExercise, ProgrammingExercise)
* @see ProgrammingExerciseImportService#importRepositories(ProgrammingExercise, ProgrammingExercise)
*/
@PostMapping(IMPORT)
@PreAuthorize("hasRole('EDITOR')")
@FeatureToggle(Feature.ProgrammingExercises)
public ResponseEntity<ProgrammingExercise> importProgrammingExercise(@PathVariable long sourceExerciseId, @RequestBody ProgrammingExercise newExercise, @RequestParam(defaultValue = "false") boolean recreateBuildPlans, @RequestParam(defaultValue = "false") boolean updateTemplate) {
if (sourceExerciseId < 0) {
throw new BadRequestAlertException("Invalid source id when importing programming exercises", ENTITY_NAME, "invalidSourceExerciseId");
}
// Valid exercises have set either a course or an exerciseGroup
newExercise.checkCourseAndExerciseGroupExclusivity(ENTITY_NAME);
log.debug("REST request to import programming exercise {} into course {}", sourceExerciseId, newExercise.getCourseViaExerciseGroupOrCourseMember().getId());
newExercise.validateGeneralSettings();
newExercise.validateProgrammingSettings();
validateStaticCodeAnalysisSettings(newExercise);
final var user = userRepository.getUserWithGroupsAndAuthorities();
Course course = courseService.retrieveCourseOverExerciseGroupOrCourseId(newExercise);
authCheckService.checkHasAtLeastRoleInCourseElseThrow(Role.EDITOR, course, user);
// Validate course settings
programmingExerciseRepository.validateCourseSettings(newExercise, course);
final var originalProgrammingExercise = programmingExerciseRepository.findByIdWithEagerTestCasesStaticCodeAnalysisCategoriesHintsAndTemplateAndSolutionParticipationsAndAuxReposAndTasksWithTestCases(sourceExerciseId).orElseThrow(() -> new EntityNotFoundException("ProgrammingExercise", sourceExerciseId));
// The static code analysis flag can only change, if the build plans are recreated and the template is upgraded
if (newExercise.isStaticCodeAnalysisEnabled() != originalProgrammingExercise.isStaticCodeAnalysisEnabled() && !(recreateBuildPlans && updateTemplate)) {
throw new BadRequestAlertException("Static code analysis can only change, if the recreation of build plans and update of template files is activated", ENTITY_NAME, "staticCodeAnalysisCannotChange");
}
// If the new exercise has a submission policy, it must be validated.
if (newExercise.getSubmissionPolicy() != null) {
submissionPolicyService.validateSubmissionPolicy(newExercise.getSubmissionPolicy());
}
// Check if the user has the rights to access the original programming exercise
Course originalCourse = courseService.retrieveCourseOverExerciseGroupOrCourseId(originalProgrammingExercise);
authCheckService.checkHasAtLeastRoleInCourseElseThrow(Role.EDITOR, originalCourse, user);
newExercise.generateAndSetProjectKey();
programmingExerciseService.checkIfProjectExists(newExercise);
final var importedProgrammingExercise = programmingExerciseImportService.importProgrammingExerciseBasis(originalProgrammingExercise, newExercise);
programmingExerciseImportService.importRepositories(originalProgrammingExercise, importedProgrammingExercise);
// Update the template files
if (updateTemplate) {
TemplateUpgradeService upgradeService = templateUpgradePolicy.getUpgradeService(importedProgrammingExercise.getProgrammingLanguage());
upgradeService.upgradeTemplate(importedProgrammingExercise);
}
HttpHeaders responseHeaders;
// Copy or recreate the build plans
try {
if (recreateBuildPlans) {
// Create completely new build plans for the exercise
programmingExerciseService.setupBuildPlansForNewExercise(importedProgrammingExercise);
} else {
// We have removed the automatic build trigger from test to base for new programming exercises.
// We also remove this build trigger in the case of an import as the source exercise might still have this trigger.
// The importBuildPlans method includes this process
programmingExerciseImportService.importBuildPlans(originalProgrammingExercise, importedProgrammingExercise);
}
responseHeaders = HeaderUtil.createEntityCreationAlert(applicationName, true, ENTITY_NAME, importedProgrammingExercise.getTitle());
} catch (Exception e) {
responseHeaders = HeaderUtil.createFailureAlert(applicationName, true, ENTITY_NAME, "importExerciseTriggerPlanFail", "Unable to trigger imported build plans");
}
programmingExerciseService.scheduleOperations(importedProgrammingExercise.getId());
// Remove unnecessary fields
importedProgrammingExercise.setTestCases(null);
importedProgrammingExercise.setStaticCodeAnalysisCategories(null);
importedProgrammingExercise.setTemplateParticipation(null);
importedProgrammingExercise.setSolutionParticipation(null);
importedProgrammingExercise.setExerciseHints(null);
importedProgrammingExercise.setTasks(null);
return ResponseEntity.ok().headers(responseHeaders).body(importedProgrammingExercise);
}
use of de.tum.in.www1.artemis.web.rest.errors.EntityNotFoundException in project ArTEMiS by ls1intum.
the class ProgrammingExerciseParticipationResource method getParticipationWithLatestResultForStudentParticipation.
/**
* Get the given student participation with its latest result and feedbacks.
*
* @param participationId for which to retrieve the student participation with latest result and feedbacks.
* @return the ResponseEntity with status 200 (OK) and the participation with its latest result in the body.
*/
@GetMapping("/programming-exercise-participations/{participationId}/student-participation-with-latest-result-and-feedbacks")
@PreAuthorize("hasRole('USER')")
public ResponseEntity<Participation> getParticipationWithLatestResultForStudentParticipation(@PathVariable Long participationId) {
ProgrammingExerciseStudentParticipation participation = programmingExerciseStudentParticipationRepository.findStudentParticipationWithLatestResultAndFeedbacksAndRelatedSubmissions(participationId).orElseThrow(() -> new EntityNotFoundException("Participation", participationId));
if (!programmingExerciseParticipationService.canAccessParticipation(participation)) {
throw new AccessForbiddenException("participation", participationId);
}
if (!authCheckService.isAtLeastTeachingAssistantForExercise(participation.getExercise())) {
// hide details that should not be shown to the students
participation.getExercise().filterSensitiveInformation();
participation.getResults().forEach(result -> filterSensitiveInformationInResult(participation, result));
}
return ResponseEntity.ok(participation);
}
use of de.tum.in.www1.artemis.web.rest.errors.EntityNotFoundException in project ArTEMiS by ls1intum.
the class CourseResource method downloadCourseArchive.
/**
* Downloads the zip file of the archived course if it exists. Throws a 404 if the course doesn't exist
*
* @param courseId The course id of the archived course
* @return ResponseEntity with status
*/
@PreAuthorize("hasRole('INSTRUCTOR')")
@GetMapping("/courses/{courseId}/download-archive")
public ResponseEntity<Resource> downloadCourseArchive(@PathVariable Long courseId) throws FileNotFoundException {
log.info("REST request to download archive of Course : {}", courseId);
final Course course = courseRepository.findByIdElseThrow(courseId);
authCheckService.checkHasAtLeastRoleInCourseElseThrow(Role.INSTRUCTOR, course, null);
if (!course.hasCourseArchive()) {
throw new EntityNotFoundException("Archived course", courseId);
}
// The path is stored in the course table
Path archive = Path.of(courseArchivesDirPath, course.getCourseArchivePath());
File zipFile = archive.toFile();
InputStreamResource resource = new InputStreamResource(new FileInputStream(zipFile));
return ResponseEntity.ok().contentLength(zipFile.length()).contentType(MediaType.APPLICATION_OCTET_STREAM).header("filename", zipFile.getName()).body(resource);
}
use of de.tum.in.www1.artemis.web.rest.errors.EntityNotFoundException in project ArTEMiS by ls1intum.
the class ProgrammingExerciseResource method updateProblemStatement.
/**
* PATCH /programming-exercises-problem: Updates the problem statement of the exercise.
*
* @param exerciseId The ID of the exercise for which to change the problem statement
* @param updatedProblemStatement The new problemStatement
* @param notificationText to notify the student group about the updated problemStatement on the programming exercise
* @return the ResponseEntity with status 200 (OK) and with body the updated problemStatement, with status 404 if the programmingExercise could not be found, or with 403 if the user does not have permissions to access the programming exercise.
*/
@PatchMapping(PROBLEM)
@PreAuthorize("hasRole('EDITOR')")
public ResponseEntity<ProgrammingExercise> updateProblemStatement(@PathVariable long exerciseId, @RequestBody String updatedProblemStatement, @RequestParam(value = "notificationText", required = false) String notificationText) {
log.debug("REST request to update ProgrammingExercise with new problem statement: {}", updatedProblemStatement);
var programmingExercise = programmingExerciseRepository.findWithTemplateAndSolutionParticipationTeamAssignmentConfigCategoriesById(exerciseId).orElseThrow(() -> new EntityNotFoundException("Programming Exercise", exerciseId));
var user = userRepository.getUserWithGroupsAndAuthorities();
authCheckService.checkHasAtLeastRoleForExerciseElseThrow(Role.EDITOR, programmingExercise, user);
var updatedProgrammingExercise = programmingExerciseService.updateProblemStatement(programmingExercise, updatedProblemStatement, notificationText);
exerciseService.logUpdate(updatedProgrammingExercise, updatedProgrammingExercise.getCourseViaExerciseGroupOrCourseMember(), user);
return ResponseEntity.ok().headers(HeaderUtil.createEntityUpdateAlert(applicationName, true, ENTITY_NAME, updatedProgrammingExercise.getTitle())).body(updatedProgrammingExercise);
}
use of de.tum.in.www1.artemis.web.rest.errors.EntityNotFoundException in project ArTEMiS by ls1intum.
the class ProgrammingSubmissionResultSimulationResource method createNewProgrammingExerciseResult.
/**
* This method is used to notify artemis that there is a new programming exercise build result.
* This result is only a SIMULATION for the testing of programming exercises without a connection
* to the VCS and CI server
* This functionality is only for testing purposes (noVersionControlAndContinuousIntegrationAvailable)
* @param exerciseId id of the exercise
* @return HTTP OK and Result
*/
@PostMapping(Endpoints.RESULTS_SIMULATION)
@PreAuthorize("hasRole('EDITOR')")
public ResponseEntity<Result> createNewProgrammingExerciseResult(@PathVariable Long exerciseId) {
log.debug("Received result notify (NEW)");
User user = userRepository.getUserWithGroupsAndAuthorities();
ProgrammingExercise programmingExercise = programmingExerciseRepository.findByIdWithStudentParticipationsAndLegalSubmissionsElseThrow(exerciseId);
var studentParticipation = participationService.findOneByExerciseAndParticipantAnyState(programmingExercise, user).orElseThrow(() -> new EntityNotFoundException("Participation for programming exercise " + programmingExercise.getId() + " and user " + user.getLogin() + " not found!"));
var programmingExerciseStudentParticipation = (ProgrammingExerciseStudentParticipation) studentParticipation;
Result result = programmingSubmissionResultSimulationService.createResult(programmingExerciseStudentParticipation);
messagingService.broadcastNewResult(programmingExerciseStudentParticipation, result);
log.info("The new result for {} was saved successfully", programmingExerciseStudentParticipation.getBuildPlanId());
try {
return ResponseEntity.created(new URI("/api/results" + result.getId())).body(result);
} catch (URISyntaxException e) {
log.error("Error while simulating a result", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).headers(HeaderUtil.createAlert(applicationName, "An error occurred while simulating a result: " + e.getMessage(), "errorResult")).body(null);
}
}
Aggregations