JobsController.java

1
package edu.ucsb.cs.scaffold.controller;
2
3
import edu.ucsb.cs.scaffold.entity.Course;
4
import edu.ucsb.cs.scaffold.errors.EntityNotFoundException;
5
import edu.ucsb.cs.scaffold.jobs.CopyConceptGraphJob;
6
import edu.ucsb.cs.scaffold.jobs.ReadPLColorsJob;
7
import edu.ucsb.cs.scaffold.jobs.RotatePatKeysJob;
8
import edu.ucsb.cs.scaffold.jobs.SyncCourseWithPlRepoJob;
9
import edu.ucsb.cs.scaffold.jobs.SyncCourseWithPlRepoJobFactory;
10
import edu.ucsb.cs.scaffold.jobs.UpdateAllJob;
11
import edu.ucsb.cs.scaffold.repository.AdminRepository;
12
import edu.ucsb.cs.scaffold.repository.CourseRepository;
13
import edu.ucsb.cs.scaffold.repository.PatCredentialRepository;
14
import edu.ucsb.cs.scaffold.repository.PlColorRepository;
15
import edu.ucsb.cs.scaffold.repository.UserRepository;
16
import edu.ucsb.cs.scaffold.services.ConceptYamlService;
17
import edu.ucsb.cs.scaffold.services.GithubService;
18
import edu.ucsb.cs.scaffold.services.PatEncryptionService;
19
import edu.ucsb.cs.scaffold.services.UpdateUserService;
20
import edu.ucsb.cs156.jobs.entities.Job;
21
import edu.ucsb.cs156.jobs.repositories.JobsRepository;
22
import edu.ucsb.cs156.jobs.services.JobService;
23
import io.swagger.v3.oas.annotations.Operation;
24
import io.swagger.v3.oas.annotations.Parameter;
25
import io.swagger.v3.oas.annotations.tags.Tag;
26
import lombok.extern.slf4j.Slf4j;
27
import org.springframework.beans.factory.annotation.Autowired;
28
import org.springframework.security.access.prepost.PreAuthorize;
29
import org.springframework.web.bind.annotation.GetMapping;
30
import org.springframework.web.bind.annotation.PostMapping;
31
import org.springframework.web.bind.annotation.RequestMapping;
32
import org.springframework.web.bind.annotation.RequestParam;
33
import org.springframework.web.bind.annotation.RestController;
34
35
/**
36
 * Launch endpoints for this app's concrete jobs, plus the course-scoped jobs listing (which uses
37
 * this app's CourseSecurity rule). The generic admin endpoints (list all / paginated / logs /
38
 * delete) come from the lib-jobs library's own controller.
39
 */
