CourseSecurity.java

1
package edu.ucsb.cs.scaffold.config;
2
3
import edu.ucsb.cs.scaffold.entity.Course;
4
import edu.ucsb.cs.scaffold.model.CurrentUser;
5
import edu.ucsb.cs.scaffold.repository.ConceptEdgeRepository;
6
import edu.ucsb.cs.scaffold.repository.ConceptRepository;
7
import edu.ucsb.cs.scaffold.repository.CourseRepository;
8
import edu.ucsb.cs.scaffold.repository.RosterStudentRepository;
9
import edu.ucsb.cs.scaffold.services.CurrentUserService;
10
import java.util.Collection;
11
import java.util.Optional;
12
import lombok.extern.slf4j.Slf4j;
13
import org.springframework.security.access.expression.method.MethodSecurityExpressionOperations;
14
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
15
import org.springframework.security.access.prepost.PreAuthorize;
16
import org.springframework.security.core.GrantedAuthority;
17
import org.springframework.stereotype.Component;
18
19
/**
20
 * CourseSecurity provides methods to check permissions for managing courses and roster students. It
21
 * uses the CurrentUserService to get the current user and RoleHierarchy to check roles.
22
 *
23
 * <p>The methods defined here are used as annotations (e.g. <code>
24
 *   @PreAuthorize("@CourseSecurity.hasManagePermissions(#root, #id)")</code>) in the
25
 * CourseController and RosterStudentController to enforce security checks.
26
 *
27
 * <p>Note that for a method with a courseId, you <em>still</em> need to verify in each method,
28
 * whether the course exists or not. These annotations will <em>only</em> check whether or not the
29
 * particular user has access to a particular course, for example.
30
 *
31
 * <p>When testing, use <code>@WithInstructorCoursePermissions</code> or <code>
32
 * @WithStaffCoursePermissions</code> to mock a user with the appropriate roles.
33
 */
