-
Notifications
You must be signed in to change notification settings - Fork 0
Backend/auth #92
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
Backend/auth #92
Changes from all commits
6cdbd04
213a428
ceac0cb
1743e02
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 |
|---|---|---|
|
|
@@ -72,6 +72,12 @@ public final ResponseEntity<ErrorDetails> userIsNotInGroupException(Exception ex | |
| return new ResponseEntity<>(errorDetails, HttpStatus.CONFLICT); | ||
| } | ||
|
|
||
| @ExceptionHandler(UserIsNotGroupOwner.class) | ||
| public final ResponseEntity<ErrorDetails> userIsNotInGroupOwnerException(Exception ex, WebRequest request) { | ||
| ErrorDetails errorDetails = new ErrorDetails(LocalDateTime.now(), ex.getMessage(), request.getDescription(false), ex.getStackTrace().length); | ||
|
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. The |
||
| return new ResponseEntity<>(errorDetails, HttpStatus.FORBIDDEN); | ||
| } | ||
|
|
||
| @ExceptionHandler(OwnerDeletionException.class) | ||
| public final ResponseEntity<ErrorDetails> ownerDeletionException(Exception ex, WebRequest request) { | ||
| ErrorDetails errorDetails = new ErrorDetails(LocalDateTime.now(), ex.getMessage(), request.getDescription(false), ex.getStackTrace().length); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package share.fare.backend.exception; | ||
|
|
||
| public class UserIsNotGroupOwner extends RuntimeException { | ||
| public UserIsNotGroupOwner(Long userId, Long groupId) { | ||
| super("User " + userId + " is not group owner of " + groupId); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,20 +11,18 @@ | |
| import share.fare.backend.entity.User; | ||
| import share.fare.backend.exception.ActivityNotFoundException; | ||
| import share.fare.backend.exception.GroupNotFoundException; | ||
| import share.fare.backend.exception.UserNotFoundException; | ||
| import share.fare.backend.mapper.ActivityMapper; | ||
| import share.fare.backend.repository.ActivityRepository; | ||
| import share.fare.backend.repository.GroupRepository; | ||
| import share.fare.backend.repository.UserRepository; | ||
|
|
||
| @Service | ||
| @RequiredArgsConstructor | ||
| public class ActivityService { | ||
| private final ActivityRepository activityRepository; | ||
| private final GroupRepository groupRepository; | ||
| private final UserRepository userRepository; | ||
| private final SecurityService securityService; | ||
|
|
||
| public ActivityResponse createActivity(ActivityRequest activityRequest, Long createdByUserId, Long groupId) { | ||
| public ActivityResponse createActivity(ActivityRequest activityRequest, User currentUser, Long groupId) { | ||
| if (activityRequest.getStartDate() != null && activityRequest.getEndDate() != null) { | ||
| if (activityRequest.getStartDate().isAfter(activityRequest.getEndDate())) { | ||
| throw new IllegalArgumentException("Start date must be before end date."); | ||
|
|
@@ -35,28 +33,33 @@ public ActivityResponse createActivity(ActivityRequest activityRequest, Long cre | |
| .findById(groupId) | ||
| .orElseThrow(() -> new GroupNotFoundException(groupId)); | ||
|
|
||
| User user = userRepository | ||
| .findById(createdByUserId) | ||
| .orElseThrow(() -> new UserNotFoundException(createdByUserId)); | ||
| securityService.checkIfUserIsInGroup(currentUser, group); | ||
|
|
||
| Activity activity = ActivityMapper.toEntity(activityRequest, group); | ||
|
|
||
| return ActivityMapper.toResponse(activityRepository.save(activity)); | ||
| } | ||
|
|
||
| public ActivityResponse updateActivity(ActivityRequest request, Long activityId) { | ||
| public ActivityResponse updateActivity(ActivityRequest request, Long activityId, User currentUser) { | ||
| Activity activity = activityRepository | ||
| .findById(activityId) | ||
| .orElseThrow(() -> new ActivityNotFoundException("Activity with ID: " + activityId + " not found")); | ||
|
|
||
| securityService.checkIfUserIsInGroup(currentUser, activity.getGroup()); | ||
|
|
||
| activity.setName(request.getName()); | ||
| activity.setDescription(request.getDescription()); | ||
| activity.setLink(request.getLink()); | ||
|
|
||
| return ActivityMapper.toResponse(activityRepository.save(activity)); | ||
| } | ||
|
|
||
| public void deleteActivity(Long activityId) { | ||
| public void deleteActivity(Long activityId, User currentUser) { | ||
| Activity activity = activityRepository.findById(activityId) | ||
| .orElseThrow(() -> new ActivityNotFoundException("Activity with ID: " + activityId + " not found")); | ||
|
|
||
| securityService.checkIfUserIsInGroup(currentUser, activity.getGroup()); | ||
|
Comment on lines
+58
to
+61
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. |
||
|
|
||
| activityRepository.deleteById(activityId); | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,11 +25,14 @@ public class GroupMembershipService { | |
| private final GroupMembershipRepository groupMembershipRepository; | ||
| private final GroupRepository groupRepository; | ||
| private final UserRepository userRepository; | ||
| private final SecurityService securityService; | ||
|
|
||
| public GroupMembershipResponse addMemberToGroup(Long groupId, Long userId, GroupRole role, Long currentUserId) { | ||
| public GroupMembershipResponse addMemberToGroup(Long groupId, Long userId, GroupRole role, User currentUser) { | ||
| Group group = groupRepository.findById(groupId) | ||
| .orElseThrow(() -> new GroupNotFoundException(groupId)); | ||
|
|
||
| securityService.checkIfUserIsInGroup(currentUser, group); | ||
|
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. The authorization check |
||
|
|
||
| User user = userRepository.findById(userId) | ||
| .orElseThrow(() -> new UserNotFoundException(userId)); | ||
|
|
||
|
|
@@ -47,7 +50,7 @@ public GroupMembershipResponse addMemberToGroup(Long groupId, Long userId, Group | |
| return GroupMembershipMapper.toResponse(savedMembership); | ||
| } | ||
|
|
||
| public void removeMemberFromGroup(Long groupId, Long userId) { | ||
| public void removeMemberFromGroup(Long groupId, Long userId, User currentUser) { | ||
| Group group = groupRepository.findById(groupId) | ||
| .orElseThrow(() -> new GroupNotFoundException(groupId)); | ||
|
|
||
|
|
@@ -57,17 +60,21 @@ public void removeMemberFromGroup(Long groupId, Long userId) { | |
| GroupMembership membership = groupMembershipRepository.findByGroupAndUser(group, user) | ||
| .orElseThrow(() -> new UserIsNotInGroupException("User is not a member of the group")); | ||
|
|
||
| securityService.checkIfUserCanRemoveMember(currentUser, user, group); | ||
|
|
||
| if (membership.getRole() == GroupRole.OWNER) { | ||
| throw new IllegalArgumentException("Owner cannot be removed from the group"); | ||
| } | ||
|
|
||
| groupMembershipRepository.delete(membership); | ||
| } | ||
|
|
||
| public GroupMembershipResponse updateMemberRole(Long groupId, Long userId, GroupRole newRole) { | ||
| public GroupMembershipResponse updateMemberRole(Long groupId, Long userId, GroupRole newRole, User currentUser) { | ||
| Group group = groupRepository.findById(groupId) | ||
| .orElseThrow(() -> new GroupNotFoundException(groupId)); | ||
|
|
||
| securityService.checkIfUserIsGroupOwner(currentUser, group); | ||
|
|
||
| User user = userRepository.findById(userId) | ||
| .orElseThrow(() -> new UserNotFoundException(userId)); | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| package share.fare.backend.service; | ||
|
|
||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.stereotype.Service; | ||
| import share.fare.backend.entity.Group; | ||
| import share.fare.backend.entity.GroupMembership; | ||
| import share.fare.backend.entity.GroupRole; | ||
| import share.fare.backend.entity.User; | ||
| import share.fare.backend.exception.UserIsNotGroupOwner; | ||
| import share.fare.backend.exception.UserIsNotInGroupException; | ||
| import share.fare.backend.repository.GroupMembershipRepository; | ||
|
|
||
| @Service | ||
| @RequiredArgsConstructor | ||
| public class SecurityService { | ||
| private final GroupMembershipRepository membershipRepository; | ||
|
|
||
| public void checkIfUserIsInGroup(User user, Group group) { | ||
| findMembershipOrThrow(user, group); | ||
| } | ||
|
|
||
| public void checkIfUserIsGroupOwner(User user, Group group) { | ||
| GroupMembership membership = findMembershipOrThrow(user, group); | ||
|
|
||
| if (membership.getRole() != GroupRole.OWNER) { | ||
| throw new UserIsNotGroupOwner(user.getId(), group.getId()); | ||
| } | ||
| } | ||
|
|
||
| public void checkIfUserCanRemoveMember(User currentUser, User userToRemove, Group group) { | ||
| GroupMembership membership = findMembershipOrThrow(currentUser, group); | ||
| if (membership.getRole() != GroupRole.OWNER && !currentUser.getId().equals(userToRemove.getId())) { | ||
| throw new UserIsNotGroupOwner(currentUser.getId(), group.getId()); | ||
| } | ||
| } | ||
|
Comment on lines
+30
to
+35
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. The logic in |
||
|
|
||
| private GroupMembership findMembershipOrThrow(User user, Group group) { | ||
| return membershipRepository.findByGroupAndUser(group, user) | ||
| .orElseThrow(() -> | ||
| new UserIsNotInGroupException("User " + user.getId() + " is not in group " + group.getName())); | ||
| } | ||
| } | ||
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 retrieval of the
Groupentity followed by a security checksecurityService.checkIfUserIsInGroup(user, group)is a good practice for ensuring the user has access to the group chat. This explicit check enhances security before accessing sensitive chat data.