40
@Tag(name = "Jobs")
41
@RequestMapping("/api/jobs")
42
@RestController
43
@Slf4j
44
public class JobsController extends ApiController {
45
  @Autowired private JobsRepository jobsRepository;
46
47
  @Autowired private JobService jobService;
48
49
  @Autowired private UpdateUserService updateUserService;
50
51
  @Autowired private CourseRepository courseRepository;
52
  @Autowired private PatEncryptionService patEncryptionService;
53
  @Autowired private PatCredentialRepository patCredentialRepository;
54
  @Autowired private SyncCourseWithPlRepoJobFactory syncCourseWithPlRepoJobFactory;
55
  @Autowired private UserRepository userRepository;
56
  @Autowired private AdminRepository adminRepository;
57
  @Autowired private ConceptYamlService conceptYamlService;
58
  @Autowired private GithubService githubService;
59
  @Autowired private PlColorRepository plColorRepository;
60
61
  @Operation(summary = "Launch UpdateAll job")
62
  @PreAuthorize("hasRole('ROLE_ADMIN')")
63
  @PostMapping("/launch/updateAll")
64
  public Job launchUpdateAllJob() {
65
66
    UpdateAllJob job = UpdateAllJob.builder().updateUserService(updateUserService).build();
67 1 1. launchUpdateAllJob : replaced return value with null for edu/ucsb/cs/scaffold/controller/JobsController::launchUpdateAllJob → KILLED
    return jobService.runAsJob(job);
68
  }
69
70
  @Operation(
71
      summary =
72
          "Launch RotatePatKeys job (re-encrypt stored PATs under the current PAT_ENCRYPTION_KEY)")
73
  @PreAuthorize("hasRole('ROLE_ADMIN')")
74
  @PostMapping("/launch/rotatePatKeys")
75
  public Job launchRotatePatKeysJob() {
76
77
    RotatePatKeysJob job =
78
        RotatePatKeysJob.builder()
79
            .patEncryptionService(patEncryptionService)
80
            .patCredentialRepository(patCredentialRepository)
81
            .build();
82 1 1. launchRotatePatKeysJob : replaced return value with null for edu/ucsb/cs/scaffold/controller/JobsController::launchRotatePatKeysJob → KILLED
    return jobService.runAsJob(job);
83
  }
84
85
  @Operation(
86
      summary =
87
          "Launch SyncCourseWithPlRepo job (sync the course's questions and assessments from"
88
              + " GitHub and PrairieLearn, using the launching user's PATs)")
89
  @PreAuthorize("@CourseSecurity.hasManagePermissions(#root, #courseId)")
90
  @PostMapping("/launch/syncCourseWithPlRepo")
91
  public Job launchSyncCourseWithPlRepoJob(
92
      @Parameter(name = "courseId") @RequestParam Long courseId) {
93
94
    Course course =
95
        courseRepository
96
            .findById(courseId)
97 1 1. lambda$launchSyncCourseWithPlRepoJob$0 : replaced return value with null for edu/ucsb/cs/scaffold/controller/JobsController::lambda$launchSyncCourseWithPlRepoJob$0 → KILLED
            .orElseThrow(() -> new EntityNotFoundException(Course.class, courseId));
98
    SyncCourseWithPlRepoJob job =
99
        syncCourseWithPlRepoJobFactory.create(getCurrentUser().getUser().getId(), course);
100 1 1. launchSyncCourseWithPlRepoJob : replaced return value with null for edu/ucsb/cs/scaffold/controller/JobsController::launchSyncCourseWithPlRepoJob → KILLED
    return jobService.runAsJob(job);
101
  }
102
103
  @Operation(
104
      summary =
105
          "Launch CopyConceptGraph job (replace the to course's concept graph with a copy of the"
106
              + " from course's concept graph, and clear the to course's user state)")
107
  @PreAuthorize(
108
      "@CourseSecurity.hasManagePermissions(#root, #fromCourseId) and"
109
          + " @CourseSecurity.hasManagePermissions(#root, #toCourseId)")
110
  @PostMapping("/launch/copyConceptGraph")
111
  public Job launchCopyConceptGraphJob(
112
      @Parameter(name = "fromCourseId") @RequestParam Long fromCourseId,
113
      @Parameter(name = "toCourseId") @RequestParam Long toCourseId) {
114
115
    CopyConceptGraphJob job =
116
        CopyConceptGraphJob.builder()
117
            .userId(getCurrentUser().getUser().getId())
118
            .fromCourseId(fromCourseId)
119
            .toCourseId(toCourseId)
120
            .userRepository(userRepository)
121
            .courseRepository(courseRepository)
122
            .adminRepository(adminRepository)
123
            .conceptYamlService(conceptYamlService)
124
            .build();
125 1 1. launchCopyConceptGraphJob : replaced return value with null for edu/ucsb/cs/scaffold/controller/JobsController::launchCopyConceptGraphJob → KILLED
    return jobService.runAsJob(job);
126
  }
127
128
  @Operation(
129
      summary =
130
          "Launch ReadPLColors job (read PrairieLearn's badge colors from GitHub and update the"
131
              + " pl_color table, using the launching admin's GitHub PAT)")
132
  @PreAuthorize("hasRole('ROLE_ADMIN')")
133
  @PostMapping("/launch/readPLColors")
134
  public Job launchReadPLColorsJob() {
135
136
    ReadPLColorsJob job =
137
        ReadPLColorsJob.builder()
138
            .userId(getCurrentUser().getUser().getId())
139
            .patCredentialRepository(patCredentialRepository)
140
            .patEncryptionService(patEncryptionService)
141
            .githubService(githubService)
142
            .plColorRepository(plColorRepository)
143
            .build();
144 1 1. launchReadPLColorsJob : replaced return value with null for edu/ucsb/cs/scaffold/controller/JobsController::launchReadPLColorsJob → KILLED
    return jobService.runAsJob(job);
145
  }
146
147
  @Operation(summary = "List jobs by courseId")
148
  @PreAuthorize("@CourseSecurity.hasManagePermissions(#root, #courseId)")
149
  @GetMapping("/course")
150
  public Iterable<Job> jobsByCourse(@Parameter(name = "courseId") @RequestParam Long courseId) {
151 1 1. jobsByCourse : replaced return value with Collections.emptyList for edu/ucsb/cs/scaffold/controller/JobsController::jobsByCourse → KILLED
    return jobsRepository.findByScopeTypeAndScopeIdOrderByIdDesc("course", courseId);
152
  }
153
}

