-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature 2825/adjust admin menu #2828
Changes from 8 commits
523015b
b786c08
a30fd25
51f334a
fbe0b18
ae8bed0
2d8c62f
091554a
1bc6da6
40b92b4
6360bfb
29488da
8d4b2ef
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
package com.objectcomputing.checkins.services.kudos; | ||
|
||
import com.objectcomputing.checkins.services.permissions.Permission; | ||
import com.objectcomputing.checkins.configuration.CheckInsConfiguration; | ||
import com.objectcomputing.checkins.notifications.email.EmailSender; | ||
import com.objectcomputing.checkins.notifications.email.MailJetFactory; | ||
|
@@ -121,10 +122,6 @@ public Kudos save(KudosCreateDTO kudosDTO) { | |
|
||
@Override | ||
public Kudos approve(Kudos kudos) { | ||
if (!currentUserServices.isAdmin()) { | ||
throw new PermissionException(NOT_AUTHORIZED_MSG); | ||
} | ||
|
||
UUID kudosId = kudos.getId(); | ||
Kudos existingKudos = kudosRepository.findById(kudosId).orElseThrow(() -> | ||
new BadArgException(KUDOS_DOES_NOT_EXIST_MSG.formatted(kudosId))); | ||
|
@@ -151,7 +148,7 @@ public KudosResponseDTO getById(UUID id) { | |
|
||
if (kudos.getDateApproved() == null) { | ||
// If not yet approved, only admins and the sender can access the kudos | ||
if (!currentUserServices.isAdmin() && !isSender) { | ||
if (!hasAdministerKudosPermission() && !isSender) { | ||
throw new PermissionException(NOT_AUTHORIZED_MSG); | ||
} | ||
} else { | ||
|
@@ -162,7 +159,7 @@ public KudosResponseDTO getById(UUID id) { | |
.stream() | ||
.anyMatch(recipient -> recipient.getMemberId().equals(currentUserId)); | ||
|
||
if (!currentUserServices.isAdmin() && !isSender && !isRecipient) { | ||
if (!hasAdministerKudosPermission() && !isSender && !isRecipient) { | ||
throw new PermissionException(NOT_AUTHORIZED_MSG); | ||
} | ||
} | ||
|
@@ -173,10 +170,6 @@ public KudosResponseDTO getById(UUID id) { | |
|
||
@Override | ||
public void delete(UUID id) { | ||
if (!currentUserServices.isAdmin()) { | ||
throw new PermissionException(NOT_AUTHORIZED_MSG); | ||
} | ||
|
||
Kudos kudos = kudosRepository.findById(id).orElseThrow(() -> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same above here. Is there a permission check happening? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same with the delete:
|
||
new NotFoundException(KUDOS_DOES_NOT_EXIST_MSG.formatted(id))); | ||
|
||
|
@@ -196,7 +189,7 @@ public List<KudosResponseDTO> findByValues(@Nullable UUID recipientId, @Nullable | |
} else if (senderId != null) { | ||
return findAllFromMember(senderId); | ||
} else { | ||
if (!currentUserServices.isAdmin()) { | ||
if (!hasAdministerKudosPermission()) { | ||
throw new PermissionException(NOT_AUTHORIZED_MSG); | ||
} | ||
|
||
|
@@ -215,7 +208,7 @@ public List<KudosResponseDTO> getRecent() { | |
} | ||
|
||
private List<KudosResponseDTO> findByPending(boolean isPending) { | ||
if (!currentUserServices.isAdmin()) { | ||
if (!hasAdministerKudosPermission()) { | ||
throw new PermissionException(NOT_AUTHORIZED_MSG); | ||
} | ||
|
||
|
@@ -235,10 +228,10 @@ private List<KudosResponseDTO> findByPending(boolean isPending) { | |
|
||
|
||
private List<KudosResponseDTO> findAllToMember(UUID memberId) { | ||
boolean isAdmin = currentUserServices.isAdmin(); | ||
UUID currentUserId = currentUserServices.getCurrentUser().getId(); | ||
|
||
if (!currentUserId.equals(memberId) && !isAdmin) { | ||
if (!currentUserId.equals(memberId) && | ||
!hasAdministerKudosPermission()) { | ||
throw new PermissionException("You are not authorized to retrieve the kudos another user has received"); | ||
} | ||
|
||
|
@@ -261,10 +254,10 @@ private List<KudosResponseDTO> findAllToMember(UUID memberId) { | |
|
||
private List<KudosResponseDTO> findAllFromMember(UUID senderId) { | ||
|
||
boolean isAdmin = currentUserServices.isAdmin(); | ||
UUID currentUserId = currentUserServices.getCurrentUser().getId(); | ||
|
||
if (!currentUserId.equals(senderId) && !isAdmin) { | ||
if (!currentUserId.equals(senderId) && | ||
!hasAdministerKudosPermission()) { | ||
throw new PermissionException("You are not authorized to retrieve the kudos another user has sent"); | ||
} | ||
|
||
|
@@ -386,4 +379,8 @@ private void slackApprovedKudos(Kudos kudos) { | |
LOG.error("Unable to POST to Slack: " + httpResponse.reason()); | ||
} | ||
} | ||
|
||
private boolean hasAdministerKudosPermission() { | ||
return currentUserServices.hasPermission(Permission.CAN_ADMINISTER_KUDOS); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,6 +25,7 @@ | |
import java.util.*; | ||
|
||
import static com.objectcomputing.checkins.util.Util.nullSafeUUIDToString; | ||
import static com.objectcomputing.checkins.services.validate.PermissionsValidation.NOT_AUTHORIZED_MSG; | ||
|
||
@Singleton | ||
@CacheConfig("member-cache") | ||
|
@@ -110,27 +111,9 @@ public MemberProfile saveProfile(MemberProfile memberProfile) { | |
emailAssignment(createdMemberProfile, true); // PDL | ||
emailAssignment(createdMemberProfile, false); // Supervisor | ||
return createdMemberProfile; | ||
} | ||
|
||
Optional<MemberProfile> existingProfileOpt = memberProfileRepository.findById(memberProfile.getId()); | ||
MemberProfile updatedMemberProfile = memberProfileRepository.update(memberProfile); | ||
if (existingProfileOpt.isEmpty()) { | ||
LOG.error("MemberProfile with id {} not found", memberProfile.getId()); | ||
} else { | ||
MemberProfile existingProfile = existingProfileOpt.get(); | ||
|
||
boolean pdlChanged = !Objects.equals(existingProfile.getPdlId(), memberProfile.getPdlId()); | ||
boolean supervisorChanged = !Objects.equals(existingProfile.getSupervisorid(), memberProfile.getSupervisorid()); | ||
|
||
if (pdlChanged) { | ||
emailAssignment(updatedMemberProfile, true); // PDL | ||
} | ||
if (supervisorChanged) { | ||
emailAssignment(updatedMemberProfile, false); // Supervisor | ||
} | ||
throw new BadArgException("New member created with an id"); | ||
} | ||
|
||
return updatedMemberProfile; | ||
} | ||
|
||
public void emailAssignment(MemberProfile member, boolean isPDL) { | ||
|
@@ -165,9 +148,6 @@ 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"); | ||
} | ||
MemberProfile memberProfile = memberProfileRepository.findById(id).orElse(null); | ||
Set<Role> userRoles = (memberProfile != null) ? roleServices.findUserRoles(memberProfile.getId()) : Collections.emptySet(); | ||
|
||
|
@@ -180,7 +160,7 @@ public boolean deleteProfile(@NotNull UUID id) { | |
} else if (!teamMemberServices.findByFields(null, id, null).isEmpty()) { | ||
throw new BadArgException(String.format("User %s cannot be deleted since TeamMember record(s) exist", MemberProfileUtils.getFullName(memberProfile))); | ||
} else if (!userRoles.isEmpty()) { | ||
throw new BadArgException(String.format("User %s cannot be deleted since user has PDL role", MemberProfileUtils.getFullName(memberProfile))); | ||
throw new BadArgException(String.format("User %s cannot be deleted since user has one or more roles", MemberProfileUtils.getFullName(memberProfile))); | ||
} | ||
|
||
// Update PDL ID for all associated members before termination | ||
|
@@ -237,6 +217,47 @@ public List<MemberProfile> getSubordinatesForId(UUID id) { | |
@Override | ||
@CacheInvalidate(cacheNames = {"member-cache"}) | ||
public MemberProfile updateProfile(MemberProfile memberProfile) { | ||
if (memberProfile.getId() == null) { | ||
throw new BadArgException("Null profile id in update"); | ||
} | ||
|
||
MemberProfile currentUser = currentUserServices.getCurrentUser(); | ||
boolean isAdmin = currentUserServices.isAdmin(); | ||
if (!isAdmin && (currentUser == null || !currentUser.getId().equals(memberProfile.getId()))) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Was this an intentional or accidental can kicking? 🤣 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, intentional in that there are no required permissions to update a member profile. Since every member can update their own profile, I didn't see a way to limit which profile could be updated except by using the existing mechanism of checking for admin. But, as I'm writing this, I'm thinking that we could add a permission to be able to "update all profiles" and specifically check for it here instead of admin. Thoughts? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I think that would work! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 I'm onboard with that. |
||
throw new PermissionException(NOT_AUTHORIZED_MSG); | ||
} | ||
|
||
MemberProfile emailProfile = memberProfileRepository.findByWorkEmail(memberProfile.getWorkEmail()).orElse(null); | ||
|
||
if (emailProfile != null && emailProfile.getId() != null && !Objects.equals(memberProfile.getId(), emailProfile.getId())) { | ||
throw new AlreadyExistsException(String.format("Email %s already exists in database", | ||
memberProfile.getWorkEmail())); | ||
} | ||
|
||
Optional<MemberProfile> existingProfileOpt = memberProfileRepository.findById(memberProfile.getId()); | ||
MemberProfile updatedMemberProfile = memberProfileRepository.update(memberProfile); | ||
if (existingProfileOpt.isEmpty()) { | ||
LOG.error("MemberProfile with id {} not found", memberProfile.getId()); | ||
} else { | ||
MemberProfile existingProfile = existingProfileOpt.get(); | ||
|
||
boolean pdlChanged = !Objects.equals(existingProfile.getPdlId(), memberProfile.getPdlId()); | ||
boolean supervisorChanged = !Objects.equals(existingProfile.getSupervisorid(), memberProfile.getSupervisorid()); | ||
|
||
if (pdlChanged) { | ||
emailAssignment(updatedMemberProfile, true); // PDL | ||
} | ||
if (supervisorChanged) { | ||
emailAssignment(updatedMemberProfile, false); // Supervisor | ||
} | ||
} | ||
|
||
return updatedMemberProfile; | ||
} | ||
|
||
@Override | ||
@CacheInvalidate(cacheNames = {"member-cache"}) | ||
public MemberProfile updateCurrentUserProfile(MemberProfile memberProfile) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems to be misleading. This isn't related to the "current user" at all, is it? Am I missing something? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, it is only called from the current user controller when updating the "last seen" for the current user. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe it should be renamed to something like "directProfileUpdate" or something indicating that there is no security related to it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we isolate that code to update the "last seen" here and call it something like 'updateLastSeen' and just pass in the user id? that feels less risky than an unsecured profile update API. |
||
return memberProfileRepository.update(memberProfile); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we not need to replace this with a permission check? I don't see it happening elsewhere in here, but I could be missing it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The controller handles this: