package de.ph87.tools.group; import de.ph87.tools.user.User; import de.ph87.tools.user.UserPublicMapper; import de.ph87.tools.user.UserService; import jakarta.annotation.Nullable; import jakarta.servlet.http.HttpServletResponse; import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.server.ResponseStatusException; @Slf4j @Service @Transactional @RequiredArgsConstructor public class GroupService { private final GroupRepository groupRepository; private final UserService userService; private final GroupMapper groupMapper; private final UserPublicMapper userPublicMapper; private final GroupOfUserService groupOfUserService; @NonNull public GroupDto create(@Nullable final String privateUuid, @NonNull final HttpServletResponse response) { final User user = userService.getUserByPrivateUuidOrElseCreate(privateUuid, response); final Group group = createUnchecked(user); return doJoinUnchecked(group, user); } public boolean canAccess(@Nullable final String privateUuid, @NonNull final String groupUuid) { if (privateUuid == null) { return false; } return userService.findByPrivateUuid(privateUuid).flatMap(user -> groupOfUserService.findGroupOfUser(groupUuid, user)).isPresent(); } @NonNull public GroupDto get(@NonNull final String privateUuid, @NonNull final String groupUuid) { final GroupOfUserService.GroupOfUser ug = groupOfUserService.accessGroupOfUser(groupUuid, privateUuid); return groupMapper.toDto(ug.group); } @NonNull public GroupDto join(@NonNull final String privateUuid, @NonNull final GroupJoinRequest request) { final User user = userService.getByPrivateUuidOrThrow(privateUuid); final Group group = getByGroupByGroupUuid(request.uuid); if (!group.getPassword().equals(request.password)) { log.error("Wrong password: user={}, group={}", user, group); throw new ResponseStatusException(HttpStatus.FORBIDDEN); } return doJoinUnchecked(group, user); } @NonNull private Group getByGroupByGroupUuid(@NonNull final String groupUuid) { return groupRepository.findByUuid(groupUuid).orElseThrow(() -> new ResponseStatusException(HttpStatus.BAD_REQUEST)); } @NonNull public GroupDto changeTitle(@NonNull final String privateUuid, @NonNull final GroupChangeTitleRequest request) { final GroupOfUserService.GroupOfUser ug = groupOfUserService.accessGroupOfUser(request.uuid, privateUuid); if (!ug.group.isOwnedBy(ug.user)) { throw new ResponseStatusException(HttpStatus.FORBIDDEN); } ug.group.setTitle(request.title); return groupMapper.publish(ug.group); } @NonNull public GroupDto changePassword(@NonNull final String privateUuid, @NonNull final GroupChangePasswordInbound request) { final User user = userService.getByPrivateUuidOrThrow(privateUuid); final Group group = groupOfUserService.getGroupOfUser(request.uuid, user); if (!group.isOwnedBy(user)) { throw new ResponseStatusException(HttpStatus.FORBIDDEN); } group.setPassword(request.password); return groupMapper.publish(group); } public void leave(@NonNull final String privateUuid, @NonNull final String groupUuid) { final User user = userService.getByPrivateUuidOrThrow(privateUuid); final Group group = getByGroupByGroupUuid(groupUuid); doLeaveUnchecked(group, user); } /* CREATE, JOIN, LEAVE -------------------------------------------------------------------------- */ @NonNull private Group createUnchecked(@NonNull final User user) { final Group group = groupRepository.save(new Group(user)); log.info("Group CREATED: {}", group); return group; } @NonNull private GroupDto doJoinUnchecked(@NonNull final Group group, @NonNull final User user) { group.getUsers().add(user); group.touch(); user.touch(); log.info("User joined Group: user={}, group={}", user, group); final GroupDto groupDto = groupMapper.publish(group); userPublicMapper.publish(user); return groupDto; } private void doLeaveUnchecked(final Group group, final User user) { group.getUsers().remove(user); group.touch(); user.touch(); log.info("User left Group: user={}, group={}", user, group); groupMapper.publish(group); userPublicMapper.publish(user); } }