Skip to content

Commit

Permalink
Merge pull request #78 from YAPP-Github/feature/MAFOO-181
Browse files Browse the repository at this point in the history
[MAFOO-181] feat: ๊ณต์œ  ์•จ๋ฒ” ๋Œ€์ƒ ์‚ฌ์šฉ์ž ๊ฒ€์ƒ‰ API๋ฅผ ๊ตฌํ˜„ํ–ˆ์–ด์š”
  • Loading branch information
gmkim20713 authored Nov 23, 2024
2 parents 93ca666 + c2c2c9d commit 153a726
Show file tree
Hide file tree
Showing 12 changed files with 182 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,23 @@
@RequestMapping("/v1/shared-members")
public interface SharedMemberApi {

@Operation(summary = "๊ณต์œ  ์‚ฌ์šฉ์ž ์กฐํšŒ", description = "์•จ๋ฒ” ID ๋ฐ ์‚ฌ์šฉ์ž ID์— ํ•ด๋‹นํ•˜๋Š” ๊ณต์œ  ์‚ฌ์šฉ์ž๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.")
@GetMapping
Mono<SharedMemberResponse> getSharedMemberByAlbumAndMember(
@RequestMemberId
String requestMemberId,

@ULID
@Parameter(description = "์•จ๋ฒ” ID", example = "test_album_id")
@RequestParam
String albumId,

@ULID
@Parameter(description = "์‚ฌ์šฉ์ž ID", example = "test_album_id")
@RequestParam
String memberId
);

@Operation(summary = "๊ณต์œ  ์‚ฌ์šฉ์ž ์ƒ์„ฑ", description = "๊ณต์œ  ์‚ฌ์šฉ์ž๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.")
@PostMapping
Mono<SharedMemberResponse> createSharedMember(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ public class SharedMemberController implements SharedMemberApi {

private final SharedMemberService sharedMemberService;

@Override
public Mono<SharedMemberResponse> getSharedMemberByAlbumAndMember(
String requestMemberId,
String albumId,
String memberId
) {
return sharedMemberService.findSharedMemberByAlbumIdAndMemberId(albumId, memberId)
.map(SharedMemberResponse::fromEntity);
}

@Override
public Mono<SharedMemberResponse> createSharedMember(
String memberId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ public class SharedMemberService {

private final AlbumPermissionVerifier albumPermissionVerifier;

@Transactional(readOnly = true)
public Mono<SharedMemberEntity> findSharedMemberByAlbumIdAndMemberId(String albumId, String requestMemberId) {
return sharedMemberQuery.findByAlbumIdAndMemberId(albumId, requestMemberId);
}

@Transactional
public Mono<SharedMemberEntity> addSharedMember(String albumId, String permissionLevel, String sharingMemberId, String requestMemberId) {
return albumPermissionVerifier.verifyOwnershipOrAccessPermission(albumId, requestMemberId, FULL_ACCESS)
Expand Down
15 changes: 12 additions & 3 deletions user-service/src/main/java/kr/mafoo/user/api/MemberApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import kr.mafoo.user.annotation.RequestMemberId;
import kr.mafoo.user.controller.dto.response.MemberDetailResponse;
import kr.mafoo.user.controller.dto.response.MemberResponse;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
Expand All @@ -17,16 +19,23 @@
@Validated
@RequestMapping("/v1/members")
public interface MemberApi {
@Operation(summary = "์‚ฌ์šฉ์ž ๊ฒ€์ƒ‰", description = "ํ‚ค์›Œ๋“œ๋กœ ์‚ฌ์šฉ์ž๋ฅผ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค. (์ด๋ฆ„์œผ๋กœ ๊ฒ€์ƒ‰)")
@Operation(summary = "๊ณต์œ  ์•จ๋ฒ” ๋Œ€์ƒ ์‚ฌ์šฉ์ž ๊ฒ€์ƒ‰", description = "ํ‚ค์›Œ๋“œ๋กœ ์‚ฌ์šฉ์ž๋ฅผ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค. (์ด๋ฆ„์œผ๋กœ ๊ฒ€์ƒ‰)")
@GetMapping
Flux<MemberResponse> getMemberListByName(
Flux<MemberDetailResponse> getMemberListByNameForSharedAlbum(
@RequestMemberId
@Parameter(hidden = true)
String requesterId,

@Parameter(description = "๊ฒ€์ƒ‰์–ด", example = "์‚ฌ๋žŒ")
@RequestParam
String keyword
String keyword,

@Parameter(description = "์•จ๋ฒ” ID", example = "test_album_id")
@RequestParam
String albumId,

// Authorization Header๋ฅผ ๋ฐ›์•„์˜ฌ ๋ชฉ์ 
ServerHttpRequest serverHttpRequest
);

@Operation(summary = "์‚ฌ์šฉ์ž ๋‹จ๊ฑด ์กฐํšŒ", description = "์‚ฌ์šฉ์ž ๋‹จ๊ฑด ์ •๋ณด๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package kr.mafoo.user.controller;

import kr.mafoo.user.api.MemberApi;
import kr.mafoo.user.controller.dto.response.MemberDetailResponse;
import kr.mafoo.user.controller.dto.response.MemberResponse;
import kr.mafoo.user.service.MemberService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
Expand All @@ -14,12 +16,16 @@ public class MemberController implements MemberApi {
private final MemberService memberService;

@Override
public Flux<MemberResponse> getMemberListByName(
public Flux<MemberDetailResponse> getMemberListByNameForSharedAlbum(
String requesterId,
String keyword
String keyword,
String albumId,
ServerHttpRequest serverHttpRequest
) {
return memberService.getMemberByKeyword(keyword)
.map(MemberResponse::fromEntity);
String authorizationToken = serverHttpRequest.getHeaders().getFirst("Authorization");

return memberService.getMemberByKeywordForSharedAlbum(keyword, albumId, authorizationToken)
.map(MemberDetailResponse::fromDto);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package kr.mafoo.user.controller.dto.response;

import io.swagger.v3.oas.annotations.media.Schema;
import kr.mafoo.user.service.dto.MemberDetailDto;

@Schema(description = "์‚ฌ์šฉ์ž์˜ ์ •๋ณด ์‘๋‹ต")
public record MemberDetailResponse(
@Schema(description = "์‚ฌ์šฉ์ž ID", example = "test")
String memberId,

@Schema(description = "์‚ฌ์šฉ์ž ์ด๋ฆ„", example = "์†ก์˜๋ฏผ")
String name,

@Schema(description = "ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ URL", example = "https://mafoo.kr/profile.jpg")
String profileImageUrl,

@Schema(description = "์‹๋ณ„ ๋ฒˆํ˜ธ", example = "0000")
String serialNumber,

@Schema(description = "๊ณต์œ  ์‚ฌ์šฉ์ž ID", example = "test_shared_member_id")
String sharedMemberId,

@Schema(description = "๊ณต์œ  ์ƒํƒœ", example = "PENDING")
String shareStatus,

@Schema(description = "๊ถŒํ•œ ๋‹จ๊ณ„", example = "FULL_ACCESS")
String permissionLevel
) {
public static MemberDetailResponse fromDto(
MemberDetailDto dto
) {
return new MemberDetailResponse(
dto.memberId(),
dto.name(),
dto.profileImageUrl(),
dto.serialNumber(),
dto.sharedMemberId(),
dto.shareStatus(),
dto.permissionLevel()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ public enum ErrorCode {
TOKEN_TYPE_MISMATCH("AU0001", "ํ† ํฐ ํƒ€์ž…์ด ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. (์•„๋งˆ AccessToken?)"),
TOKEN_EXPIRED("AU0002", "ํ† ํฐ์ด ๋งŒ๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค"),
TOKEN_INVALID("AU0003", "ํ† ํฐ์ด ์œ ํšจํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค"),

MAFOO_PHOTO_API_FAILED("MPE0001", "๋งˆํ‘ธ์˜ photo-service API ํ˜ธ์ถœ์ด ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค")
;
private final String code;
private final String message;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package kr.mafoo.user.exception;

public class MafooPhotoApiFailedException extends DomainException {
public MafooPhotoApiFailedException() {
super(ErrorCode.MAFOO_PHOTO_API_FAILED);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import kr.mafoo.user.exception.MemberNotFoundException;
import kr.mafoo.user.repository.MemberRepository;
import kr.mafoo.user.repository.SocialMemberRepository;
import kr.mafoo.user.service.dto.MemberDetailDto;
import kr.mafoo.user.util.IdGenerator;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -19,6 +20,7 @@ public class MemberService {
private final MemberRepository memberRepository;
private final SocialMemberRepository socialMemberRepository;
private final SlackService slackService;
private final SharedMemberService sharedMemberService;

@Transactional
public Mono<Void> quitMemberByMemberId(String memberId) {
Expand All @@ -27,10 +29,13 @@ public Mono<Void> quitMemberByMemberId(String memberId) {
.then(memberRepository.deleteMemberById(memberId));
}

public Flux<MemberEntity> getMemberByKeyword(String keyword) {
public Flux<MemberDetailDto> getMemberByKeywordForSharedAlbum(String keyword, String albumId, String token) {
return memberRepository
.findAllByNameContaining(keyword)
.switchIfEmpty(Mono.error(new MemberNotFoundException()));
.switchIfEmpty(Mono.error(new MemberNotFoundException()))
.concatMap(member -> sharedMemberService.getSharedMemberInfoByAlbumId(albumId, member.getId(), token)
.flatMap(sharedMemberDto -> Mono.just(MemberDetailDto.fromSharedMember(member, sharedMemberDto)))
);
}

public Mono<MemberEntity> getMemberByMemberId(String memberId) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package kr.mafoo.user.service;
import kr.mafoo.user.exception.MafooPhotoApiFailedException;
import kr.mafoo.user.service.dto.SharedMemberDto;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

@RequiredArgsConstructor
@Service
public class SharedMemberService {

@Value("${app.gateway.endpoint}")
private String endpoint;

private final WebClient client;

public Mono<SharedMemberDto> getSharedMemberInfoByAlbumId(String albumId, String memberId, String authorizationToken) {
return client
.get()
.uri(endpoint + "/photo/v1/shared-members?albumId=" + albumId + "&memberId=" + memberId)
.header("Authorization", "Bearer " + authorizationToken)
.retrieve()
.onStatus(status -> status.isSameCodeAs(HttpStatus.BAD_REQUEST), (res) -> Mono.empty())
.onStatus(status -> !status.is2xxSuccessful(), (res) -> Mono.error(new MafooPhotoApiFailedException()))
.bodyToMono(SharedMemberDto.class);
}

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package kr.mafoo.user.service.dto;

import kr.mafoo.user.domain.MemberEntity;

public record MemberDetailDto(
String memberId,
String name,
String profileImageUrl,
String serialNumber,
String sharedMemberId,
String shareStatus,
String permissionLevel
) {
public static MemberDetailDto fromSharedMember(
MemberEntity memberEntity,
SharedMemberDto sharedMemberDto
) {
return new MemberDetailDto(
memberEntity.getId(),
memberEntity.getName(),
memberEntity.getProfileImageUrl(),
String.format("%04d", memberEntity.getSerialNumber()),
sharedMemberDto.sharedMemberId(),
sharedMemberDto.shareStatus(),
sharedMemberDto.permissionLevel()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package kr.mafoo.user.service.dto;

public record SharedMemberDto(
String sharedMemberId,
String shareStatus,
String permissionLevel,
String albumId,
String memberId
) {
}

0 comments on commit 153a726

Please sign in to comment.