Skip to content

Commit

Permalink
Merge pull request #2766 from objectcomputing/release/0.8
Browse files Browse the repository at this point in the history
Release v0.8.8
  • Loading branch information
mkimberlin authored Nov 13, 2024
2 parents dee0ca8 + 15fe0fc commit 85e7d17
Show file tree
Hide file tree
Showing 17 changed files with 244 additions and 235 deletions.
2 changes: 1 addition & 1 deletion server/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ plugins {
id "jacoco"
}

version "0.8.7"
version "0.8.8"
group "com.objectcomputing.checkins"

repositories {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.objectcomputing.checkins.services.feedback_answer;

import com.objectcomputing.checkins.services.feedback_request.FeedbackRequest;
import io.micronaut.core.annotation.Nullable;

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

List<FeedbackAnswer> findByValues(@Nullable UUID questionId, @Nullable UUID requestId);

boolean getIsPermitted(FeedbackRequest feedbackRequest);
}
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public List<FeedbackAnswer> findByValues(@Nullable UUID questionId, @Nullable UU
boolean isRequesteesSupervisor = requesteeId != null ? memberProfileServices.getSupervisorsForId(requesteeId).stream().anyMatch(profile -> currentUserId.equals(profile.getId())) : false;
MemberProfile requestee = memberProfileServices.getById(requesteeId);
final UUID requesteePDL = requestee.getPdlId();
if (currentUserServices.isAdmin() || currentUserId.equals(requesteePDL) || isRequesteesSupervisor || requestCreatorId.equals(currentUserId) || recipientId.equals(currentUserId)) {
if (currentUserServices.isAdmin() || currentUserId.equals(requesteePDL) || isRequesteesSupervisor || requestCreatorId.equals(currentUserId) || recipientId.equals(currentUserId) || feedbackRequestServices.selfRevieweeIsCurrentUserReviewee(feedbackRequest, currentUserId)) {
response.addAll(feedbackAnswerRepository.getByQuestionIdAndRequestId(Util.nullSafeUUIDToString(questionId), Util.nullSafeUUIDToString(requestId)));
return response;
}
Expand Down Expand Up @@ -145,15 +145,36 @@ public boolean updateIsPermitted(FeedbackRequest feedbackRequest) {
}

public boolean getIsPermitted(FeedbackRequest feedbackRequest) {
final boolean isAdmin = currentUserServices.isAdmin();
final UUID requestCreatorId = feedbackRequest.getCreatorId();
UUID requesteeId = feedbackRequest.getRequesteeId();
MemberProfile requestee = memberProfileServices.getById(requesteeId);
// Admins can always get questions and answers.
if (currentUserServices.isAdmin()) {
return true;
}

// See if the current user is the requestee's supervisor.
final UUID requesteeId = feedbackRequest.getRequesteeId();
final UUID currentUserId = currentUserServices.getCurrentUser().getId();
if (requesteeId != null &&
memberProfileServices.getSupervisorsForId(requesteeId).stream().anyMatch(profile -> currentUserId.equals(profile.getId()))) {
return true;
}

// See if the current user is the requestee's PDL.
final MemberProfile requestee = memberProfileServices.getById(requesteeId);
if (currentUserId.equals(requestee.getPdlId())) {
return true;
}

// See if the current user is the request creator or the recipient of
// the request.
final UUID requestCreatorId = feedbackRequest.getCreatorId();
final UUID recipientId = feedbackRequest.getRecipientId();
boolean isRequesteesSupervisor = requesteeId != null ? memberProfileServices.getSupervisorsForId(requesteeId).stream().anyMatch(profile -> currentUserId.equals(profile.getId())) : false;
final UUID requesteePDL = requestee.getPdlId();
if (requestCreatorId.equals(currentUserId) ||
recipientId.equals(currentUserId)) {
return true;
}


return isAdmin || currentUserId.equals(requesteePDL) || isRequesteesSupervisor || requestCreatorId.equals(currentUserId) || recipientId.equals(currentUserId);
return feedbackRequestServices.selfRevieweeIsCurrentUserReviewee(
feedbackRequest, currentUserId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public QuestionAndAnswerServicesImpl(FeedbackAnswerServices feedbackAnswerServic
@Override
public List<Tuple> getAllQuestionsAndAnswers(UUID requestId) {
FeedbackRequest feedbackRequest = feedbackRequestServices.getById(requestId);
if (!getIsPermitted(feedbackRequest)) {
if (!feedbackAnswerServices.getIsPermitted(feedbackRequest)) {
throw new PermissionException(NOT_AUTHORIZED_MSG);
}
List<TemplateQuestion> templateQuestions = templateQuestionServices.findByFields(feedbackRequest.getTemplateId());
Expand Down Expand Up @@ -77,7 +77,7 @@ public Tuple getQuestionAndAnswer(@Nullable UUID requestId, @Nullable UUID quest
TemplateQuestion question = new TemplateQuestion();
FeedbackRequest feedbackRequest = feedbackRequestServices.getById(requestId);

if (!getIsPermitted(feedbackRequest)) {
if (!feedbackAnswerServices.getIsPermitted(feedbackRequest)) {
throw new PermissionException(NOT_AUTHORIZED_MSG);
}

Expand All @@ -101,18 +101,4 @@ public Tuple getQuestionAndAnswer(@Nullable UUID requestId, @Nullable UUID quest
}
return new Tuple(question, returnedAnswer);
}

public boolean getIsPermitted(FeedbackRequest feedbackRequest) {
final boolean isAdmin = currentUserServices.isAdmin();
final UUID requestCreatorId = feedbackRequest.getCreatorId();
UUID requesteeId = feedbackRequest.getRequesteeId();
MemberProfile requestee = memberProfileServices.getById(requesteeId);
final UUID currentUserId = currentUserServices.getCurrentUser().getId();
final UUID recipientId = feedbackRequest.getRecipientId();
boolean isRequesteesSupervisor = requesteeId != null ? memberProfileServices.getSupervisorsForId(requesteeId).stream().anyMatch(profile -> currentUserId.equals(profile.getId())) : false;
final UUID requesteePDL = requestee.getPdlId();

return isAdmin || currentUserId.equals(requesteePDL) || isRequesteesSupervisor || requestCreatorId.equals(currentUserId) || recipientId.equals(currentUserId);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,7 @@ public interface FeedbackRequestServices {
FeedbackRequest getById(UUID id);

List<FeedbackRequest> findByValues(UUID creatorId, UUID requesteeId, UUID recipientId, LocalDate oldestDate, UUID reviewPeriodId, UUID templateId, List<UUID> requesteeIds);
}

boolean selfRevieweeIsCurrentUserReviewee(FeedbackRequest request,
UUID currentUserId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -272,10 +272,8 @@ public FeedbackRequest getById(UUID id) {
if (feedbackReq.isEmpty()) {
throw new NotFoundException("No feedback req with id " + id);
}
final LocalDate sendDate = feedbackReq.get().getSendDate();
final UUID requesteeId = feedbackReq.get().getRequesteeId();
final UUID recipientId = feedbackReq.get().getRecipientId();
if (!getIsPermitted(requesteeId, recipientId, sendDate)) {

if (!getIsPermitted(feedbackReq.get())) {
throw new PermissionException(NOT_AUTHORIZED_MSG);
}

Expand Down Expand Up @@ -303,9 +301,12 @@ public List<FeedbackRequest> findByValues(UUID creatorId, UUID requesteeId, UUID
if (currentUserServices.isAdmin()) {
visible = true;
} else if (request != null) {
if (currentUserId.equals(request.getCreatorId())) visible = true;
if (isSupervisor(request.getRequesteeId(), currentUserId)) visible = true;
if (currentUserId.equals(request.getRecipientId())) visible = true;
if (currentUserId.equals(request.getCreatorId()) ||
isSupervisor(request.getRequesteeId(), currentUserId) ||
currentUserId.equals(request.getRecipientId()) ||
selfRevieweeIsCurrentUserReviewee(request, currentUserId)) {
visible = true;
}
}
return visible;
}).toList();
Expand All @@ -318,6 +319,23 @@ private boolean isSupervisor(UUID requesteeId, UUID currentUserId) {
&& memberProfileServices.getSupervisorsForId(requesteeId).stream().anyMatch(profile -> currentUserId.equals(profile.getId()));
}

public boolean selfRevieweeIsCurrentUserReviewee(FeedbackRequest request,
UUID currentUserId) {
// If we are looking at a self-review request, see if there is a review
// request in the same review period that is assigned to the current
// user and the requestee is the same as the self-review request. If
// so, this user is allowed to see the self-review request.
if (request.getRecipientId().equals(request.getRequesteeId())) {
List<FeedbackRequest> other = feedbackReqRepository.findByValues(
null, request.getRecipientId().toString(),
currentUserId.toString(), null,
Util.nullSafeUUIDToString(request.getReviewPeriodId()),
null);
return (other.size() == 1);
}
return false;
}

private boolean createIsPermitted(UUID requesteeId) {
final boolean isAdmin = currentUserServices.isAdmin();
final UUID currentUserId = currentUserServices.getCurrentUser().getId();
Expand All @@ -329,16 +347,21 @@ private boolean createIsPermitted(UUID requesteeId) {
return isAdmin || currentUserId.equals(requesteePDL) || isRequesteesSupervisor || currentUserId.equals(requesteeId);
}

private boolean getIsPermitted(UUID requesteeId, UUID recipientId, LocalDate sendDate) {
LocalDate today = LocalDate.now();
private boolean getIsPermitted(FeedbackRequest feedbackReq) {
final LocalDate sendDate = feedbackReq.getSendDate();
final UUID requesteeId = feedbackReq.getRequesteeId();
final UUID recipientId = feedbackReq.getRecipientId();
final LocalDate today = LocalDate.now();
final UUID currentUserId = currentUserServices.getCurrentUser().getId();

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

return createIsPermitted(requesteeId) || currentUserId.equals(recipientId);
return createIsPermitted(requesteeId) ||
currentUserId.equals(recipientId) ||
selfRevieweeIsCurrentUserReviewee(feedbackReq, currentUserId);
}

private boolean updateDueDateIsPermitted(FeedbackRequest feedbackRequest) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
public interface MemberProfileServices {
MemberProfile getById(UUID id);

MemberProfile findByWorkEmail(@NotNull String workEmail);

Set<MemberProfile> findByValues(String firstName, String lastName, String title,
UUID pdlId, String workEmail, UUID supervisorId, Boolean terminated);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import com.objectcomputing.checkins.services.role.RoleServices;
import com.objectcomputing.checkins.services.team.member.TeamMemberServices;
import io.micronaut.cache.annotation.CacheConfig;
import io.micronaut.cache.annotation.CacheInvalidate;
import io.micronaut.cache.annotation.Cacheable;
import io.micronaut.core.annotation.Nullable;
import jakarta.inject.Named;
Expand Down Expand Up @@ -55,6 +56,7 @@ public MemberProfileServicesImpl(MemberProfileRepository memberProfileRepository
}

@Override
@Cacheable
public MemberProfile getById(@NotNull UUID id) {
Optional<MemberProfile> optional = memberProfileRepository.findById(id);
if (optional.isEmpty()) {
Expand All @@ -67,6 +69,14 @@ public MemberProfile getById(@NotNull UUID id) {
return memberProfile;
}

@Cacheable
@Override
public MemberProfile findByWorkEmail(@NotNull String workEmail) {
return memberProfileRepository.findByWorkEmail(workEmail).orElseThrow(() ->
new NotFoundException("Member not found")
);
}

@Override
public Set<MemberProfile> findByValues(@Nullable String firstName,
@Nullable String lastName,
Expand All @@ -86,6 +96,7 @@ public Set<MemberProfile> findByValues(@Nullable String firstName,
}

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

Expand Down Expand Up @@ -152,6 +163,7 @@ public void emailAssignment(MemberProfile member, boolean isPDL) {
}

@Override
@CacheInvalidate(cacheNames = {"member-cache"})
public boolean deleteProfile(@NotNull UUID id) {
if (!currentUserServices.isAdmin()) {
throw new PermissionException("Requires admin privileges");
Expand Down Expand Up @@ -183,6 +195,7 @@ public boolean deleteProfile(@NotNull UUID id) {
}

@Override
@Cacheable(parameters = {"firstName", "lastName"})
public MemberProfile findByName(@NotNull String firstName, @NotNull String lastName) {
List<MemberProfile> searchResult = memberProfileRepository.search(firstName, null, lastName,
null, null, null, null, null, null);
Expand Down Expand Up @@ -222,6 +235,7 @@ public List<MemberProfile> getSubordinatesForId(UUID id) {
}

@Override
@CacheInvalidate(cacheNames = {"member-cache"})
public MemberProfile updateProfile(MemberProfile memberProfile) {
return memberProfileRepository.update(memberProfile);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.objectcomputing.checkins.services.reports;

import com.objectcomputing.checkins.services.memberprofile.MemberProfileRepository;
import com.objectcomputing.checkins.exceptions.BadArgException;

import com.objectcomputing.checkins.services.memberprofile.MemberProfileServices;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;

Expand All @@ -18,7 +18,7 @@

abstract class CSVProcessor {

public void load(MemberProfileRepository memberProfileRepository,
public void load(MemberProfileServices memberProfileServices,
ByteBuffer dataSource) throws IOException,
BadArgException {
ByteArrayInputStream stream = new ByteArrayInputStream(dataSource.array());
Expand All @@ -30,10 +30,10 @@ public void load(MemberProfileRepository memberProfileRepository,
.setNullString("")
.build()
.parse(input);
loadImpl(memberProfileRepository, csvParser);
loadImpl(memberProfileServices, csvParser);
}

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

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

import com.objectcomputing.checkins.exceptions.NotFoundException;
import com.objectcomputing.checkins.services.memberprofile.MemberProfile;
import com.objectcomputing.checkins.services.memberprofile.MemberProfileRepository;
import com.objectcomputing.checkins.exceptions.BadArgException;

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

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.Optional;
import java.util.*;

public class CompensationHistory extends CSVProcessor {

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

@Override
protected void loadImpl(MemberProfileRepository memberProfileRepository,
protected void loadImpl(MemberProfileServices memberProfileServices,
CSVParser csvParser) throws BadArgException {
history.clear();
for (CSVRecord csvRecord : csvParser) {
try {
String emailAddress = csvRecord.get("emailAddress");
Optional<MemberProfile> memberProfile =
memberProfileRepository.findByWorkEmail(emailAddress);
if (memberProfile.isPresent()) {
String startDate = csvRecord.get("startDate");
LocalDate date = parseDate(startDate);
if (date == null) {
LOG.error("Unable to parse date: {}", startDate);
} else {
String value = csvRecord.get("compensation");
Compensation comp = new Compensation(
memberProfile.get().getId(),
date,
value == null ? null : value.replaceAll("[^\\d\\.,]", ""),
csvRecord.get("totalComp")
);
history.add(comp);
history.clear();
for (CSVRecord csvRecord : csvParser) {
String emailAddress = null;
try {
emailAddress = csvRecord.get("emailAddress");
MemberProfile memberProfile = memberProfileServices.findByWorkEmail(emailAddress);
String startDate = csvRecord.get("startDate");
LocalDate date = parseDate(startDate);
if (date == null) {
LOG.error("Unable to parse date: {}", startDate);
} else {
String value = csvRecord.get("compensation");
Compensation comp = new Compensation(
memberProfile.getId(),
date,
value == null ? null : value.replaceAll("[^\\d\\.,]", ""),
csvRecord.get("totalComp")
);
history.add(comp);
}
} catch (NotFoundException nfe) {
LOG.error("Unable to find a profile for {}", emailAddress);
} catch (IllegalArgumentException ex) {
throw new BadArgException("Unable to parse the compensation history");
}
} else {
LOG.error("Unable to find a profile for {}", emailAddress);
}
} catch(IllegalArgumentException ex) {
throw new BadArgException("Unable to parse the compensation history");
}
}
}

public List<Compensation> getHistory(UUID memberId) {
return history.stream()
.filter(entry -> entry.memberId().equals(memberId))
.toList();
return history.stream()
.filter(entry -> entry.memberId().equals(memberId))
.toList();
}
}
Loading

0 comments on commit 85e7d17

Please sign in to comment.