Skip to content

Commit

Permalink
Merge pull request #386 from mp-access/feature/submission-browser-382
Browse files Browse the repository at this point in the history
Feature/submission browser
  • Loading branch information
a-a-hofmann authored Nov 6, 2019
2 parents b272726 + d2e1fd9 commit 7cc03ed
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import ch.uzh.ifi.access.course.model.security.GrantedCourseAccess;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.OAuth2Request;

Expand Down Expand Up @@ -45,4 +46,22 @@ public boolean hasAdminAccess(String courseId) {
public String getUserId() {
return userId;
}

/**
* Creates a new authentication object for the given user and sets it to the security context.
* If the user is not allowed to impersonate a user, does nothing and returns null.
*
* @param userId the user to impersonate
* @param courseId the course for which the calling user has admin access
* @return impersonated authentication object if admin, null otherwise.
*/
public CourseAuthentication impersonateUser(String userId, String courseId) {
if (hasAdminAccess(courseId)) {
CourseAuthentication impersonatedAuth = new CourseAuthentication(getOAuth2Request(), this, courseAccesses, userId);
SecurityContextHolder.getContext().setAuthentication(impersonatedAuth);
return impersonatedAuth;
}

return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ public Optional<Integer> getExerciseMaxSubmissions(String exerciseId) {
return courseDao.selectExerciseById(exerciseId).map(Exercise::getMaxSubmits);
}

public Optional<Course> getCourseByExerciseId(String exerciseId) {
return getExerciseById(exerciseId).flatMap(ex -> getCourseById(ex.getCourseId()));
}

private boolean hasAccessToExerciseSolutions(Exercise exercise, CourseAuthentication authentication) {
return exercise.isPastDueDate() || authentication.hasPrivilegedAccess(exercise.getCourseId());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import ch.uzh.ifi.access.course.service.CourseService;
import ch.uzh.ifi.access.student.reporting.AssignmentReport;
import ch.uzh.ifi.access.student.service.AdminSubmissionService;
import ch.uzh.ifi.access.student.service.UserService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
Expand Down Expand Up @@ -48,8 +49,18 @@ public ResponseEntity<?> reevaluateInvalidateSubmissionsForAssignment(@PathVaria
Assignment assignment = course.getAssignmentById(assignmentId)
.orElseThrow(() -> new ResourceNotFoundException("No assignment found"));

adminSubmissionService.reevaluateAssignmentsInvalidSubmissions(course, assignment);
return ResponseEntity.ok("ok");
adminSubmissionService.reevaluateAssignmentsInvalidSubmissions(course, assignment);
return ResponseEntity.ok("ok");
}

@GetMapping("/courses/{courseId}/participants")
public ResponseEntity<?> getCourseParticipants(@PathVariable String courseId) {
Course course = courseService
.getCourseById(courseId)
.orElseThrow(() -> new ResourceNotFoundException("No course found"));

UserService.UserQueryResult courseStudents = adminSubmissionService.getCourseStudents(course);

return ResponseEntity.ok(courseStudents);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import ch.uzh.ifi.access.course.config.CourseAuthentication;
import ch.uzh.ifi.access.course.config.CoursePermissionEvaluator;
import ch.uzh.ifi.access.course.controller.ResourceNotFoundException;
import ch.uzh.ifi.access.course.model.Course;
import ch.uzh.ifi.access.course.model.Exercise;
import ch.uzh.ifi.access.course.service.CourseService;
import ch.uzh.ifi.access.student.dto.StudentAnswerDTO;
Expand Down Expand Up @@ -51,6 +52,22 @@ public SubmissionController(StudentSubmissionService studentSubmissionService, C
this.gracefulShutdown = gracefulShutdown;
}

@GetMapping("/{submissionId}/users/{userId}")
public ResponseEntity<StudentSubmission> getSubmissionById(@PathVariable String submissionId, @PathVariable String userId, @ApiIgnore CourseAuthentication authentication) {
Optional<StudentSubmission> subOpt = studentSubmissionService.findById(submissionId);

return subOpt
.flatMap(submission -> courseService.getCourseByExerciseId(submission.getExerciseId()))
.flatMap(course -> {
if (authentication.hasAdminAccess(course.getId())) {
return subOpt;
}
return Optional.empty();
})
.map(ResponseEntity::ok)
.orElse(ResponseEntity.badRequest().build());
}

@GetMapping("/{submissionId}")
public ResponseEntity<StudentSubmission> getSubmissionById(@PathVariable String submissionId, @ApiIgnore CourseAuthentication authentication) {
StudentSubmission submission = studentSubmissionService.findById(submissionId).orElse(null);
Expand Down Expand Up @@ -78,6 +95,22 @@ public ResponseEntity<StudentSubmission> getSubmissionByExercise(@PathVariable S
.orElse(ResponseEntity.noContent().build());
}

@GetMapping("/exercises/{exerciseId}/users/{userId}")
public ResponseEntity<StudentSubmission> getSubmissionByExerciseAsAdmin(@PathVariable String exerciseId, @PathVariable String userId, @ApiIgnore CourseAuthentication authentication) {
Assert.notNull(authentication, "No authentication object found for user");

Course course = courseService.getCourseByExerciseId(exerciseId).orElseThrow(IllegalArgumentException::new);

CourseAuthentication impersonation = authentication.impersonateUser(userId, course.getId());
if (impersonation != null) {
return getSubmissionByExercise(exerciseId, impersonation);
}

logger.warn("User {} called a restricted function for which it does not have enough rights!", authentication.getUserId());

return ResponseEntity.status(403).build();
}

@PostMapping("/exercises/{exerciseId}")
public ResponseEntity<?> submit(@PathVariable String exerciseId, @RequestBody StudentAnswerDTO submissionDTO, @ApiIgnore CourseAuthentication authentication) {
Assert.notNull(authentication, "No authentication object found for user");
Expand Down Expand Up @@ -127,6 +160,22 @@ public Map<String, String> getEvalProcessState(@PathVariable String processId, @
return processService.getEvalProcessState(processId);
}

@GetMapping("/exercises/{exerciseId}/users/{userId}/history")
public ResponseEntity<SubmissionHistoryDTO> getAllSubmissionsForExercise(@PathVariable String exerciseId, @PathVariable String userId, @ApiIgnore CourseAuthentication authentication) {
Assert.notNull(authentication, "No authentication object found for user");

Course course = courseService.getCourseByExerciseId(exerciseId).orElseThrow(IllegalArgumentException::new);

CourseAuthentication impersonation = authentication.impersonateUser(userId, course.getId());
if (impersonation != null) {
return ResponseEntity.ok(getAllSubmissionsForExercise(exerciseId, impersonation));
}

logger.warn("User {} called a restricted function for which it does not have enough rights!", authentication.getUserId());

return ResponseEntity.status(403).build();
}

@GetMapping("/exercises/{exerciseId}/history")
public SubmissionHistoryDTO getAllSubmissionsForExercise(@PathVariable String exerciseId, @ApiIgnore CourseAuthentication authentication) {
Assert.notNull(authentication, "No authentication object found for user");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ protected void triggerReEvaluation(List<StudentSubmission> submissions) {
logger.debug(String.format("Fire re-evaluation for processId %s with new submission %s)", reSubmitted.getId(), processId));
evaluationService.fireEvalProcessExecutionAsync(processId);
}
}

@PreAuthorize("@coursePermissionEvaluator.hasAdminAccessToCourse(authentication, #course)")
public UserService.UserQueryResult getCourseStudents(Course course) {
return userService.getCourseStudents(course);
}
}

0 comments on commit 7cc03ed

Please sign in to comment.