34
@Slf4j
35
@Component("CourseSecurity")
36
public class CourseSecurity {
37
  private final CurrentUserService currentUserService;
38
  private final RoleHierarchy roleHierarchy;
39
  private final CourseRepository courseRepository;
40
  private final RosterStudentRepository rosterStudentRepository;
41
  private final ConceptRepository conceptRepository;
42
  private final ConceptEdgeRepository conceptEdgeRepository;
43
44
  public CourseSecurity(
45
      CurrentUserService currentUserService,
46
      RoleHierarchy roleHierarchy,
47
      CourseRepository courseRepository,
48
      RosterStudentRepository rosterStudentRepository,
49
      ConceptRepository conceptRepository,
50
      ConceptEdgeRepository conceptEdgeRepository) {
51
    this.currentUserService = currentUserService;
52
    this.roleHierarchy = roleHierarchy;
53
    this.courseRepository = courseRepository;
54
    this.rosterStudentRepository = rosterStudentRepository;
55
    this.conceptRepository = conceptRepository;
56
    this.conceptEdgeRepository = conceptEdgeRepository;
57
  }
58
59
  /**
60
   * Use this when you want to check whether the user is either a staff member, instructor or admin
61
   * for the course.
62
   *
63
   * @param operations
64
   * @param courseId
65
   * @return true if the user has manage permissions for the course, false otherwise.
66
   */
67
  @PreAuthorize("hasRole('ROLE_USER')")
68
  public Boolean hasManagePermissions(
69
      MethodSecurityExpressionOperations operations, Long courseId) {
70 1 1. hasManagePermissions : negated conditional → KILLED
    if (courseId == null) {
71
      // A null id can reach here from endpoints that take the courseId from a request body
72
      // (e.g. @PreAuthorize("... #dto.courseId")). Grant access so the controller can reject
73
      // the request with a proper validation error, mirroring the course-not-found case below.
74 1 1. hasManagePermissions : replaced Boolean return with False for edu/ucsb/cs/scaffold/config/CourseSecurity::hasManagePermissions → KILLED
      return true;
75
    }
76
    Optional<Course> course = courseRepository.findById(courseId);
77 1 1. hasManagePermissions : negated conditional → KILLED
    if (course.isEmpty()) {
78 1 1. hasManagePermissions : replaced Boolean return with False for edu/ucsb/cs/scaffold/config/CourseSecurity::hasManagePermissions → KILLED
      return true;
79
    }
80 2 1. hasManagePermissions : replaced Boolean return with False for edu/ucsb/cs/scaffold/config/CourseSecurity::hasManagePermissions → KILLED
2. hasManagePermissions : replaced Boolean return with True for edu/ucsb/cs/scaffold/config/CourseSecurity::hasManagePermissions → KILLED
    return baseHasManagePermissions(operations, course.get());
81
  }
82
83
  /**
84
   * Use this for operations that only an instructor can do, but not a staff member, such as adding
85
   * or deleting a course staff member.
86
   *
87
   * @param operations
88
   * @param courseId
89
   * @return true if the user has instructor permissions for the course, false otherwise.
90
   */
91
  @PreAuthorize("hasRole('ROLE_INSTRUCTOR')")
92
  public Boolean hasInstructorPermissions(
93
      MethodSecurityExpressionOperations operations, Long courseId) {
94
    CurrentUser currentUser = currentUserService.getCurrentUser();
95
    Collection<? extends GrantedAuthority> authorities =
96
        roleHierarchy.getReachableGrantedAuthorities(currentUser.getRoles());
97 3 1. lambda$hasInstructorPermissions$0 : replaced boolean return with true for edu/ucsb/cs/scaffold/config/CourseSecurity::lambda$hasInstructorPermissions$0 → KILLED
2. lambda$hasInstructorPermissions$0 : replaced boolean return with false for edu/ucsb/cs/scaffold/config/CourseSecurity::lambda$hasInstructorPermissions$0 → KILLED
3. hasInstructorPermissions : negated conditional → KILLED
    if (authorities.stream().anyMatch(role -> role.getAuthority().equals("ROLE_ADMIN"))) {
98 1 1. hasInstructorPermissions : replaced Boolean return with False for edu/ucsb/cs/scaffold/config/CourseSecurity::hasInstructorPermissions → KILLED
      return true;
99
    } else {
100
      Optional<Course> course = courseRepository.findById(courseId);
101 1 1. hasInstructorPermissions : negated conditional → KILLED
      if (course.isEmpty()) {
102 1 1. hasInstructorPermissions : replaced Boolean return with False for edu/ucsb/cs/scaffold/config/CourseSecurity::hasInstructorPermissions → KILLED
        return true;
103
      }
104 2 1. hasInstructorPermissions : replaced Boolean return with True for edu/ucsb/cs/scaffold/config/CourseSecurity::hasInstructorPermissions → KILLED
2. hasInstructorPermissions : replaced Boolean return with False for edu/ucsb/cs/scaffold/config/CourseSecurity::hasInstructorPermissions → KILLED
      return currentUser.getUser().getEmail().equals(course.get().getInstructorEmail());
105
    }
106
  }
107
108
  /**
109
   * This method checks if the current user has management permissions for the course associated
110
   * with the given rosterStudent. This allows us to create endpoints that just take a roster
111
   * student id, not a course id, and still check permissions. This one works for both staff and
112
   * instructor permissions.
113
   *
114
   * @param operations
115
   * @param rosterStudentId
116
   * @return
117
   */
118
  @PreAuthorize("hasRole('ROLE_USER')")
119
  public Boolean hasRosterStudentManagementPermissions(
120
      MethodSecurityExpressionOperations operations, Long rosterStudentId) {
121 2 1. hasRosterStudentManagementPermissions : replaced Boolean return with False for edu/ucsb/cs/scaffold/config/CourseSecurity::hasRosterStudentManagementPermissions → KILLED
2. hasRosterStudentManagementPermissions : replaced Boolean return with True for edu/ucsb/cs/scaffold/config/CourseSecurity::hasRosterStudentManagementPermissions → KILLED
    return rosterStudentRepository
122
        .findById(rosterStudentId)
123 2 1. lambda$hasRosterStudentManagementPermissions$1 : replaced Boolean return with True for edu/ucsb/cs/scaffold/config/CourseSecurity::lambda$hasRosterStudentManagementPermissions$1 → KILLED
2. lambda$hasRosterStudentManagementPermissions$1 : replaced Boolean return with False for edu/ucsb/cs/scaffold/config/CourseSecurity::lambda$hasRosterStudentManagementPermissions$1 → KILLED
        .map(rosterStudent -> baseHasManagePermissions(operations, rosterStudent.getCourse()))
124
        .orElse(true);
125
  }
126
127
  /**
128
   * This method checks if the current user has management permissions for the course associated
129
   * with the given concept, so that endpoints can take just a concept id. Works for both staff and
130
   * instructor permissions.
131
   *
132
   * @param operations
133
   * @param conceptId numeric id of the concept
134
   * @return
135
   */
136
  @PreAuthorize("hasRole('ROLE_USER')")
137
  public Boolean hasConceptManagementPermissions(
138
      MethodSecurityExpressionOperations operations, Long conceptId) {
139 2 1. hasConceptManagementPermissions : replaced Boolean return with True for edu/ucsb/cs/scaffold/config/CourseSecurity::hasConceptManagementPermissions → KILLED
2. hasConceptManagementPermissions : replaced Boolean return with False for edu/ucsb/cs/scaffold/config/CourseSecurity::hasConceptManagementPermissions → KILLED
    return conceptRepository
140
        .findById(conceptId)
141 2 1. lambda$hasConceptManagementPermissions$2 : replaced Boolean return with False for edu/ucsb/cs/scaffold/config/CourseSecurity::lambda$hasConceptManagementPermissions$2 → KILLED
2. lambda$hasConceptManagementPermissions$2 : replaced Boolean return with True for edu/ucsb/cs/scaffold/config/CourseSecurity::lambda$hasConceptManagementPermissions$2 → KILLED
        .map(concept -> baseHasManagePermissions(operations, concept.getCourse()))
142
        .orElse(true);
143
  }
144
145
  /**
146
   * This method checks if the current user has management permissions for the course associated
147
   * with the given concept edge, so that endpoints can take just a concept edge id. Works for both
148
   * staff and instructor permissions.
149
   *
150
   * @param operations
151
   * @param conceptEdgeId numeric id of the concept edge
152
   * @return
153
   */
154
  @PreAuthorize("hasRole('ROLE_USER')")
155
  public Boolean hasConceptEdgeManagementPermissions(
156
      MethodSecurityExpressionOperations operations, Long conceptEdgeId) {
157 2 1. hasConceptEdgeManagementPermissions : replaced Boolean return with False for edu/ucsb/cs/scaffold/config/CourseSecurity::hasConceptEdgeManagementPermissions → KILLED
2. hasConceptEdgeManagementPermissions : replaced Boolean return with True for edu/ucsb/cs/scaffold/config/CourseSecurity::hasConceptEdgeManagementPermissions → KILLED
    return conceptEdgeRepository
158
        .findById(conceptEdgeId)
159 2 1. lambda$hasConceptEdgeManagementPermissions$3 : replaced Boolean return with False for edu/ucsb/cs/scaffold/config/CourseSecurity::lambda$hasConceptEdgeManagementPermissions$3 → KILLED
2. lambda$hasConceptEdgeManagementPermissions$3 : replaced Boolean return with True for edu/ucsb/cs/scaffold/config/CourseSecurity::lambda$hasConceptEdgeManagementPermissions$3 → KILLED
        .map(edge -> baseHasManagePermissions(operations, edge.getCourse()))
160
        .orElse(true);
161
  }
162
163
  /**
164
   * This is a helper method that checks if the current user has management permissions for the
165
   * given course.
166
   *
167
   * @param operations
168
   * @param course
169
   * @return
170
   */
171
  public Boolean baseHasManagePermissions(
172
      MethodSecurityExpressionOperations operations, Course course) {
173
    CurrentUser currentUser = currentUserService.getCurrentUser();
174
    Collection<? extends GrantedAuthority> authorities =
175
        roleHierarchy.getReachableGrantedAuthorities(currentUser.getRoles());
176 3 1. baseHasManagePermissions : negated conditional → KILLED
2. lambda$baseHasManagePermissions$4 : replaced boolean return with true for edu/ucsb/cs/scaffold/config/CourseSecurity::lambda$baseHasManagePermissions$4 → KILLED
3. lambda$baseHasManagePermissions$4 : replaced boolean return with false for edu/ucsb/cs/scaffold/config/CourseSecurity::lambda$baseHasManagePermissions$4 → KILLED
    if (authorities.stream().anyMatch(role -> role.getAuthority().equals("ROLE_ADMIN"))) {
177 1 1. baseHasManagePermissions : replaced Boolean return with False for edu/ucsb/cs/scaffold/config/CourseSecurity::baseHasManagePermissions → KILLED
      return true;
178
    } else {
179
      if (course.getCourseStaff().stream()
180 3 1. lambda$baseHasManagePermissions$5 : replaced boolean return with false for edu/ucsb/cs/scaffold/config/CourseSecurity::lambda$baseHasManagePermissions$5 → KILLED
2. baseHasManagePermissions : negated conditional → KILLED
3. lambda$baseHasManagePermissions$5 : replaced boolean return with true for edu/ucsb/cs/scaffold/config/CourseSecurity::lambda$baseHasManagePermissions$5 → KILLED
          .anyMatch(staff -> staff.getEmail().equals(currentUser.getUser().getEmail()))) {
181 1 1. baseHasManagePermissions : replaced Boolean return with False for edu/ucsb/cs/scaffold/config/CourseSecurity::baseHasManagePermissions → KILLED
        return true;
182
      }
183 2 1. baseHasManagePermissions : replaced Boolean return with True for edu/ucsb/cs/scaffold/config/CourseSecurity::baseHasManagePermissions → KILLED
2. baseHasManagePermissions : replaced Boolean return with False for edu/ucsb/cs/scaffold/config/CourseSecurity::baseHasManagePermissions → KILLED
      return currentUser.getUser().getEmail().equals(course.getInstructorEmail());
184
    }
185
  }
186
}

