Skip to content

Commit

Permalink
Merge pull request #76 from YAPP-Github/feature/MAFOO-179
Browse files Browse the repository at this point in the history
[MAFOO-179] feat: ์•จ๋ฒ” ๋ชฉ๋ก ์กฐํšŒ API์— ๊ณต์œ  ๋ฐ›์€ ์•จ๋ฒ”์ด ํฌํ•จ๋˜๋„๋ก ์ˆ˜์ •ํ–ˆ์–ด์š”
  • Loading branch information
gmkim20713 authored Nov 22, 2024
2 parents 98b6f78 + 50682db commit 93ca666
Show file tree
Hide file tree
Showing 9 changed files with 157 additions and 13 deletions.
10 changes: 7 additions & 3 deletions photo-service/src/main/java/kr/mafoo/photo/api/AlbumApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
import kr.mafoo.photo.annotation.RequestMemberId;
import kr.mafoo.photo.annotation.ULID;
import kr.mafoo.photo.controller.dto.request.AlbumCreateRequest;
import kr.mafoo.photo.controller.dto.request.AlbumUpdateDisplayIndexRequest;
import kr.mafoo.photo.controller.dto.request.AlbumUpdateNameAndTypeRequest;
import kr.mafoo.photo.controller.dto.request.AlbumUpdateOwnershipRequest;
import kr.mafoo.photo.controller.dto.response.AlbumDetailResponse;
import kr.mafoo.photo.controller.dto.response.AlbumResponse;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
Expand All @@ -22,9 +23,12 @@
public interface AlbumApi {
@Operation(summary = "์‚ฌ์šฉ์ž ๋ณ„ ์•จ๋ฒ” ๋ชฉ๋ก ์กฐํšŒ", description = "์‚ฌ์šฉ์ž ๋ณ„ ์•จ๋ฒ” ๋ชฉ๋ก์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.")
@GetMapping
Flux<AlbumResponse> getAlbumListByMember(
Flux<AlbumDetailResponse> getAlbumListByMember(
@RequestMemberId
String memberId
String memberId,

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

@Operation(summary = "์•จ๋ฒ” ๋‹จ๊ฑด ์กฐํšŒ", description = "์•จ๋ฒ” ๋‹จ๊ฑด์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

import kr.mafoo.photo.api.AlbumApi;
import kr.mafoo.photo.controller.dto.request.AlbumCreateRequest;
import kr.mafoo.photo.controller.dto.request.AlbumUpdateDisplayIndexRequest;
import kr.mafoo.photo.controller.dto.request.AlbumUpdateNameAndTypeRequest;
import kr.mafoo.photo.controller.dto.request.AlbumUpdateOwnershipRequest;
import kr.mafoo.photo.controller.dto.response.AlbumDetailResponse;
import kr.mafoo.photo.controller.dto.response.AlbumResponse;
import kr.mafoo.photo.service.AlbumService;
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 @@ -19,12 +20,15 @@ public class AlbumController implements AlbumApi {
private final AlbumService albumService;

@Override
public Flux<AlbumResponse> getAlbumListByMember(
String memberId
public Flux<AlbumDetailResponse> getAlbumListByMember(
String memberId,
ServerHttpRequest serverHttpRequest
) {
String authorizationToken = serverHttpRequest.getHeaders().getFirst("Authorization");

return albumService
.findAlbumListByMemberId(memberId)
.map(AlbumResponse::fromEntity);
.findAlbumListByMemberId(memberId, authorizationToken)
.map(AlbumDetailResponse::fromDto);
}

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

import io.swagger.v3.oas.annotations.media.Schema;
import kr.mafoo.photo.domain.enums.AlbumType;
import kr.mafoo.photo.domain.enums.PermissionLevel;
import kr.mafoo.photo.domain.enums.ShareStatus;
import kr.mafoo.photo.service.dto.AlbumDto;

@Schema(description = "์•จ๋ฒ” ์‘๋‹ต")
public record AlbumDetailResponse(
@Schema(description = "์•จ๋ฒ” ID", example = "test_album_id")
String albumId,

@Schema(description = "์•จ๋ฒ” ์ด๋ฆ„", example = "์•ผ๋ฟŒ๋“ค")
String name,

@Schema(description = "์•จ๋ฒ” ์ข…๋ฅ˜", example = "HEART")
AlbumType type,

@Schema(description = "์•จ๋ฒ” ๋‚ด ์‚ฌ์ง„ ์ˆ˜", example = "6")
String photoCount,

@Schema(description = "๊ณต์œ  ๋ฐ›์€ ์•จ๋ฒ” ์ƒํƒœ", example = "null")
ShareStatus shareStatus,

@Schema(description = "๊ณต์œ  ๋ฐ›์€ ์•จ๋ฒ” ๊ถŒํ•œ", example = "null")
PermissionLevel permissionLevel,

@Schema(description = "๊ณต์œ  ๋ฐ›์€ ์•จ๋ฒ” ์†Œ์œ ์ž ํ”„๋กœํ•„ ์‚ฌ์ง„ URL", example = "null")
String ownerProfileImageUrl
) {
public static AlbumDetailResponse fromDto(
AlbumDto dto
) {
return new AlbumDetailResponse(
dto.albumId(),
dto.name(),
dto.type(),
dto.photoCount().toString(),
dto.shareStatus(),
dto.permissionLevel(),
dto.ownerProfileImageUrl()
);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package kr.mafoo.photo.repository;

import kr.mafoo.photo.domain.SharedMemberEntity;
import kr.mafoo.photo.domain.enums.ShareStatus;
import org.springframework.data.r2dbc.repository.R2dbcRepository;
import org.springframework.stereotype.Repository;
import reactor.core.publisher.Flux;
Expand All @@ -9,5 +10,6 @@
@Repository
public interface SharedMemberRepository extends R2dbcRepository<SharedMemberEntity, String> {
Flux<SharedMemberEntity> findAllByAlbumId(String albumId);
Flux<SharedMemberEntity> findAllByMemberIdAndShareStatusNot(String memberId, ShareStatus status);
Mono<SharedMemberEntity> findByAlbumIdAndMemberId(String albumId, String memberId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public Mono<AlbumEntity> verifyOwnershipOrAccessPermission(String albumId, Strin
.flatMap(sharedAlbumMember ->
checkShareStatus(sharedAlbumMember.getShareStatus())
.then(checkAccessPermission(sharedAlbumMember.getPermissionLevel(), permissionLevel))
).then(albumQuery.findById(albumId)) // FIXME : findById ์ค‘๋ณต ์‹คํ–‰ ์ œ๊ฑฐ ํ•„์š”
).then(albumQuery.findById(albumId))
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import kr.mafoo.photo.repository.AlbumRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@Service
Expand All @@ -17,4 +18,9 @@ public Mono<AlbumEntity> findById(String albumId) {
return albumRepository.findById(albumId)
.switchIfEmpty(Mono.error(new AlbumNotFoundException()));
}

public Flux<AlbumEntity> findByMemberId(String memberId) {
return albumRepository.findAllByOwnerMemberIdOrderByDisplayIndex(memberId)
.switchIfEmpty(Mono.error(new AlbumNotFoundException()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
import static kr.mafoo.photo.domain.enums.PermissionLevel.FULL_ACCESS;
import static kr.mafoo.photo.domain.enums.PermissionLevel.VIEW_ACCESS;

import java.util.Comparator;
import kr.mafoo.photo.domain.AlbumEntity;
import kr.mafoo.photo.exception.AlbumNotFoundException;
import kr.mafoo.photo.exception.SharedMemberNotFoundException;
import kr.mafoo.photo.service.dto.AlbumDto;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -19,15 +23,36 @@ public class AlbumService {

private final AlbumPermissionVerifier albumPermissionVerifier;

private final SharedMemberQuery sharedMemberQuery;
private final MemberService memberService;

@Transactional(readOnly = true)
public Flux<AlbumEntity> findAlbumListByMemberId(String memberId) {
return null;
public Flux<AlbumDto> findAlbumListByMemberId(String memberId, String token) {
return Flux.merge(
findOwnedAlbumListByMemberId(memberId),
findSharedAlbumListByMemberId(memberId, token)
).sort(Comparator.comparing(AlbumDto::createdAt).reversed());
}

private Flux<AlbumDto> findOwnedAlbumListByMemberId(String memberId) {
return albumQuery.findByMemberId(memberId)
.onErrorResume(AlbumNotFoundException.class, ex -> Mono.empty())
.map(AlbumDto::fromOwnedAlbum);
}

private Flux<AlbumDto> findSharedAlbumListByMemberId(String memberId, String token) {
return sharedMemberQuery.findAllByMemberIdWhereStatusNotRejected(memberId)
.onErrorResume(SharedMemberNotFoundException.class, ex -> Mono.empty())
.concatMap(sharedMember -> albumQuery.findById(sharedMember.getAlbumId())
.flatMap(album -> memberService.getMemberInfoById(album.getOwnerMemberId(), token)
.flatMap(member -> Mono.just(AlbumDto.fromSharedAlbum(album, sharedMember, member)))
)
);
}

@Transactional(readOnly = true)
public Mono<AlbumEntity> findAlbumById(String albumId, String memberId) {
return albumPermissionVerifier.verifyOwnershipOrAccessPermission(albumId, memberId, VIEW_ACCESS)
.then(albumQuery.findById(albumId));
return albumPermissionVerifier.verifyOwnershipOrAccessPermission(albumId, memberId, VIEW_ACCESS);
}

@Transactional
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package kr.mafoo.photo.service;

import static kr.mafoo.photo.domain.enums.ShareStatus.REJECTED;

import kr.mafoo.photo.domain.SharedMemberEntity;
import kr.mafoo.photo.exception.SharedMemberDuplicatedException;
import kr.mafoo.photo.exception.SharedMemberNotFoundException;
Expand All @@ -20,6 +22,11 @@ public Flux<SharedMemberEntity> findAllByAlbumId(String albumId) {
.switchIfEmpty(Mono.error(new SharedMemberNotFoundException()));
}

public Flux<SharedMemberEntity> findAllByMemberIdWhereStatusNotRejected(String memberId) {
return sharedMemberRepository.findAllByMemberIdAndShareStatusNot(memberId, REJECTED)
.switchIfEmpty(Mono.error(new SharedMemberNotFoundException()));
}

public Mono<SharedMemberEntity> findBySharedMemberId(String sharedMemberId) {
return sharedMemberRepository.findById(sharedMemberId)
.switchIfEmpty(Mono.error(new SharedMemberNotFoundException()));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package kr.mafoo.photo.service.dto;

import java.time.LocalDateTime;
import kr.mafoo.photo.domain.AlbumEntity;
import kr.mafoo.photo.domain.SharedMemberEntity;
import kr.mafoo.photo.domain.enums.AlbumType;
import kr.mafoo.photo.domain.enums.PermissionLevel;
import kr.mafoo.photo.domain.enums.ShareStatus;

public record AlbumDto(
String albumId,
String name,
AlbumType type,
Integer photoCount,
ShareStatus shareStatus,
PermissionLevel permissionLevel,
String ownerProfileImageUrl,
LocalDateTime createdAt
) {
public static AlbumDto fromOwnedAlbum(
AlbumEntity albumEntity
) {
return new AlbumDto(
albumEntity.getAlbumId(),
albumEntity.getName(),
albumEntity.getType(),
albumEntity.getPhotoCount(),
null,
null,
null,
albumEntity.getCreatedAt()
);
}

public static AlbumDto fromSharedAlbum(
AlbumEntity albumEntity,
SharedMemberEntity sharedMemberEntity,
MemberDto memberDto
) {
return new AlbumDto(
albumEntity.getAlbumId(),
albumEntity.getName(),
albumEntity.getType(),
albumEntity.getPhotoCount(),
sharedMemberEntity.getShareStatus(),
sharedMemberEntity.getPermissionLevel(),
memberDto.profileImageUrl(),
sharedMemberEntity.getCreatedAt()
);
}
}

0 comments on commit 93ca666

Please sign in to comment.