Mutations

67

1.1
Location : launchUpdateAllJob
Killed by : edu.ucsb.cs.scaffold.controller.JobsControllerJobsTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.controller.JobsControllerJobsTests]/[method:admin_can_launch_updateAll_job()]
replaced return value with null for edu/ucsb/cs/scaffold/controller/JobsController::launchUpdateAllJob → KILLED

82

1.1
Location : launchRotatePatKeysJob
Killed by : edu.ucsb.cs.scaffold.controller.JobsControllerJobsTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.controller.JobsControllerJobsTests]/[method:admin_can_launch_rotatePatKeys_job()]
replaced return value with null for edu/ucsb/cs/scaffold/controller/JobsController::launchRotatePatKeysJob → KILLED

97

1.1
Location : lambda$launchSyncCourseWithPlRepoJob$0
Killed by : edu.ucsb.cs.scaffold.controller.JobsControllerJobsTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.controller.JobsControllerJobsTests]/[method:launching_syncCourseWithPlRepo_for_a_missing_course_returns_404()]
replaced return value with null for edu/ucsb/cs/scaffold/controller/JobsController::lambda$launchSyncCourseWithPlRepoJob$0 → KILLED

100

1.1
Location : launchSyncCourseWithPlRepoJob
Killed by : edu.ucsb.cs.scaffold.controller.JobsControllerJobsTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.controller.JobsControllerJobsTests]/[method:instructor_with_course_permissions_can_launch_syncCourseWithPlRepo_job()]
replaced return value with null for edu/ucsb/cs/scaffold/controller/JobsController::launchSyncCourseWithPlRepoJob → KILLED

125

1.1
Location : launchCopyConceptGraphJob
Killed by : edu.ucsb.cs.scaffold.controller.JobsControllerJobsTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.controller.JobsControllerJobsTests]/[method:instructor_with_course_permissions_can_launch_copyConceptGraph_job()]
replaced return value with null for edu/ucsb/cs/scaffold/controller/JobsController::launchCopyConceptGraphJob → KILLED

144

1.1
Location : launchReadPLColorsJob
Killed by : edu.ucsb.cs.scaffold.controller.JobsControllerJobsTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.controller.JobsControllerJobsTests]/[method:admin_can_launch_readPLColors_job()]
replaced return value with null for edu/ucsb/cs/scaffold/controller/JobsController::launchReadPLColorsJob → KILLED

151

1.1
Location : jobsByCourse
Killed by : edu.ucsb.cs.scaffold.controller.JobsControllerJobsTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.controller.JobsControllerJobsTests]/[method:admin_can_get_jobs_by_course()]
replaced return value with Collections.emptyList for edu/ucsb/cs/scaffold/controller/JobsController::jobsByCourse → KILLED

Active mutators

Tests examined


Report generated by PIT 1.17.0