Mutations

70

1.1
Location : hasManagePermissions
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:UnsuccessfulInstructor]/[method:instructor_cant_load_non_owned_course()]
negated conditional → KILLED

74

1.1
Location : hasManagePermissions
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:NullCourseId]/[method:null_course_id_is_allowed_through_for_controller_validation()]
replaced Boolean return with False for edu/ucsb/cs/scaffold/config/CourseSecurity::hasManagePermissions → KILLED

77

1.1
Location : hasManagePermissions
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:NotFound]/[method:null_on_null()]
negated conditional → KILLED

78

1.1
Location : hasManagePermissions
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:NotFound]/[method:null_on_null()]
replaced Boolean return with False for edu/ucsb/cs/scaffold/config/CourseSecurity::hasManagePermissions → KILLED

80

1.1
Location : hasManagePermissions
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:SuccessfulAdmin]/[method:instructor_can_load_owned_course()]
replaced Boolean return with False for edu/ucsb/cs/scaffold/config/CourseSecurity::hasManagePermissions → KILLED

2.2
Location : hasManagePermissions
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:UnsuccessfulInstructor]/[method:instructor_cant_load_non_owned_course()]
replaced Boolean return with True for edu/ucsb/cs/scaffold/config/CourseSecurity::hasManagePermissions → KILLED

