diff --git a/server/src/main/java/com/objectcomputing/checkins/services/feedback_answer/FeedbackAnswerServices.java b/server/src/main/java/com/objectcomputing/checkins/services/feedback_answer/FeedbackAnswerServices.java index bdb6d3becb..b6e15e2ba4 100644 --- a/server/src/main/java/com/objectcomputing/checkins/services/feedback_answer/FeedbackAnswerServices.java +++ b/server/src/main/java/com/objectcomputing/checkins/services/feedback_answer/FeedbackAnswerServices.java @@ -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; @@ -14,4 +15,6 @@ public interface FeedbackAnswerServices { FeedbackAnswer getById(UUID id); List findByValues(@Nullable UUID questionId, @Nullable UUID requestId); + + boolean getIsPermitted(FeedbackRequest feedbackRequest); } diff --git a/server/src/main/java/com/objectcomputing/checkins/services/feedback_answer/FeedbackAnswerServicesImpl.java b/server/src/main/java/com/objectcomputing/checkins/services/feedback_answer/FeedbackAnswerServicesImpl.java index d32806b246..f2eab96940 100644 --- a/server/src/main/java/com/objectcomputing/checkins/services/feedback_answer/FeedbackAnswerServicesImpl.java +++ b/server/src/main/java/com/objectcomputing/checkins/services/feedback_answer/FeedbackAnswerServicesImpl.java @@ -113,7 +113,7 @@ public List 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; } @@ -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); } } diff --git a/server/src/main/java/com/objectcomputing/checkins/services/feedback_answer/question_and_answer/QuestionAndAnswerServicesImpl.java b/server/src/main/java/com/objectcomputing/checkins/services/feedback_answer/question_and_answer/QuestionAndAnswerServicesImpl.java index bdff6d7e25..180b399879 100644 --- a/server/src/main/java/com/objectcomputing/checkins/services/feedback_answer/question_and_answer/QuestionAndAnswerServicesImpl.java +++ b/server/src/main/java/com/objectcomputing/checkins/services/feedback_answer/question_and_answer/QuestionAndAnswerServicesImpl.java @@ -42,7 +42,7 @@ public QuestionAndAnswerServicesImpl(FeedbackAnswerServices feedbackAnswerServic @Override public List getAllQuestionsAndAnswers(UUID requestId) { FeedbackRequest feedbackRequest = feedbackRequestServices.getById(requestId); - if (!getIsPermitted(feedbackRequest)) { + if (!feedbackAnswerServices.getIsPermitted(feedbackRequest)) { throw new PermissionException(NOT_AUTHORIZED_MSG); } List templateQuestions = templateQuestionServices.findByFields(feedbackRequest.getTemplateId()); @@ -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); } @@ -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); - } - } diff --git a/server/src/main/java/com/objectcomputing/checkins/services/feedback_request/FeedbackRequestServices.java b/server/src/main/java/com/objectcomputing/checkins/services/feedback_request/FeedbackRequestServices.java index 90cfd09ce3..31d0f7dfec 100644 --- a/server/src/main/java/com/objectcomputing/checkins/services/feedback_request/FeedbackRequestServices.java +++ b/server/src/main/java/com/objectcomputing/checkins/services/feedback_request/FeedbackRequestServices.java @@ -14,4 +14,7 @@ public interface FeedbackRequestServices { FeedbackRequest getById(UUID id); List findByValues(UUID creatorId, UUID requesteeId, UUID recipientId, LocalDate oldestDate, UUID reviewPeriodId, UUID templateId, List requesteeIds); -} \ No newline at end of file + + boolean selfRevieweeIsCurrentUserReviewee(FeedbackRequest request, + UUID currentUserId); +} diff --git a/server/src/main/java/com/objectcomputing/checkins/services/feedback_request/FeedbackRequestServicesImpl.java b/server/src/main/java/com/objectcomputing/checkins/services/feedback_request/FeedbackRequestServicesImpl.java index 180d8fef35..4d07ab3778 100644 --- a/server/src/main/java/com/objectcomputing/checkins/services/feedback_request/FeedbackRequestServicesImpl.java +++ b/server/src/main/java/com/objectcomputing/checkins/services/feedback_request/FeedbackRequestServicesImpl.java @@ -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); } @@ -303,9 +301,12 @@ public List 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(); @@ -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 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(); @@ -329,8 +347,11 @@ 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 @@ -338,7 +359,9 @@ private boolean getIsPermitted(UUID requesteeId, UUID recipientId, LocalDate sen 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) { diff --git a/web-ui/src/components/reviews/TeamReviews.jsx b/web-ui/src/components/reviews/TeamReviews.jsx index 5a6d92235f..418518416d 100644 --- a/web-ui/src/components/reviews/TeamReviews.jsx +++ b/web-ui/src/components/reviews/TeamReviews.jsx @@ -55,6 +55,7 @@ import { } from '../../context/actions'; import { AppContext } from '../../context/AppContext'; import { + selectIsAdmin, selectCsrfToken, selectCurrentMembers, selectCurrentUser, @@ -125,7 +126,7 @@ const ReviewStatus = { const TeamReviews = ({ onBack, periodId }) => { const { state, dispatch } = useContext(AppContext); const location = useLocation(); - + const isAdmin = selectIsAdmin(state); const [openMode, setOpenMode] = useState(false); const [approvalState, setApprovalState] = useState(false); const [assignments, setAssignments] = useState([]); @@ -796,7 +797,7 @@ const TeamReviews = ({ onBack, periodId }) => { const url = getReviewerURL(request, selfReviewRequest); return (url ? - + { const manages = recipientProfile.supervisorid == currentUser?.id; const request = getReviewRequest(member, currentUser); const isReviewer = request?.recipientId == currentUser?.id; - if (manages || isReviewer) { + if (isAdmin || manages || isReviewer) { const selfReviewRequest = getSelfReviewRequest(member); return (