RepositoryController.java

1
package edu.ucsb.cs156.frontiers.controllers;
2
3
import com.fasterxml.jackson.databind.ObjectMapper;
4
import edu.ucsb.cs156.frontiers.entities.Course;
5
import edu.ucsb.cs156.frontiers.entities.Job;
6
import edu.ucsb.cs156.frontiers.enums.RepositoryCreationOption;
7
import edu.ucsb.cs156.frontiers.enums.RepositoryPermissions;
8
import edu.ucsb.cs156.frontiers.errors.EntityNotFoundException;
9
import edu.ucsb.cs156.frontiers.errors.NoLinkedOrganizationException;
10
import edu.ucsb.cs156.frontiers.jobs.CreateStudentOrStaffRepositoriesJob;
11
import edu.ucsb.cs156.frontiers.jobs.CreateTeamRepositoriesJob;
12
import edu.ucsb.cs156.frontiers.jobs.DeleteRepoJob;
13
import edu.ucsb.cs156.frontiers.repositories.CourseRepository;
14
import edu.ucsb.cs156.frontiers.services.GithubTeamService;
15
import edu.ucsb.cs156.frontiers.services.JwtService;
16
import edu.ucsb.cs156.frontiers.services.RepositoryService;
17
import edu.ucsb.cs156.frontiers.services.jobs.JobService;
18
import io.swagger.v3.oas.annotations.tags.Tag;
19
import java.util.Optional;
20
import org.springframework.beans.factory.annotation.Autowired;
21
import org.springframework.security.access.prepost.PreAuthorize;
22
import org.springframework.web.bind.annotation.DeleteMapping;
23
import org.springframework.web.bind.annotation.PostMapping;
24
import org.springframework.web.bind.annotation.RequestMapping;
25
import org.springframework.web.bind.annotation.RequestParam;
26
import org.springframework.web.bind.annotation.RestController;
27
import org.springframework.web.client.RestTemplate;
28
29
@Tag(name = "Repository Controller")
30
@RestController
31
@RequestMapping("/api/repos")
32
public class RepositoryController extends ApiController {
33
34
  @Autowired RepositoryService repositoryService;
35
36
  @Autowired JobService jobService;
37
38
  @Autowired CourseRepository courseRepository;
39
40
  @Autowired GithubTeamService githubTeamService;
41
42
  @Autowired JwtService jwtService;
43
44
  @Autowired ObjectMapper mapper;
45
46
  /**
47
   * Fires a job that creates a repo for every RosterStudent with a linked user with a GitHub
48
   * account.
49
   *
50
   * @param courseId ID of course to create repos for
51
   * @param repoPrefix each repo created will begin with this prefix, followed by a dash and the
52
   *     student's GitHub username
53
   * @param isPrivate determines whether the repository being created is private
54
   * @return the {@link edu.ucsb.cs156.frontiers.entities.Job Job} started to create the repos.
55
   */
56
  @PostMapping("/createRepos")
57
  @PreAuthorize("@CourseSecurity.hasManagePermissions(#root, #courseId)")
58
  public Job createRepos(
59
      @RequestParam Long courseId,
60
      @RequestParam String repoPrefix,
61
      @RequestParam Optional<Boolean> isPrivate,
62
      @RequestParam RepositoryPermissions permissions,
63
      @RequestParam(required = false, defaultValue = "STUDENTS_ONLY")
64
          RepositoryCreationOption creationOption) {
65
    Course course =
66
        courseRepository
67
            .findById(courseId)
68 1 1. lambda$createRepos$0 : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RepositoryController::lambda$createRepos$0 → KILLED
            .orElseThrow(() -> new EntityNotFoundException(Course.class, courseId));
69 2 1. createRepos : negated conditional → KILLED
2. createRepos : negated conditional → KILLED
    if (course.getOrgName() == null || course.getInstallationId() == null) {
70
      throw new NoLinkedOrganizationException(course.getCourseName());
71
    } else {
72
      CreateStudentOrStaffRepositoriesJob job =
73
          CreateStudentOrStaffRepositoriesJob.builder()
74
              .repositoryPrefix(repoPrefix)
75
              .isPrivate(isPrivate.orElse(false))
76
              .repositoryService(repositoryService)
77
              .course(course)
78
              .permissions(permissions)
79
              .creationOption(creationOption)
80
              .build();
81 1 1. createRepos : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RepositoryController::createRepos → KILLED
      return jobService.runAsJob(job);
82
    }
83
  }
84
85
  /**
86
   * Fires a job that creates team repos shared by all TeamMembers of each Team in a Course .
87
   *
88
   * @param courseId ID of course to create team repos for
89
   * @param repoPrefix each team repo created will begin with this prefix, followed by a dash and
90
   *     the team's name
91
   * @param isPrivate determines whether the repository being created is private
92
   * @return the {@link edu.ucsb.cs156.frontiers.entities.Job Job} started to create the repos.
93
   */
94
  @PostMapping("/createTeamRepos")
95
  @PreAuthorize("@CourseSecurity.hasManagePermissions(#root, #courseId)")
96
  public Job createTeamRepos(
97
      @RequestParam Long courseId,
98
      @RequestParam String repoPrefix,
99
      @RequestParam Optional<Boolean> isPrivate,
100
      @RequestParam RepositoryPermissions permissions,
101
      @RequestParam Optional<String> teamRegex) {
102
    Course course =
103
        courseRepository
104
            .findById(courseId)
105 1 1. lambda$createTeamRepos$1 : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RepositoryController::lambda$createTeamRepos$1 → KILLED
            .orElseThrow(() -> new EntityNotFoundException(Course.class, courseId));
106 2 1. createTeamRepos : negated conditional → KILLED
2. createTeamRepos : negated conditional → KILLED
    if (course.getOrgName() == null || course.getInstallationId() == null) {
107
      throw new NoLinkedOrganizationException(course.getCourseName());
108
    } else {
109
      CreateTeamRepositoriesJob job =
110
          CreateTeamRepositoriesJob.builder()
111
              .repositoryPrefix(repoPrefix)
112
              .isPrivate(isPrivate.orElse(false))
113
              .repositoryService(repositoryService)
114
              .githubTeamService(githubTeamService)
115
              .course(course)
116
              .permissions(permissions)
117
              .teamRegex(teamRegex.orElse(null))
118
              .build();
119 1 1. createTeamRepos : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RepositoryController::createTeamRepos → KILLED
      return jobService.runAsJob(job);
120
    }
121
  }
122
123
  /**
124
   * Fires a job that bulk deletes empty repos matching a specific prefix in the course's attached
125
   * organization.
126
   *
127
   * @param courseId ID of the course
128
   * @param prefix the prefix of the repositories to delete
129
   * @return the {@link edu.ucsb.cs156.frontiers.entities.Job Job} started to delete the repos.
130
   */
131
  @DeleteMapping("")
132
  @PreAuthorize("@CourseSecurity.hasManagePermissions(#root, #courseId)")
133
  public Job deleteRepos(@RequestParam Long courseId, @RequestParam String prefix) {
134
    Course course =
135
        courseRepository
136
            .findById(courseId)
137 1 1. lambda$deleteRepos$2 : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RepositoryController::lambda$deleteRepos$2 → KILLED
            .orElseThrow(() -> new EntityNotFoundException(Course.class, courseId));
138
139 2 1. deleteRepos : negated conditional → KILLED
2. deleteRepos : negated conditional → KILLED
    if (course.getOrgName() == null || course.getInstallationId() == null) {
140
      throw new NoLinkedOrganizationException(course.getCourseName());
141
    } else {
142
      DeleteRepoJob job =
143
          DeleteRepoJob.builder()
144
              .course(course)
145
              .prefix(prefix)
146
              .jwtService(jwtService)
147
              .mapper(mapper)
148
              .restTemplate(new RestTemplate())
149
              .build();
150 1 1. deleteRepos : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RepositoryController::deleteRepos → KILLED
      return jobService.runAsJob(job);
151
    }
152
  }
153
}