97

1.1
Location : lambda$hasInstructorPermissions$0
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:UnsuccessfulInstructorPerms]/[method:instructor_cant_load_non_owned_course()]
replaced boolean return with true for edu/ucsb/cs/scaffold/config/CourseSecurity::lambda$hasInstructorPermissions$0 → KILLED

2.2
Location : lambda$hasInstructorPermissions$0
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:SuccessfulAdminPerms]/[method:instructor_can_load_owned_course()]
replaced boolean return with false for edu/ucsb/cs/scaffold/config/CourseSecurity::lambda$hasInstructorPermissions$0 → KILLED

3.3
Location : hasInstructorPermissions
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:UnsuccessfulInstructorPerms]/[method:instructor_cant_load_non_owned_course()]
negated conditional → KILLED

98

1.1
Location : hasInstructorPermissions
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:SuccessfulAdminPerms]/[method:instructor_can_load_owned_course()]
replaced Boolean return with False for edu/ucsb/cs/scaffold/config/CourseSecurity::hasInstructorPermissions → KILLED

101

1.1
Location : hasInstructorPermissions
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:NotFoundInstructor]/[method:null_on_null()]
negated conditional → KILLED

102

1.1
Location : hasInstructorPermissions
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:NotFoundInstructor]/[method:null_on_null()]
replaced Boolean return with False for edu/ucsb/cs/scaffold/config/CourseSecurity::hasInstructorPermissions → KILLED

