Skip to content

Commit

Permalink
Merge pull request #13 from YAPP-Github/feature/#11
Browse files Browse the repository at this point in the history
feat: ์‚ฌ์ง„ ์กฐํšŒ, ์ˆ˜์ •, ์‚ญ์ œ API ๊ตฌํ˜„
  • Loading branch information
gmkim20713 authored Jul 2, 2024
2 parents f304c9c + cf7e544 commit 47b81c7
Show file tree
Hide file tree
Showing 10 changed files with 221 additions and 17 deletions.
21 changes: 17 additions & 4 deletions photo-service/src/main/java/kr/mafoo/photo/api/PhotoApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import kr.mafoo.photo.annotation.RequestMemberId;
import kr.mafoo.photo.controller.dto.request.PhotoCreateRequest;
import kr.mafoo.photo.controller.dto.request.PhotoAlbumUpdateRequest;
import kr.mafoo.photo.controller.dto.request.PhotoUpdateAlbumIdRequest;
import kr.mafoo.photo.controller.dto.response.PhotoResponse;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
Expand All @@ -15,33 +16,45 @@
public interface PhotoApi {
@Operation(summary = "์‚ฌ์ง„ ์กฐํšŒ", description = "์‚ฌ์ง„ ๋ชฉ๋ก์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.")
@GetMapping
Flux<PhotoResponse> getAlbumPhotos(
Flux<PhotoResponse> getPhotos(
@RequestMemberId
String memberId,

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

@Operation(summary = "์‚ฌ์ง„ ์ƒ์„ฑ", description = "์‚ฌ์ง„์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.")
@PostMapping
Mono<PhotoResponse> createPhoto(
@RequestMemberId
String memberId,

@RequestBody
PhotoCreateRequest request
);

@Operation(summary = "์‚ฌ์ง„ ์•จ๋ฒ” ์ˆ˜์ •", description = "์‚ฌ์ง„์„ ๋‹ค๋ฅธ ์•จ๋ฒ”์œผ๋กœ ์ด๋™์‹œํ‚ต๋‹ˆ๋‹ค.")
@PatchMapping("/{photoId}/album")
Mono<PhotoResponse> updatePhotoAlbum(
@RequestMemberId
String memberId,

@Parameter(description = "์‚ฌ์ง„ ID", example = "test_photo_id")
@PathVariable
String photoId,

@RequestBody
PhotoAlbumUpdateRequest request
PhotoUpdateAlbumIdRequest request
);

@Operation(summary = "์‚ฌ์ง„ ์‚ญ์ œ", description = "์‚ฌ์ง„์„ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.")
@DeleteMapping("{photoId}")
Mono<Void> deletePhoto(
@RequestMemberId
String memberId,

@Parameter(description = "์‚ฌ์ง„ ID", example = "test_photo_id")
@PathVariable
String photoId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,33 @@

import kr.mafoo.photo.api.PhotoApi;
import kr.mafoo.photo.controller.dto.request.PhotoCreateRequest;
import kr.mafoo.photo.controller.dto.request.PhotoAlbumUpdateRequest;
import kr.mafoo.photo.controller.dto.request.PhotoUpdateAlbumIdRequest;
import kr.mafoo.photo.controller.dto.response.PhotoResponse;
import kr.mafoo.photo.service.PhotoService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@RequiredArgsConstructor
@RestController
public class PhotoController implements PhotoApi {

private final PhotoService photoService;

@Override
public Flux<PhotoResponse> getAlbumPhotos(
public Flux<PhotoResponse> getPhotos(
String memberId,
String albumId
){
return Flux.just(
new PhotoResponse("test_photo_id_a", "test_album_id_a", "photo_url"),
new PhotoResponse("test_photo_id_b", "test_album_id_a", "photo_url"),
new PhotoResponse("test_photo_id_c", "test_album_id_a", "photo_url")
);
return photoService
.findAllByAlbumId(albumId, memberId)
.map(PhotoResponse::fromEntity);
}

@Override
public Mono<PhotoResponse> createPhoto(
String memberId,
PhotoCreateRequest request
){
return Mono.just(
Expand All @@ -33,18 +38,21 @@ public Mono<PhotoResponse> createPhoto(

@Override
public Mono<PhotoResponse> updatePhotoAlbum(
String memberId,
String photoId,
PhotoAlbumUpdateRequest request
PhotoUpdateAlbumIdRequest request
){
return Mono.just(
new PhotoResponse("test_photo_id", "photo_url", "test_album_id")
);
return photoService
.updatePhotoAlbumId(photoId, request.albumId(), memberId)
.map(PhotoResponse::fromEntity);
}

@Override
public Mono<Void> deletePhoto(
String memberId,
String photoId
){
return Mono.empty();
return photoService
.deletePhotoById(photoId, memberId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import io.swagger.v3.oas.annotations.media.Schema;

@Schema(description = "์‚ฌ์ง„ ์•จ๋ฒ” ์ˆ˜์ • ์š”์ฒญ")
public record PhotoAlbumUpdateRequest(
public record PhotoUpdateAlbumIdRequest(
@Schema(description = "์•จ๋ฒ” ID", example = "test_album_id")
String albumId
) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package kr.mafoo.photo.controller.dto.response;

import io.swagger.v3.oas.annotations.media.Schema;
import kr.mafoo.photo.domain.PhotoEntity;

@Schema(description = "์‚ฌ์ง„ ์‘๋‹ต")
public record PhotoResponse(
Expand All @@ -13,4 +14,13 @@ public record PhotoResponse(
@Schema(description = "์•จ๋ฒ” ID", example = "test_album_id")
String albumId
) {
public static PhotoResponse fromEntity(
PhotoEntity entity
) {
return new PhotoResponse(
entity.getPhotoId(),
entity.getPhotoUrl(),
entity.getAlbumId()
);
}
}
75 changes: 75 additions & 0 deletions photo-service/src/main/java/kr/mafoo/photo/domain/PhotoEntity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package kr.mafoo.photo.domain;

import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.annotation.Transient;
import org.springframework.data.domain.Persistable;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Table;

import java.time.LocalDateTime;

@Getter
@NoArgsConstructor
@Table("photo")
public class PhotoEntity implements Persistable<String> {
@Id
@Column("id")
private String photoId;

@Column("url")
private String photoUrl;

@Column("owner_member_id")
private String ownerMemberId;

@Column("album_id")
private String albumId;

@CreatedDate
@Column("created_at")
private LocalDateTime createdAt;

@LastModifiedDate
@Column("updated_at")
private LocalDateTime updatedAt;

@Transient
private boolean isNew = false;

@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;

PhotoEntity that = (PhotoEntity) obj;
return photoId.equals(that.photoId);
}

@Override
public int hashCode() {
return photoId.hashCode();
}

@Override
public String getId() {
return photoId;
}

public PhotoEntity updateAlbumId(String albumId) {
this.albumId = albumId;
return this;
}

public static PhotoEntity newPhoto(String photoId, String photoUrl, String ownerMemberId) {
PhotoEntity photo = new PhotoEntity();
photo.photoId = photoId;
photo.photoUrl = photoUrl;
photo.ownerMemberId = ownerMemberId;
photo.isNew = true;
return photo;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
@RequiredArgsConstructor
public enum ErrorCode {
ALBUM_NOT_FOUND("AE0001", "์•จ๋ฒ”์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค"),
PHOTO_NOT_FOUND("PE0001", "์‚ฌ์ง„์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค"),

;
private final String code;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package kr.mafoo.photo.exception;

public class PhotoNotFoundException extends DomainException {
public PhotoNotFoundException() {
super(ErrorCode.PHOTO_NOT_FOUND);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package kr.mafoo.photo.repository;

import kr.mafoo.photo.domain.PhotoEntity;
import org.springframework.data.r2dbc.repository.R2dbcRepository;
import reactor.core.publisher.Flux;

public interface PhotoRepository extends R2dbcRepository<PhotoEntity, String> {
Flux<PhotoEntity> findAllByAlbumId(String ownerAlbumId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package kr.mafoo.photo.service;

import kr.mafoo.photo.domain.PhotoEntity;
import kr.mafoo.photo.exception.AlbumNotFoundException;
import kr.mafoo.photo.exception.PhotoNotFoundException;
import kr.mafoo.photo.repository.AlbumRepository;
import kr.mafoo.photo.repository.PhotoRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@RequiredArgsConstructor
@Service
public class PhotoService {
private final PhotoRepository photoRepository;
private final AlbumRepository albumRepository;

public Flux<PhotoEntity> findAllByAlbumId(String albumId, String requestMemberId) {
return albumRepository
.findById(albumId)
.switchIfEmpty(Mono.error(new AlbumNotFoundException()))
.flatMapMany(albumEntity -> {
if(!albumEntity.getOwnerMemberId().equals(requestMemberId)) {
// ๋‚ด ์•จ๋ฒ”์ด ์•„๋‹ˆ๋ฉด ๊ทธ๋ƒฅ ์—†๋Š” ์•จ๋ฒ” ์ฒ˜๋ฆฌ
return Mono.error(new AlbumNotFoundException());
} else {
return photoRepository.findAllByAlbumId(albumId);
}
});
}

public Mono<Void> deletePhotoById(String photoId, String requestMemberId) {
return photoRepository
.findById(photoId)
.switchIfEmpty(Mono.error(new PhotoNotFoundException()))
.flatMap(photoEntity -> {
if(!photoEntity.getOwnerMemberId().equals(requestMemberId)) {
// ๋‚ด ์‚ฌ์ง„์ด ์•„๋‹ˆ๋ฉด ๊ทธ๋ƒฅ ์—†๋Š” ์‚ฌ์ง„ ์ฒ˜๋ฆฌ
return Mono.error(new PhotoNotFoundException());
} else {
return photoRepository.deleteById(photoId);
}
});
}

public Mono<PhotoEntity> updatePhotoAlbumId(String photoId, String albumId, String requestMemberId) {
return photoRepository
.findById(photoId)
.switchIfEmpty(Mono.error(new PhotoNotFoundException()))
.flatMap(photoEntity -> {
if(!photoEntity.getOwnerMemberId().equals(requestMemberId)) {
// ๋‚ด ์‚ฌ์ง„์ด ์•„๋‹ˆ๋ฉด ๊ทธ๋ƒฅ ์—†๋Š” ์‚ฌ์ง„ ์ฒ˜๋ฆฌ
return Mono.error(new PhotoNotFoundException());
} else {
return albumRepository
.findById(albumId)
.switchIfEmpty(Mono.error(new AlbumNotFoundException()))
.flatMap(albumEntity -> {
if(!albumEntity.getOwnerMemberId().equals(requestMemberId)) {
// ๋‚ด ์•จ๋ฒ”์ด ์•„๋‹ˆ๋ฉด ๊ทธ๋ƒฅ ์—†๋Š” ์•จ๋ฒ” ์ฒ˜๋ฆฌ
return Mono.error(new AlbumNotFoundException());
} else {
return photoRepository.save(photoEntity.updateAlbumId(albumId));
}
});
}
});
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
CREATE TABLE photo(
`id` CHAR(26) PRIMARY KEY NOT NULL COMMENT '์‚ฌ์ง„์•„์ด๋””',
`url` VARCHAR(255) NOT NULL COMMENT '์‚ฌ์ง„url',
`owner_member_id` CHAR(26) NOT NULL COMMENT '์‚ฌ์ง„์†Œ์œ ์ž์•„์ด๋””',
`album_id` CHAR(26) NULL COMMENT '์‚ฌ์ง„์•จ๋ฒ”์•„์ด๋””',
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX `photo_idx1` (`owner_member_id`),
INDEX `photo_idx2` (`album_id`)
);

0 comments on commit 47b81c7

Please sign in to comment.