Skip to content

Commit

Permalink
[deploy #154] prod 배포 (#155)
Browse files Browse the repository at this point in the history
* [fix #142] 앨범 내 사진 조회 최신순으로 정렬 (#143)

* [fix #140] 앨범 공유 수락 API 로직 수정 (#144)

* [feat #128] 포토부스 관련 API 구현 (#146)

* [feat #128] 포토부스 관련 API 구현

* [fix #128] Photo 공유 수락 API 로직 수정

* [chore #128] swagger 업데이트

* [chore #128] 공백 제거

* [fix #147] 포포리즘 공유 API 수정 (#148)

* [feat #128] 포토부스 관련 API 구현

* [fix #128] Photo 공유 수락 API 로직 수정

* [chore #128] swagger 업데이트

* [chore #128] 공백 제거

* [fix #147] 포포리즘 공유 API 수정

* [chore #147] swagger 수정

* [hotfix #149] 포포리즘 공유 API request body 수정 (#150)

* [hotfix #149] 포포리즘 공유 request body 수정

* [chore #149] 사용하지 않는 import 제거

* [setting #149] banner 추가

* [chore #149] CI 스크립트 수정

* [chore #149] CI prod 스크립트 수정

* [chore #149] cd 스크립트 수정

* [fix #151] 배포 전 버그 수정 (access token 만료 시간 변경, 포포리즘 공유 API 수정) (#152)

* [fix #151] Access Token 만료시간 변경

* [fix #151] 사진 upload url 변경

* [fix #151] 포포리즘 공유시에 이미지 저장 url 변경 (#153)

* [fix #151] Access Token 만료시간 변경

* [fix #151] 사진 upload url 변경

* [hotfix #151] 포포리즘 저장 url 변경

---------

Co-authored-by: Yunseo Kang <[email protected]>
  • Loading branch information
unanchoi and yungu0010 authored Jul 21, 2023
1 parent 584b9bd commit ba855e8
Show file tree
Hide file tree
Showing 25 changed files with 243 additions and 33 deletions.
1 change: 0 additions & 1 deletion .github/workflows/cd-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ jobs:
- name: make application.yml, application-infra.yml
run: |
## create application.yml
mkdir ./src/main/resources
cd ./src/main/resources
# application.yml 파일 생성
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ jobs:
- name: make application.yml, application-infra.yml
run: |
## create application.yml
mkdir ./src/main/resources
cd ./src/main/resources
# application.yml 파일 생성
Expand Down
3 changes: 1 addition & 2 deletions .github/workflows/ci-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,11 @@ jobs:
- name: application.yml
run: |
## create application.yml
mkdir ./src/main/resources
cd ./src/main/resources
# application.yml 파일 생성
touch ./application.yml
touch ./application-infra.yml]
touch ./application-infra.yml
touch ./pophory_fcm.json
# GitHub-Actions 에서 설정한 값을 application.yml 파일에 쓰기
Expand Down
5 changes: 1 addition & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
name: Pophory CI

on:
push:
branches: [ "develop" ]
pull_request:
branches: [ "develop" ]

Expand All @@ -28,12 +26,11 @@ jobs:
- name: application.yml
run: |
## create application.yml
mkdir ./src/main/resources
cd ./src/main/resources
# application.yml 파일 생성
touch ./application.yml
touch ./application-infra.yml]
touch ./application-infra.yml
touch ./pophory_fcm.json
# GitHub-Actions 에서 설정한 값을 application.yml 파일에 쓰기
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public PhotoListGetV2ResponseDto getPhotosByAlbumV2(Long albumId, Long memberId)
photoJpaRepository.findAllByAlbum(getAlbumById(albumId))
.stream()
.sorted(Comparator.comparing(Photo::getTakenAt)
.thenComparing(Photo::getCreatedAt))
.thenComparing(Photo::getCreatedAt).reversed())
.map(PhotoGetV2ResponseDto::of)
.collect(Collectors.toList())
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@
@Service
@RequiredArgsConstructor
public class SocialService {

// TODO: AccessToken 만료시간 2시간으로 설정
protected static final Long ACCESS_TOKEN_EXPIRATION_TIME = 60 * 60 * 1000 * 2 * 100L; // 200시간

protected static final Long ACCESS_TOKEN_EXPIRATION_TIME = 60 * 60 * 1000 * 2L; // 2시간
protected static final Long REFRESH_TOKEN_EXPIRATION_TIME = 60 * 60 * 1000 * 24 * 14L; // 2주

private final JwtTokenProvider jwtTokenProvider;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package com.pophory.pophoryserver.domain.auth;

public enum SocialType {
KAKAO, APPLE;
KAKAO, APPLE, DEFAULT;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,16 @@
import com.pophory.pophoryserver.domain.auth.SocialService;
import com.pophory.pophoryserver.domain.auth.dto.request.AuthRequestDto;
import com.pophory.pophoryserver.domain.auth.dto.response.AuthResponseDto;
import com.pophory.pophoryserver.domain.auth.dto.response.TokenResponseDto;
import com.pophory.pophoryserver.global.util.MemberUtil;
import com.pophory.pophoryserver.global.config.jwt.JwtTokenProvider;
import com.pophory.pophoryserver.global.config.jwt.UserAuthentication;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
Expand All @@ -31,6 +30,7 @@ public class AuthV2Controller {

private final SocialService socialService;
private final AuthService authService;
private final JwtTokenProvider jwtTokenProvider;

@PostMapping
@SecurityRequirement(name = "Authorization")
Expand All @@ -43,4 +43,4 @@ public class AuthV2Controller {
public ResponseEntity<AuthResponseDto> socialLogin(@RequestHeader("Authorization") String socialAccessToken, @RequestBody AuthRequestDto request) throws NoSuchAlgorithmException, InvalidKeySpecException {
return ResponseEntity.ok(socialService.signIn(socialAccessToken, request));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ public interface MemberJpaRepository extends JpaRepository<Member, Long> {
boolean existsMemberBySocialIdAndSocialType(String socialId, SocialType socialType);

Optional<Member> getMemberBySocialIdAndSocialType(String socialId, SocialType socialType);

Optional<Member> findByNickname(String nickname);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import com.pophory.pophoryserver.domain.photo.dto.response.PhotoShareResponseDto;
import com.pophory.pophoryserver.domain.photo.service.PhotoShareService;
import com.pophory.pophoryserver.global.util.MemberUtil;
import com.pophory.pophoryserver.global.util.PhotoUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.pophory.pophoryserver.domain.photo.controller;


import com.pophory.pophoryserver.domain.member.dto.response.MemberMyPageGetResponseDto;
import com.pophory.pophoryserver.domain.photo.dto.response.PhotoAllListResponseDto;
import com.pophory.pophoryserver.domain.photo.service.PhotoService;
import com.pophory.pophoryserver.domain.photo.dto.request.PhotoAddV2RequestDto;
Expand Down Expand Up @@ -41,8 +40,8 @@ public class PhotoV2Controller {
@Parameter(name = "Authorization", description = "Bearer {access_token}", in = ParameterIn.HEADER, required = true, schema = @Schema(type = "string"))
@ApiResponses(value = {
@ApiResponse(responseCode = "201", description = "사진 추가 성공"),
@ApiResponse(responseCode = "400", description = "사진 추가 실패"),
@ApiResponse(responseCode = "500", description = "서버 오류")
@ApiResponse(responseCode = "400", description = "사진 추가 실패", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
})
public ResponseEntity<Void> uploadPhoto(@RequestBody PhotoAddV2RequestDto request, Principal principal) throws URISyntaxException {
PhotoAddResponseDto response = photoService.addPhotoV2(request, MemberUtil.getMemberId(principal));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Data;

@AllArgsConstructor
@Getter
@Data
@Schema(description = "사진 추가 요청 DTO")
public class PhotoAddV2RequestDto {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

@AllArgsConstructor
@Data
@Schema(description = "사진 공유 요청 DTO")
public class PhotoShareRequestDto {

@Schema(description = "사진 파일이름", example = "ca4f3c69-a7ac-45ee-a594-d0567a4b66b2.jpg")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@
import com.pophory.pophoryserver.domain.photo.vo.PhotoSizeVO;
import com.pophory.pophoryserver.global.exception.AlbumLimitExceedException;
import com.pophory.pophoryserver.global.exception.BadRequestException;
import com.pophory.pophoryserver.global.exception.SelfApproveException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityNotFoundException;
import java.util.Objects;

@Service
@RequiredArgsConstructor
Expand All @@ -33,10 +35,14 @@ public PhotoShareApproveResponseDto addPhotoFromShare(Long receiverId, Long shar
Photo sharedPhoto = getPhotoById(sharedPhotoId);
Album album = getAlbumByMemberId(receiverId);
if (!album.checkPhotoLimit()) throw new AlbumLimitExceedException("앨범 한도를 초과했습니다.");
if (sharedPhoto.getAlbum().getMember().getId().equals(receiverId)) {
throw new SelfApproveException("자신의 사진은 수락할 수 없습니다.");
}
Photo photo = Photo.builder()
.imageUrl(sharedPhoto.getImageUrl())
.album(album)
.studio(sharedPhoto.getStudio())
.takenAt(sharedPhoto.getTakenAt())
.photoSizeVO(PhotoSizeVO.of(sharedPhoto.getWidth(), sharedPhoto.getHeight()))
.build();
photoJpaRepository.save(photo);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.pophory.pophoryserver.domain.pophorysm;

import com.pophory.pophoryserver.domain.pophorysm.dto.request.PophorysmShareRequestDto;
import com.pophory.pophoryserver.domain.s3.UploadType;
import com.pophory.pophoryserver.domain.version.dto.response.PophorysmGetPresignedUrlResponseDto;
import com.pophory.pophoryserver.global.util.MemberUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.security.Principal;

import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v2/pophorysm")
@Tag(name = "[Pophorysm] 포포리즘 관련 API")
public class PophorysmController {

private final PophorysmService pophorysmService;

@GetMapping(produces = APPLICATION_JSON_VALUE)
@Operation(summary = "포포리즘 공유를 위한 presigned url 조회")
@Parameter(name = "Authorization", description = "Bearer {access_token}", in = ParameterIn.HEADER, required = true, schema = @Schema(type = "string"))
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "포포리즘 공유를 위한 presigned url 조회 성공"),
@ApiResponse(responseCode = "400", description = "presigned url 조회 실패", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
})
public ResponseEntity<PophorysmGetPresignedUrlResponseDto> getPophorysmPresignedUrl(@RequestParam("u") String nickname, Principal principal) {
return ResponseEntity.ok(pophorysmService.getSharePresignedUrl(UploadType.PHOTO, nickname, MemberUtil.getMemberId(principal)));
}

@PostMapping(consumes = APPLICATION_JSON_VALUE)
@Operation(summary = "포포리즘 공유 API")
@Parameter(name = "Authorization", description = "Bearer {access_token}", in = ParameterIn.HEADER, required = true, schema = @Schema(type = "string"))
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "포포리즘 공유 성공"),
@ApiResponse(responseCode = "400", description = "포포리즘 공유 실패", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
})
public ResponseEntity<Void> sharePhotoByPophorysm(@RequestBody PophorysmShareRequestDto request, Principal principal) {
pophorysmService.sharePhoto(request, MemberUtil.getMemberId(principal));
return ResponseEntity.ok().build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package com.pophory.pophoryserver.domain.pophorysm;

import com.pophory.pophoryserver.domain.album.Album;
import com.pophory.pophoryserver.domain.member.Member;
import com.pophory.pophoryserver.domain.member.MemberJpaRepository;
import com.pophory.pophoryserver.domain.photo.Photo;
import com.pophory.pophoryserver.domain.photo.PhotoJpaRepository;
import com.pophory.pophoryserver.domain.photo.vo.PhotoSizeVO;
import com.pophory.pophoryserver.domain.pophorysm.dto.request.PophorysmShareRequestDto;
import com.pophory.pophoryserver.domain.s3.S3Service;
import com.pophory.pophoryserver.domain.s3.UploadType;
import com.pophory.pophoryserver.domain.studio.Studio;
import com.pophory.pophoryserver.domain.studio.StudioJpaRepository;
import com.pophory.pophoryserver.domain.version.dto.response.PophorysmGetPresignedUrlResponseDto;
import com.pophory.pophoryserver.global.util.PhotoUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.UUID;

@Service
@RequiredArgsConstructor
public class PophorysmService {

private final MemberJpaRepository memberJpaRepository;
private final PhotoJpaRepository photoJpaRepository;
private final StudioJpaRepository studioJpaRepository;
private final S3Service s3Service;

@Value("${pophorysm.id}")
private Long POPHORYSM_ID;

@Value("${cloud.aws.CLOUDFRONT}")
private String CLOUD_FRONT_DOMAIN;

@Transactional(readOnly = true)
public PophorysmGetPresignedUrlResponseDto getSharePresignedUrl(UploadType type, String nickname, Long memberId) {
validatePophoryId(memberId);
String pophoryId = getPophoryIdByMemberNickname(nickname);
String filename = UUID.randomUUID() + ".jpg";
String key = type.getName() + pophoryId + "member" + "/" + filename;
return PophorysmGetPresignedUrlResponseDto.of(s3Service.getPresignedUrl(key),filename, pophoryId);
}

@Transactional
public void sharePhoto(PophorysmShareRequestDto request, Long memberId) {

validatePophoryId(memberId);
Member member = getMemberByNickname(request.getNickname());
Album album = member.getAlbumList().stream().findFirst().orElseThrow(
() -> new IllegalArgumentException("앨범이 존재하지 않습니다.")
);
if (!album.checkPhotoLimit()) {
throw new IllegalArgumentException("앨범의 사진 개수가 초과되었습니다.");
}
photoJpaRepository.save(
Photo.builder()
.album(member.getAlbumList().get(0))
.studio(findPophorysmStudio(request.getStudioName()))
.takenAt(PhotoUtil.changeRequestToTakenAt(request.getTakenAt()))
.imageUrl(CLOUD_FRONT_DOMAIN + "/" + UploadType.PHOTO.getName() + member.getPophoryId() + "member" + "/" + request.getFileName())
.photoSizeVO(PhotoSizeVO.of(request.getWidth(), request.getHeight()))
.build()
);
}

private Studio findPophorysmStudio(String pophorysmStudio) {
return studioJpaRepository.findByName(pophorysmStudio).orElseThrow(
() -> new IllegalArgumentException("포포리즘 스튜디오가 존재하지 않습니다."));

}

private Member getMemberByNickname(String nickname) {
return memberJpaRepository.findByNickname(nickname).orElseThrow(
() -> new IllegalArgumentException("존재하지 않는 닉네임입니다."));
}

private Photo getPhotoById(Long id) {
return photoJpaRepository.findById(id).orElseThrow(
() -> new IllegalArgumentException("존재하지 않는 사진입니다."));
}

private String getPophoryIdByMemberNickname(String nickname) {
return memberJpaRepository.findByNickname(nickname).orElseThrow(
() -> new IllegalArgumentException("존재하지 않는 닉네임입니다.")
).getPophoryId();
}


private void validatePophoryId(Long memberId) {
if (!POPHORYSM_ID.equals(memberId)) {
throw new IllegalArgumentException("포포리즘의 사진을 공유할 수 없습니다.");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.pophory.pophoryserver.domain.pophorysm.dto.request;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;

@AllArgsConstructor
@Data
public class PophorysmShareRequestDto {

@Schema(description = "유저 닉네임", example = "kraken")
private String nickname;

@Schema(description = "파일 이름", example = "ca4f3c69-a7ac-45ee-a594-d0567a4b66b2.jpg")
private String fileName;

@Schema(description = "포포리 id", example = "2d3dfa")
private String pophoryId;

@Schema(description = "사진 가로 길이", example = "600")
private Integer width;

@Schema(description = "사진 세로 길이", example = "800")
private Integer height;

@Schema(description = "스튜디오 이름", example = "포포리즘")
private String studioName;

@Schema(description = "찍은 날짜", example = "2021.06.30")
private String takenAt;
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package com.pophory.pophoryserver.domain.studio;

import com.pophory.pophoryserver.domain.member.Member;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface StudioJpaRepository extends JpaRepository<Studio, Long> {

Optional<Studio> findByName(String name);
}
Loading

0 comments on commit ba855e8

Please sign in to comment.