104

1.1
Location : hasInstructorPermissions
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:UnsuccessfulInstructorPerms]/[method:instructor_cant_load_non_owned_course()]
replaced Boolean return with True for edu/ucsb/cs/scaffold/config/CourseSecurity::hasInstructorPermissions → KILLED

2.2
Location : hasInstructorPermissions
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:SuccessfulInstructorPerms]/[method:instructor_can_load_owned_course()]
replaced Boolean return with False for edu/ucsb/cs/scaffold/config/CourseSecurity::hasInstructorPermissions → KILLED

121

1.1
Location : hasRosterStudentManagementPermissions
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:NotFoundRosterStudent]/[method:null_on_null()]
replaced Boolean return with False for edu/ucsb/cs/scaffold/config/CourseSecurity::hasRosterStudentManagementPermissions → KILLED

2.2
Location : hasRosterStudentManagementPermissions
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:CorrectPassRosterStudent]/[method:returns_properly()]
replaced Boolean return with True for edu/ucsb/cs/scaffold/config/CourseSecurity::hasRosterStudentManagementPermissions → KILLED

123

1.1
Location : lambda$hasRosterStudentManagementPermissions$1
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:CorrectPassRosterStudent]/[method:returns_properly()]
replaced Boolean return with True for edu/ucsb/cs/scaffold/config/CourseSecurity::lambda$hasRosterStudentManagementPermissions$1 → KILLED

2.2
Location : lambda$hasRosterStudentManagementPermissions$1
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:FalseButExistsRosterStudent]/[method:returns_properly()]
replaced Boolean return with False for edu/ucsb/cs/scaffold/config/CourseSecurity::lambda$hasRosterStudentManagementPermissions$1 → KILLED

139

1.1
Location : hasConceptManagementPermissions
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:DeniedConcept]/[method:non_owner_is_denied()]
replaced Boolean return with True for edu/ucsb/cs/scaffold/config/CourseSecurity::hasConceptManagementPermissions → KILLED

2.2
Location : hasConceptManagementPermissions
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:NotFoundConcept]/[method:permission_granted_but_load_throws_when_concept_missing()]
replaced Boolean return with False for edu/ucsb/cs/scaffold/config/CourseSecurity::hasConceptManagementPermissions → KILLED

141

1.1
Location : lambda$hasConceptManagementPermissions$2
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:AllowedConcept]/[method:course_instructor_is_allowed()]
replaced Boolean return with False for edu/ucsb/cs/scaffold/config/CourseSecurity::lambda$hasConceptManagementPermissions$2 → KILLED

2.2
Location : lambda$hasConceptManagementPermissions$2
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:DeniedConcept]/[method:non_owner_is_denied()]
replaced Boolean return with True for edu/ucsb/cs/scaffold/config/CourseSecurity::lambda$hasConceptManagementPermissions$2 → KILLED

157