Mutations

68

1.1
Location : lambda$createRepos$0
Killed by : edu.ucsb.cs156.frontiers.controllers.RepositoryControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RepositoryControllerTests]/[method:notFound()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RepositoryController::lambda$createRepos$0 → KILLED

69

1.1
Location : createRepos
Killed by : edu.ucsb.cs156.frontiers.controllers.RepositoryControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RepositoryControllerTests]/[method:job_actually_fires()]
negated conditional → KILLED

2.2
Location : createRepos
Killed by : edu.ucsb.cs156.frontiers.controllers.RepositoryControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RepositoryControllerTests]/[method:just_no_install_id()]
negated conditional → KILLED

81

1.1
Location : createRepos
Killed by : edu.ucsb.cs156.frontiers.controllers.RepositoryControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RepositoryControllerTests]/[method:job_actually_fires()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RepositoryController::createRepos → KILLED

105

1.1
Location : lambda$createTeamRepos$1
Killed by : edu.ucsb.cs156.frontiers.controllers.RepositoryControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RepositoryControllerTests]/[method:team_repo_job_notFound()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RepositoryController::lambda$createTeamRepos$1 → KILLED

106

1.1
Location : createTeamRepos
Killed by : edu.ucsb.cs156.frontiers.controllers.RepositoryControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RepositoryControllerTests]/[method:team_repo_job_actually_fires()]
negated conditional → KILLED

2.2
Location : createTeamRepos
Killed by : edu.ucsb.cs156.frontiers.controllers.RepositoryControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RepositoryControllerTests]/[method:team_repo_job_just_no_install_id()]
negated conditional → KILLED

119

1.1
Location : createTeamRepos
Killed by : edu.ucsb.cs156.frontiers.controllers.RepositoryControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RepositoryControllerTests]/[method:team_repo_job_actually_fires()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RepositoryController::createTeamRepos → KILLED

137

1.1
Location : lambda$deleteRepos$2
Killed by : edu.ucsb.cs156.frontiers.controllers.RepositoryControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RepositoryControllerTests]/[method:delete_repos_notFound()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RepositoryController::lambda$deleteRepos$2 → KILLED

139

1.1
Location : deleteRepos
Killed by : edu.ucsb.cs156.frontiers.controllers.RepositoryControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RepositoryControllerTests]/[method:delete_repos_just_no_install_id()]
negated conditional → KILLED

2.2
Location : deleteRepos
Killed by : edu.ucsb.cs156.frontiers.controllers.RepositoryControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RepositoryControllerTests]/[method:delete_repos_job_actually_fires()]
negated conditional → KILLED

150

1.1
Location : deleteRepos
Killed by : edu.ucsb.cs156.frontiers.controllers.RepositoryControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RepositoryControllerTests]/[method:delete_repos_job_actually_fires()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RepositoryController::deleteRepos → KILLED

Active mutators

Tests examined


Report generated by PIT 1.17.0