Skip to content
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

[#15] 그룹 요청 처리 기능 구현 #17

Merged
merged 7 commits into from
Jun 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions group-service/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ configurations {
}

repositories {
mavenLocal()
mavenCentral()
}

Expand All @@ -30,6 +31,8 @@ dependencies {
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

implementation 'me.kong:common-library:0.0.1-SNAPSHOT'
}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,34 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.kong.groupservice.domain.entity.group.Group;
import me.kong.groupservice.dto.request.GroupJoinProcessDto;
import me.kong.groupservice.dto.request.GroupJoinRequestDto;
import me.kong.groupservice.dto.request.enums.JoinRequestSearchCondition;
import me.kong.groupservice.dto.request.SaveGroupRequestDto;
import me.kong.groupservice.dto.response.GroupJoinResponseDto;
import me.kong.groupservice.dto.response.GroupResponseDto;
import me.kong.groupservice.mapper.GroupJoinRequestMapper;
import me.kong.groupservice.mapper.GroupMapper;
import me.kong.groupservice.service.GroupJoinRequestService;
import me.kong.groupservice.service.GroupService;
import me.kong.groupservice.service.ProfileService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

import static me.kong.commonlibrary.constant.HttpStatusResponseEntity.RESPONSE_OK;

@Slf4j
@RestController
@RequestMapping("/api/groups")
@RequiredArgsConstructor
public class GroupController {

private final GroupService groupService;

private final GroupJoinRequestService joinRequestService;
private final GroupMapper groupMapper;
private final GroupJoinRequestMapper requestMapper;

@PostMapping
public ResponseEntity<GroupResponseDto> addGroup(@RequestBody @Valid SaveGroupRequestDto dto) {
Expand All @@ -39,4 +48,21 @@ public ResponseEntity<HttpStatus> joinGroup(@PathVariable Long groupId, @Request
return ResponseEntity.status(HttpStatus.OK).build();
}

@GetMapping("{groupId}/requests")
public ResponseEntity<List<GroupJoinResponseDto>> getGroupRequests(
@PathVariable Long groupId,
@RequestParam(name = "status", defaultValue = "PENDING") JoinRequestSearchCondition condition) {
List<GroupJoinResponseDto> requests = requestMapper.toDtoList(joinRequestService.getGroupJoinRequestsByGroupIdAndCondition(groupId, condition));

return new ResponseEntity<>(requests, HttpStatus.OK);
}

@PatchMapping("{groupId}/requests/{requestId}")
public ResponseEntity<HttpStatus> handleGroupJoinRequest(@PathVariable Long groupId,
@PathVariable Long requestId,
@RequestBody GroupJoinProcessDto processDto) {
joinRequestService.processGroupJoinRequest(requestId, processDto);

return RESPONSE_OK;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,12 @@ public GroupJoinRequest(Long id, String requestInfo, String nickname, JoinRespon
this.userId = userId;
this.group = group;
}

public void approveJoinRequest() {
response = JoinResponse.APPROVED;
}

public void rejectJoinRequest() {
response = JoinResponse.REJECTED;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,18 @@ default boolean pendingRequestExists(Long userId, Long groupId) {
}

Optional<GroupJoinRequest> findByResponseAndUserIdAndGroupId(JoinResponse response, Long userId, Long groupId);

List<GroupJoinRequest> findAllByGroupId(Long groupId);

default List<GroupJoinRequest> findPendingGroupJoinRequests(Long groupId) {
return findAllByGroupIdAndResponse(groupId, JoinResponse.PENDING);
}

default List<GroupJoinRequest> findProcessedGroupJoinRequests(Long groupId) {
return findAllByGroupIdAndResponseNot(groupId, JoinResponse.PENDING);
}

List<GroupJoinRequest> findAllByGroupIdAndResponse(Long groupId, JoinResponse response);

List<GroupJoinRequest> findAllByGroupIdAndResponseNot(Long groupId, JoinResponse response);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package me.kong.groupservice.dto.request;


import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import me.kong.groupservice.dto.request.enums.GroupJoinProcessAction;

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class GroupJoinProcessDto {

@NotNull
private GroupJoinProcessAction action;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package me.kong.groupservice.dto.request.enums;

public enum GroupJoinProcessAction {
APPROVE,
REJECT;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package me.kong.groupservice.dto.request.enums;

public enum JoinRequestSearchCondition {
PENDING,
PROCESSED,
ALL;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package me.kong.groupservice.dto.response;

import lombok.Builder;
import lombok.Getter;
import me.kong.groupservice.domain.entity.GroupJoinRequest.JoinResponse;

@Getter
@Builder
public class GroupJoinResponseDto {
private Long requestId;
private String nickname;
private String requestInfo;
private JoinResponse status;
private Long userId;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@
import me.kong.groupservice.domain.entity.State;
import me.kong.groupservice.domain.entity.group.Group;
import me.kong.groupservice.dto.request.GroupJoinRequestDto;
import me.kong.groupservice.dto.response.GroupJoinResponseDto;
import me.kong.groupservice.dto.response.GroupResponseDto;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
@RequiredArgsConstructor
public class GroupJoinRequestMapper {
Expand All @@ -25,4 +28,20 @@ public GroupJoinRequest toEntity(GroupJoinRequestDto dto, Group group) {
.group(group)
.build();
}

public GroupJoinResponseDto toDto(GroupJoinRequest request) {
return GroupJoinResponseDto.builder()
.requestId(request.getId())
.nickname(request.getNickname())
.requestInfo(request.getRequestInfo())
.status(request.getResponse())
.userId(request.getUserId())
.build();
}

public List<GroupJoinResponseDto> toDtoList(List<GroupJoinRequest> requests) {
return requests.stream()
.map(this::toDto)
.toList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,37 @@

import lombok.RequiredArgsConstructor;
import me.kong.groupservice.common.JwtReader;
import me.kong.groupservice.common.exception.DuplicateElementException;
import me.kong.groupservice.domain.entity.GroupJoinRequest.GroupJoinRequest;
import me.kong.groupservice.domain.entity.GroupJoinRequest.JoinResponse;
import me.kong.groupservice.domain.entity.group.Group;
import me.kong.groupservice.domain.entity.profile.GroupRole;
import me.kong.groupservice.domain.repository.GroupJoinRequestRepository;
import me.kong.groupservice.dto.request.GroupJoinProcessDto;
import me.kong.groupservice.dto.request.GroupJoinRequestDto;
import me.kong.groupservice.dto.request.enums.JoinRequestSearchCondition;
import me.kong.groupservice.mapper.GroupJoinRequestMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.NoSuchElementException;

@Service
@RequiredArgsConstructor
public class GroupJoinRequestService {

private final JwtReader jwtReader;
private final GroupJoinRequestRepository joinRequestRepository;
private final GroupJoinRequestMapper joinRequestMapper;
private final GroupJoinRequestRepository groupJoinRequestRepository;
private final ProfileService profileService;

@Transactional(readOnly = true)
public GroupJoinRequest getGroupJoinRequestByRequestId(Long requestId) {
return joinRequestRepository.findById(requestId)
.orElseThrow(() -> new NoSuchElementException("해당하는 가입 요청이 없습니다. id : " + requestId));
}

@Transactional(readOnly = true)
public boolean pendingRequestExists(Long groupId) {
Expand All @@ -26,4 +43,51 @@ public boolean pendingRequestExists(Long groupId) {
public void createNewGroupJoinRequest(GroupJoinRequestDto dto, Group group) {
joinRequestRepository.save(joinRequestMapper.toEntity(dto, group));
}

@Transactional(readOnly = true)
public List<GroupJoinRequest> getGroupJoinRequestsByGroupIdAndCondition(Long groupId, JoinRequestSearchCondition condition) {
List<GroupJoinRequest> requests;

profileService.checkLoggedInProfileIsGroupManager(groupId);

switch (condition) {
case PENDING -> {
requests = groupJoinRequestRepository.findPendingGroupJoinRequests(groupId);
}
case PROCESSED -> {
requests = groupJoinRequestRepository.findProcessedGroupJoinRequests(groupId);
}
case ALL -> {
requests = groupJoinRequestRepository.findAllByGroupId(groupId);
}
default -> {
throw new IllegalArgumentException("지원하지 않는 그룹 가입 검색 조건. status : " + condition);
}
}
return requests;
}

@Transactional
public void processGroupJoinRequest(Long requestId, GroupJoinProcessDto dto) {
GroupJoinRequest joinRequest = getGroupJoinRequestByRequestId(requestId);

if (joinRequest.getResponse() != JoinResponse.PENDING) {
throw new DuplicateElementException("이미 처리된 가입 요청입니다. 요청 id : " + requestId);
}

profileService.checkLoggedInProfileIsGroupManager(joinRequest.getGroup().getId());

switch (dto.getAction()) {
case APPROVE -> {
joinRequest.approveJoinRequest();
profileService.createNewProfile(joinRequest.getNickname(), GroupRole.MEMBER, joinRequest.getGroup());
}
case REJECT -> {
joinRequest.rejectJoinRequest();
}
default -> {
throw new IllegalArgumentException("지원하지 않는 처리 요청. action : " + dto.getAction());
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package me.kong.groupservice.service;

import lombok.RequiredArgsConstructor;
import me.kong.commonlibrary.exception.auth.UnAuthorizedException;
import me.kong.groupservice.common.JwtReader;
import me.kong.groupservice.common.exception.NoLoggedInProfileException;
import me.kong.groupservice.domain.entity.State;
Expand All @@ -11,7 +12,6 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Optional;


@Service
Expand Down Expand Up @@ -40,4 +40,14 @@ public Profile getLoggedInProfile(Long groupId) {

return profileRepository.findByUserIdAndGroupId(userId, groupId).orElseThrow(NoLoggedInProfileException::new);
}

@Transactional(readOnly = true)
public void checkLoggedInProfileIsGroupManager(Long groupId) {
Profile profile = getLoggedInProfile(groupId);

if (profile.getGroupRole() != GroupRole.MANAGER) {
throw new UnAuthorizedException("권한이 없습니다. groupId : "
+ groupId + ", profileId : " + profile.getId() + " , userId : " + profile.getUserId());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@
import me.kong.groupservice.domain.repository.GroupRepository;
import me.kong.groupservice.domain.repository.ProfileRepository;
import me.kong.groupservice.dto.request.SaveGroupRequestDto;
import me.kong.groupservice.service.GroupJoinRequestService;
import me.kong.groupservice.service.GroupService;
import me.kong.groupservice.service.ProfileService;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
Expand All @@ -29,6 +28,9 @@ public class GroupManagementServiceTest {
@Autowired
private GroupService groupService;

@Autowired
private GroupJoinRequestService joinRequestService;

@MockBean
private ProfileService profileService;

Expand Down
Loading
Loading