1.1
Location : hasConceptEdgeManagementPermissions
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:NotFoundConceptEdge]/[method:permission_granted_but_load_throws_when_edge_missing()]
replaced Boolean return with False for edu/ucsb/cs/scaffold/config/CourseSecurity::hasConceptEdgeManagementPermissions → KILLED

2.2
Location : hasConceptEdgeManagementPermissions
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:DeniedConceptEdge]/[method:non_owner_is_denied()]
replaced Boolean return with True for edu/ucsb/cs/scaffold/config/CourseSecurity::hasConceptEdgeManagementPermissions → KILLED

159

1.1
Location : lambda$hasConceptEdgeManagementPermissions$3
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:AllowedConceptEdge]/[method:course_instructor_is_allowed()]
replaced Boolean return with False for edu/ucsb/cs/scaffold/config/CourseSecurity::lambda$hasConceptEdgeManagementPermissions$3 → KILLED

2.2
Location : lambda$hasConceptEdgeManagementPermissions$3
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:DeniedConceptEdge]/[method:non_owner_is_denied()]
replaced Boolean return with True for edu/ucsb/cs/scaffold/config/CourseSecurity::lambda$hasConceptEdgeManagementPermissions$3 → KILLED

176

1.1
Location : baseHasManagePermissions
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:SuccessfulAdmin]/[method:instructor_can_load_owned_course()]
negated conditional → KILLED

2.2
Location : lambda$baseHasManagePermissions$4
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:DeniedConcept]/[method:non_owner_is_denied()]
replaced boolean return with true for edu/ucsb/cs/scaffold/config/CourseSecurity::lambda$baseHasManagePermissions$4 → KILLED

3.3
Location : lambda$baseHasManagePermissions$4
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:SuccessfulAdmin]/[method:instructor_can_load_owned_course()]
replaced boolean return with false for edu/ucsb/cs/scaffold/config/CourseSecurity::lambda$baseHasManagePermissions$4 → KILLED

177

1.1
Location : baseHasManagePermissions
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:SuccessfulAdmin]/[method:instructor_can_load_owned_course()]
replaced Boolean return with False for edu/ucsb/cs/scaffold/config/CourseSecurity::baseHasManagePermissions → KILLED

180

1.1
Location : lambda$baseHasManagePermissions$5
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:SuccessfulCourseStaff]/[method:instructor_can_load_owned_course()]
replaced boolean return with false for edu/ucsb/cs/scaffold/config/CourseSecurity::lambda$baseHasManagePermissions$5 → KILLED

2.2
Location : baseHasManagePermissions
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:DeniedConcept]/[method:non_owner_is_denied()]
negated conditional → KILLED

3.3
Location : lambda$baseHasManagePermissions$5
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:UnsuccessfulInstructor]/[method:instructor_cant_load_non_owned_course()]
replaced boolean return with true for edu/ucsb/cs/scaffold/config/CourseSecurity::lambda$baseHasManagePermissions$5 → KILLED

181

1.1
Location : baseHasManagePermissions
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:SuccessfulCourseStaff]/[method:instructor_can_load_owned_course()]
replaced Boolean return with False for edu/ucsb/cs/scaffold/config/CourseSecurity::baseHasManagePermissions → KILLED

183

1.1
Location : baseHasManagePermissions
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:DeniedConcept]/[method:non_owner_is_denied()]
replaced Boolean return with True for edu/ucsb/cs/scaffold/config/CourseSecurity::baseHasManagePermissions → KILLED

2.2
Location : baseHasManagePermissions
Killed by : edu.ucsb.cs.scaffold.config.CourseSecurityTests.[engine:junit-jupiter]/[class:edu.ucsb.cs.scaffold.config.CourseSecurityTests]/[nested-class:SuccessfulInstructor]/[method:instructor_can_load_owned_course()]
replaced Boolean return with False for edu/ucsb/cs/scaffold/config/CourseSecurity::baseHasManagePermissions → KILLED

Active mutators

Tests examined


Report generated by PIT 1.17.0