TIL

TIL - 2024/08/06

기석김 2024. 8. 15. 02:08

어느 정도 api를 구현했었는데,
스페이스 생성 시 자동으로 생성자를 멤버로 추가하는 기능 & 사용자가 가입한 스페이스 목록 조회가 필요하다.
이게 당연한 게, 스페이스 생성했을 때 그 사람이 원래는 그 스페이스에 없는 걸로 나왔는데, 이제는 생성하면 바로 그 스페이스에 들어가게 수정했고, 자신의 스페이스만 볼 수 있도록 조회 기능 수정(사용자가 로그인 시 자신의 스페이스만 볼 수 있도록 API를 수정했다) 그래서 바로 설계를 하고 api를 짰다.
Controller이다. CreateSpace 부분에 @AuthenticationPrincipal UserPrincipal
userPrincipal를 넣어준다.

그리고 my라는 사용자가 가입한 스페이스 목록 조회를 만들었다.

@RestController
@RequiredArgsConstructor
@RequestMapping("/spaces")
public class SpaceController {

    private final SpaceFacade spaceFacade;

    @PostMapping
    public Mono<ResponseEntity<SpaceResponseDto>> createSpace(
        @AuthenticationPrincipal UserPrincipal userPrincipal,
        @Valid @RequestBody SpaceRequestDto requestDto) {
        Long userId = userPrincipal.getUser().getId();
        return spaceFacade.createSpace(requestDto, userId)
            .map(ResponseEntity::ok);
    }

    @GetMapping("/my")
    public Flux<SpaceResponseDto> getMySpaces(
        @AuthenticationPrincipal UserPrincipal userPrincipal) {
        Long userId = userPrincipal.getUser().getId();
        return spaceFacade.getUserSpaces(userId);
    }

}

 

Facade 부분에서도 UserId를 가져오게 바꿨다.

@RequiredArgsConstructor
@Component
public class SpaceFacade {

    private final SpaceService spaceService;

    public Mono<SpaceResponseDto> createSpace(SpaceRequestDto requestDto, Long userId) {
        return spaceService.createSpace(requestDto, userId);
    }

    public Flux<SpaceResponseDto> getUserSpaces(Long userId) {
        return spaceService.getUserSpaces(userId);
    }
}

 

Service 부분이다. 

@RequiredArgsConstructor
@Service
public class SpaceService {

    private final SpaceRepository spaceRepository;
    private final SpaceMemberRepository spaceMemberRepository;

    public Mono<SpaceResponseDto> createSpace(SpaceRequestDto requestDto, Long userId) {
        Space space = Space.builder()
            .spaceName(requestDto.getSpaceName())
            .isPublic(requestDto.getIsPublic())
            .thumbnail(requestDto.getThumbnail())
            .build();
        return spaceRepository.save(space)
            .flatMap(savedSpace -> addUserToSpace(userId, savedSpace.getId())
                .thenReturn(new SpaceResponseDto(savedSpace)));
    }

    public Flux<SpaceResponseDto> getUserSpaces(Long userId) {
        return spaceMemberRepository.findAllByUserId(userId)
            .flatMap(spaceMember -> spaceRepository.findById(spaceMember.getSpaceId())
                .map(SpaceResponseDto::new))
            .switchIfEmpty(Flux.error(new CustomException(SpaceErrorCode.NO_SPACES_JOINED)));
    }

    private Mono<SpaceMember> addUserToSpace(Long userId, Long spaceId) {
        return spaceMemberRepository.save(SpaceMember.builder()
            .userId(userId)
            .spaceId(spaceId)
            .build());
    }

}

 

에러코드도 추가했다.

@Getter
@AllArgsConstructor
public enum SpaceErrorCode implements BaseCode {

    NO_SPACES_JOINED(HttpStatus.NOT_FOUND, 5003, "가입된 스페이스가 없습니다.", "사용자가 가입한 스페이스가 없습니다."),
    ;

    private final HttpStatus status;
    private final int code;
    private final String msg;
    private final String remark;

    @Override
    public CommonReason getCommonReason() {
        return CommonReason.builder()
            .status(status)
            .code(code)
            .msg(msg)
            .build();
    }
}

 

Repository

public interface SpaceMemberRepository extends ReactiveCrudRepository<SpaceMember, Long> {
    Flux<SpaceMember> findAllByUserId(Long userId);
}

 

테스트 결과

 

내가 가입한 스페이스만 볼 수 있는 api

 

 

만약에 어떤 스페이스에도 가입이 되지 않았다면