Skip to content

Commit d541fde

Browse files
authored
Merge pull request #2765 from objectcomputing/develop
Update release branch from develop
2 parents ee61de7 + c7dd3a0 commit d541fde

17 files changed

+244
-235
lines changed

server/build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ plugins {
77
id "jacoco"
88
}
99

10-
version "0.8.7"
10+
version "0.8.8"
1111
group "com.objectcomputing.checkins"
1212

1313
repositories {

server/src/main/java/com/objectcomputing/checkins/services/feedback_answer/FeedbackAnswerServices.java

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.objectcomputing.checkins.services.feedback_answer;
22

3+
import com.objectcomputing.checkins.services.feedback_request.FeedbackRequest;
34
import io.micronaut.core.annotation.Nullable;
45

56
import java.util.List;
@@ -14,4 +15,6 @@ public interface FeedbackAnswerServices {
1415
FeedbackAnswer getById(UUID id);
1516

1617
List<FeedbackAnswer> findByValues(@Nullable UUID questionId, @Nullable UUID requestId);
18+
19+
boolean getIsPermitted(FeedbackRequest feedbackRequest);
1720
}

server/src/main/java/com/objectcomputing/checkins/services/feedback_answer/FeedbackAnswerServicesImpl.java

+29-8
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ public List<FeedbackAnswer> findByValues(@Nullable UUID questionId, @Nullable UU
113113
boolean isRequesteesSupervisor = requesteeId != null ? memberProfileServices.getSupervisorsForId(requesteeId).stream().anyMatch(profile -> currentUserId.equals(profile.getId())) : false;
114114
MemberProfile requestee = memberProfileServices.getById(requesteeId);
115115
final UUID requesteePDL = requestee.getPdlId();
116-
if (currentUserServices.isAdmin() || currentUserId.equals(requesteePDL) || isRequesteesSupervisor || requestCreatorId.equals(currentUserId) || recipientId.equals(currentUserId)) {
116+
if (currentUserServices.isAdmin() || currentUserId.equals(requesteePDL) || isRequesteesSupervisor || requestCreatorId.equals(currentUserId) || recipientId.equals(currentUserId) || feedbackRequestServices.selfRevieweeIsCurrentUserReviewee(feedbackRequest, currentUserId)) {
117117
response.addAll(feedbackAnswerRepository.getByQuestionIdAndRequestId(Util.nullSafeUUIDToString(questionId), Util.nullSafeUUIDToString(requestId)));
118118
return response;
119119
}
@@ -145,15 +145,36 @@ public boolean updateIsPermitted(FeedbackRequest feedbackRequest) {
145145
}
146146

147147
public boolean getIsPermitted(FeedbackRequest feedbackRequest) {
148-
final boolean isAdmin = currentUserServices.isAdmin();
149-
final UUID requestCreatorId = feedbackRequest.getCreatorId();
150-
UUID requesteeId = feedbackRequest.getRequesteeId();
151-
MemberProfile requestee = memberProfileServices.getById(requesteeId);
148+
// Admins can always get questions and answers.
149+
if (currentUserServices.isAdmin()) {
150+
return true;
151+
}
152+
153+
// See if the current user is the requestee's supervisor.
154+
final UUID requesteeId = feedbackRequest.getRequesteeId();
152155
final UUID currentUserId = currentUserServices.getCurrentUser().getId();
156+
if (requesteeId != null &&
157+
memberProfileServices.getSupervisorsForId(requesteeId).stream().anyMatch(profile -> currentUserId.equals(profile.getId()))) {
158+
return true;
159+
}
160+
161+
// See if the current user is the requestee's PDL.
162+
final MemberProfile requestee = memberProfileServices.getById(requesteeId);
163+
if (currentUserId.equals(requestee.getPdlId())) {
164+
return true;
165+
}
166+
167+
// See if the current user is the request creator or the recipient of
168+
// the request.
169+
final UUID requestCreatorId = feedbackRequest.getCreatorId();
153170
final UUID recipientId = feedbackRequest.getRecipientId();
154-
boolean isRequesteesSupervisor = requesteeId != null ? memberProfileServices.getSupervisorsForId(requesteeId).stream().anyMatch(profile -> currentUserId.equals(profile.getId())) : false;
155-
final UUID requesteePDL = requestee.getPdlId();
171+
if (requestCreatorId.equals(currentUserId) ||
172+
recipientId.equals(currentUserId)) {
173+
return true;
174+
}
175+
156176

157-
return isAdmin || currentUserId.equals(requesteePDL) || isRequesteesSupervisor || requestCreatorId.equals(currentUserId) || recipientId.equals(currentUserId);
177+
return feedbackRequestServices.selfRevieweeIsCurrentUserReviewee(
178+
feedbackRequest, currentUserId);
158179
}
159180
}

server/src/main/java/com/objectcomputing/checkins/services/feedback_answer/question_and_answer/QuestionAndAnswerServicesImpl.java

+2-16
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public QuestionAndAnswerServicesImpl(FeedbackAnswerServices feedbackAnswerServic
4242
@Override
4343
public List<Tuple> getAllQuestionsAndAnswers(UUID requestId) {
4444
FeedbackRequest feedbackRequest = feedbackRequestServices.getById(requestId);
45-
if (!getIsPermitted(feedbackRequest)) {
45+
if (!feedbackAnswerServices.getIsPermitted(feedbackRequest)) {
4646
throw new PermissionException(NOT_AUTHORIZED_MSG);
4747
}
4848
List<TemplateQuestion> templateQuestions = templateQuestionServices.findByFields(feedbackRequest.getTemplateId());
@@ -77,7 +77,7 @@ public Tuple getQuestionAndAnswer(@Nullable UUID requestId, @Nullable UUID quest
7777
TemplateQuestion question = new TemplateQuestion();
7878
FeedbackRequest feedbackRequest = feedbackRequestServices.getById(requestId);
7979

80-
if (!getIsPermitted(feedbackRequest)) {
80+
if (!feedbackAnswerServices.getIsPermitted(feedbackRequest)) {
8181
throw new PermissionException(NOT_AUTHORIZED_MSG);
8282
}
8383

@@ -101,18 +101,4 @@ public Tuple getQuestionAndAnswer(@Nullable UUID requestId, @Nullable UUID quest
101101
}
102102
return new Tuple(question, returnedAnswer);
103103
}
104-
105-
public boolean getIsPermitted(FeedbackRequest feedbackRequest) {
106-
final boolean isAdmin = currentUserServices.isAdmin();
107-
final UUID requestCreatorId = feedbackRequest.getCreatorId();
108-
UUID requesteeId = feedbackRequest.getRequesteeId();
109-
MemberProfile requestee = memberProfileServices.getById(requesteeId);
110-
final UUID currentUserId = currentUserServices.getCurrentUser().getId();
111-
final UUID recipientId = feedbackRequest.getRecipientId();
112-
boolean isRequesteesSupervisor = requesteeId != null ? memberProfileServices.getSupervisorsForId(requesteeId).stream().anyMatch(profile -> currentUserId.equals(profile.getId())) : false;
113-
final UUID requesteePDL = requestee.getPdlId();
114-
115-
return isAdmin || currentUserId.equals(requesteePDL) || isRequesteesSupervisor || requestCreatorId.equals(currentUserId) || recipientId.equals(currentUserId);
116-
}
117-
118104
}

server/src/main/java/com/objectcomputing/checkins/services/feedback_request/FeedbackRequestServices.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,7 @@ public interface FeedbackRequestServices {
1414
FeedbackRequest getById(UUID id);
1515

1616
List<FeedbackRequest> findByValues(UUID creatorId, UUID requesteeId, UUID recipientId, LocalDate oldestDate, UUID reviewPeriodId, UUID templateId, List<UUID> requesteeIds);
17-
}
17+
18+
boolean selfRevieweeIsCurrentUserReviewee(FeedbackRequest request,
19+
UUID currentUserId);
20+
}

server/src/main/java/com/objectcomputing/checkins/services/feedback_request/FeedbackRequestServicesImpl.java

+33-10
Original file line numberDiff line numberDiff line change
@@ -272,10 +272,8 @@ public FeedbackRequest getById(UUID id) {
272272
if (feedbackReq.isEmpty()) {
273273
throw new NotFoundException("No feedback req with id " + id);
274274
}
275-
final LocalDate sendDate = feedbackReq.get().getSendDate();
276-
final UUID requesteeId = feedbackReq.get().getRequesteeId();
277-
final UUID recipientId = feedbackReq.get().getRecipientId();
278-
if (!getIsPermitted(requesteeId, recipientId, sendDate)) {
275+
276+
if (!getIsPermitted(feedbackReq.get())) {
279277
throw new PermissionException(NOT_AUTHORIZED_MSG);
280278
}
281279

@@ -303,9 +301,12 @@ public List<FeedbackRequest> findByValues(UUID creatorId, UUID requesteeId, UUID
303301
if (currentUserServices.isAdmin()) {
304302
visible = true;
305303
} else if (request != null) {
306-
if (currentUserId.equals(request.getCreatorId())) visible = true;
307-
if (isSupervisor(request.getRequesteeId(), currentUserId)) visible = true;
308-
if (currentUserId.equals(request.getRecipientId())) visible = true;
304+
if (currentUserId.equals(request.getCreatorId()) ||
305+
isSupervisor(request.getRequesteeId(), currentUserId) ||
306+
currentUserId.equals(request.getRecipientId()) ||
307+
selfRevieweeIsCurrentUserReviewee(request, currentUserId)) {
308+
visible = true;
309+
}
309310
}
310311
return visible;
311312
}).toList();
@@ -318,6 +319,23 @@ private boolean isSupervisor(UUID requesteeId, UUID currentUserId) {
318319
&& memberProfileServices.getSupervisorsForId(requesteeId).stream().anyMatch(profile -> currentUserId.equals(profile.getId()));
319320
}
320321

322+
public boolean selfRevieweeIsCurrentUserReviewee(FeedbackRequest request,
323+
UUID currentUserId) {
324+
// If we are looking at a self-review request, see if there is a review
325+
// request in the same review period that is assigned to the current
326+
// user and the requestee is the same as the self-review request. If
327+
// so, this user is allowed to see the self-review request.
328+
if (request.getRecipientId().equals(request.getRequesteeId())) {
329+
List<FeedbackRequest> other = feedbackReqRepository.findByValues(
330+
null, request.getRecipientId().toString(),
331+
currentUserId.toString(), null,
332+
Util.nullSafeUUIDToString(request.getReviewPeriodId()),
333+
null);
334+
return (other.size() == 1);
335+
}
336+
return false;
337+
}
338+
321339
private boolean createIsPermitted(UUID requesteeId) {
322340
final boolean isAdmin = currentUserServices.isAdmin();
323341
final UUID currentUserId = currentUserServices.getCurrentUser().getId();
@@ -329,16 +347,21 @@ private boolean createIsPermitted(UUID requesteeId) {
329347
return isAdmin || currentUserId.equals(requesteePDL) || isRequesteesSupervisor || currentUserId.equals(requesteeId);
330348
}
331349

332-
private boolean getIsPermitted(UUID requesteeId, UUID recipientId, LocalDate sendDate) {
333-
LocalDate today = LocalDate.now();
350+
private boolean getIsPermitted(FeedbackRequest feedbackReq) {
351+
final LocalDate sendDate = feedbackReq.getSendDate();
352+
final UUID requesteeId = feedbackReq.getRequesteeId();
353+
final UUID recipientId = feedbackReq.getRecipientId();
354+
final LocalDate today = LocalDate.now();
334355
final UUID currentUserId = currentUserServices.getCurrentUser().getId();
335356

336357
// The recipient can only access the feedback request after it has been sent
337358
if (sendDate.isAfter(today) && currentUserId.equals(recipientId)) {
338359
throw new PermissionException("You are not permitted to access this request before the send date.");
339360
}
340361

341-
return createIsPermitted(requesteeId) || currentUserId.equals(recipientId);
362+
return createIsPermitted(requesteeId) ||
363+
currentUserId.equals(recipientId) ||
364+
selfRevieweeIsCurrentUserReviewee(feedbackReq, currentUserId);
342365
}
343366

344367
private boolean updateDueDateIsPermitted(FeedbackRequest feedbackRequest) {

server/src/main/java/com/objectcomputing/checkins/services/memberprofile/MemberProfileServices.java

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
public interface MemberProfileServices {
1010
MemberProfile getById(UUID id);
1111

12+
MemberProfile findByWorkEmail(@NotNull String workEmail);
13+
1214
Set<MemberProfile> findByValues(String firstName, String lastName, String title,
1315
UUID pdlId, String workEmail, UUID supervisorId, Boolean terminated);
1416

server/src/main/java/com/objectcomputing/checkins/services/memberprofile/MemberProfileServicesImpl.java

+14
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import com.objectcomputing.checkins.services.role.RoleServices;
1414
import com.objectcomputing.checkins.services.team.member.TeamMemberServices;
1515
import io.micronaut.cache.annotation.CacheConfig;
16+
import io.micronaut.cache.annotation.CacheInvalidate;
1617
import io.micronaut.cache.annotation.Cacheable;
1718
import io.micronaut.core.annotation.Nullable;
1819
import jakarta.inject.Named;
@@ -55,6 +56,7 @@ public MemberProfileServicesImpl(MemberProfileRepository memberProfileRepository
5556
}
5657

5758
@Override
59+
@Cacheable
5860
public MemberProfile getById(@NotNull UUID id) {
5961
Optional<MemberProfile> optional = memberProfileRepository.findById(id);
6062
if (optional.isEmpty()) {
@@ -67,6 +69,14 @@ public MemberProfile getById(@NotNull UUID id) {
6769
return memberProfile;
6870
}
6971

72+
@Cacheable
73+
@Override
74+
public MemberProfile findByWorkEmail(@NotNull String workEmail) {
75+
return memberProfileRepository.findByWorkEmail(workEmail).orElseThrow(() ->
76+
new NotFoundException("Member not found")
77+
);
78+
}
79+
7080
@Override
7181
public Set<MemberProfile> findByValues(@Nullable String firstName,
7282
@Nullable String lastName,
@@ -86,6 +96,7 @@ public Set<MemberProfile> findByValues(@Nullable String firstName,
8696
}
8797

8898
@Override
99+
@CacheInvalidate(cacheNames = {"member-cache"})
89100
public MemberProfile saveProfile(MemberProfile memberProfile) {
90101
MemberProfile emailProfile = memberProfileRepository.findByWorkEmail(memberProfile.getWorkEmail()).orElse(null);
91102

@@ -152,6 +163,7 @@ public void emailAssignment(MemberProfile member, boolean isPDL) {
152163
}
153164

154165
@Override
166+
@CacheInvalidate(cacheNames = {"member-cache"})
155167
public boolean deleteProfile(@NotNull UUID id) {
156168
if (!currentUserServices.isAdmin()) {
157169
throw new PermissionException("Requires admin privileges");
@@ -183,6 +195,7 @@ public boolean deleteProfile(@NotNull UUID id) {
183195
}
184196

185197
@Override
198+
@Cacheable(parameters = {"firstName", "lastName"})
186199
public MemberProfile findByName(@NotNull String firstName, @NotNull String lastName) {
187200
List<MemberProfile> searchResult = memberProfileRepository.search(firstName, null, lastName,
188201
null, null, null, null, null, null);
@@ -222,6 +235,7 @@ public List<MemberProfile> getSubordinatesForId(UUID id) {
222235
}
223236

224237
@Override
238+
@CacheInvalidate(cacheNames = {"member-cache"})
225239
public MemberProfile updateProfile(MemberProfile memberProfile) {
226240
return memberProfileRepository.update(memberProfile);
227241
}

server/src/main/java/com/objectcomputing/checkins/services/reports/CSVProcessor.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package com.objectcomputing.checkins.services.reports;
22

3-
import com.objectcomputing.checkins.services.memberprofile.MemberProfileRepository;
43
import com.objectcomputing.checkins.exceptions.BadArgException;
54

5+
import com.objectcomputing.checkins.services.memberprofile.MemberProfileServices;
66
import org.apache.commons.csv.CSVFormat;
77
import org.apache.commons.csv.CSVParser;
88

@@ -18,7 +18,7 @@
1818

1919
abstract class CSVProcessor {
2020

21-
public void load(MemberProfileRepository memberProfileRepository,
21+
public void load(MemberProfileServices memberProfileServices,
2222
ByteBuffer dataSource) throws IOException,
2323
BadArgException {
2424
ByteArrayInputStream stream = new ByteArrayInputStream(dataSource.array());
@@ -30,10 +30,10 @@ public void load(MemberProfileRepository memberProfileRepository,
3030
.setNullString("")
3131
.build()
3232
.parse(input);
33-
loadImpl(memberProfileRepository, csvParser);
33+
loadImpl(memberProfileServices, csvParser);
3434
}
3535

36-
protected abstract void loadImpl(MemberProfileRepository memberProfileRepository, CSVParser csvParser) throws BadArgException;
36+
protected abstract void loadImpl(MemberProfileServices memberProfileServices, CSVParser csvParser) throws BadArgException;
3737

3838
protected LocalDate parseDate(String date) {
3939
List<String> formatStrings = List.of("yyyy", "M/d/yyyy");
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
package com.objectcomputing.checkins.services.reports;
22

3+
import com.objectcomputing.checkins.exceptions.NotFoundException;
34
import com.objectcomputing.checkins.services.memberprofile.MemberProfile;
4-
import com.objectcomputing.checkins.services.memberprofile.MemberProfileRepository;
55
import com.objectcomputing.checkins.exceptions.BadArgException;
66

7+
import com.objectcomputing.checkins.services.memberprofile.MemberProfileServices;
78
import io.micronaut.core.annotation.Introspected;
89
import org.apache.commons.csv.CSVParser;
910
import org.apache.commons.csv.CSVRecord;
@@ -12,10 +13,7 @@
1213
import org.slf4j.LoggerFactory;
1314

1415
import java.time.LocalDate;
15-
import java.util.ArrayList;
16-
import java.util.List;
17-
import java.util.UUID;
18-
import java.util.Optional;
16+
import java.util.*;
1917

2018
public class CompensationHistory extends CSVProcessor {
2119

@@ -32,41 +30,39 @@ public record Compensation(
3230
private final List<Compensation> history = new ArrayList<>();
3331

3432
@Override
35-
protected void loadImpl(MemberProfileRepository memberProfileRepository,
33+
protected void loadImpl(MemberProfileServices memberProfileServices,
3634
CSVParser csvParser) throws BadArgException {
37-
history.clear();
38-
for (CSVRecord csvRecord : csvParser) {
39-
try {
40-
String emailAddress = csvRecord.get("emailAddress");
41-
Optional<MemberProfile> memberProfile =
42-
memberProfileRepository.findByWorkEmail(emailAddress);
43-
if (memberProfile.isPresent()) {
44-
String startDate = csvRecord.get("startDate");
45-
LocalDate date = parseDate(startDate);
46-
if (date == null) {
47-
LOG.error("Unable to parse date: {}", startDate);
48-
} else {
49-
String value = csvRecord.get("compensation");
50-
Compensation comp = new Compensation(
51-
memberProfile.get().getId(),
52-
date,
53-
value == null ? null : value.replaceAll("[^\\d\\.,]", ""),
54-
csvRecord.get("totalComp")
55-
);
56-
history.add(comp);
35+
history.clear();
36+
for (CSVRecord csvRecord : csvParser) {
37+
String emailAddress = null;
38+
try {
39+
emailAddress = csvRecord.get("emailAddress");
40+
MemberProfile memberProfile = memberProfileServices.findByWorkEmail(emailAddress);
41+
String startDate = csvRecord.get("startDate");
42+
LocalDate date = parseDate(startDate);
43+
if (date == null) {
44+
LOG.error("Unable to parse date: {}", startDate);
45+
} else {
46+
String value = csvRecord.get("compensation");
47+
Compensation comp = new Compensation(
48+
memberProfile.getId(),
49+
date,
50+
value == null ? null : value.replaceAll("[^\\d\\.,]", ""),
51+
csvRecord.get("totalComp")
52+
);
53+
history.add(comp);
54+
}
55+
} catch (NotFoundException nfe) {
56+
LOG.error("Unable to find a profile for {}", emailAddress);
57+
} catch (IllegalArgumentException ex) {
58+
throw new BadArgException("Unable to parse the compensation history");
5759
}
58-
} else {
59-
LOG.error("Unable to find a profile for {}", emailAddress);
60-
}
61-
} catch(IllegalArgumentException ex) {
62-
throw new BadArgException("Unable to parse the compensation history");
6360
}
64-
}
6561
}
6662

6763
public List<Compensation> getHistory(UUID memberId) {
68-
return history.stream()
69-
.filter(entry -> entry.memberId().equals(memberId))
70-
.toList();
64+
return history.stream()
65+
.filter(entry -> entry.memberId().equals(memberId))
66+
.toList();
7167
}
7268
}

0 commit comments

Comments
 (0)