Skip to content

Commit

Permalink
Merge pull request #111 from TRIP-Side-Project/dev
Browse files Browse the repository at this point in the history
merge main
  • Loading branch information
don9m1n authored Dec 21, 2023
2 parents 03de107 + 7833c1f commit d61f41d
Show file tree
Hide file tree
Showing 35 changed files with 468 additions and 183 deletions.
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-mail'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'

// oauth2
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
Expand Down
10 changes: 5 additions & 5 deletions src/main/java/com/api/trip/common/exception/CustomException.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
import lombok.Getter;

@Getter
public abstract class CustomException extends RuntimeException {
public class CustomException extends RuntimeException {

protected CustomException(ErrorCode errorCode){
private final ErrorCode errorCode;

public CustomException(ErrorCode errorCode) {
super(errorCode.getMessage());
this.errorCode = errorCode;
}
private ErrorCode errorCode;


}
29 changes: 26 additions & 3 deletions src/main/java/com/api/trip/common/exception/ErrorCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ public enum ErrorCode {

// 400
EMPTY_REFRESH_TOKEN("RefreshToken이 필요합니다.", HttpStatus.BAD_REQUEST),
EMPTY_EMAIL("이메일이 필요합니다.", HttpStatus.BAD_REQUEST),
INVALID_IMAGE_TYPE("유효하지 않은 파일 형식입니다.", HttpStatus.BAD_REQUEST),

// 401
LOGOUTED_TOKEN("이미 로그아웃 처리된 토큰입니다.", HttpStatus.UNAUTHORIZED),
Expand All @@ -18,9 +20,32 @@ public enum ErrorCode {
EMPTY_AUTHORITY("권한 정보가 필요합니다.", HttpStatus.UNAUTHORIZED),
INVALID_ACCESS_TOKEN("유효하지 않은 AccessToken입니다.", HttpStatus.UNAUTHORIZED),
INVALID_REFRESH_TOKEN("유효하지 않은 RefreshToken입니다.", HttpStatus.UNAUTHORIZED),
INVALID_CURRENT_PASSWORD("현재 비밀번호가 일치하지 않습니다!", HttpStatus.UNAUTHORIZED),
INVALID_NEW_PASSWORD("새 비밀번호가 일치하지 않습니다!", HttpStatus.UNAUTHORIZED),

// 403
FORBIDDEN_CREATE("생성 권한이 없습니다.", HttpStatus.FORBIDDEN),
FORBIDDEN_DELETE("삭제 권한이 없습니다.", HttpStatus.FORBIDDEN),
FORBIDDEN_UPDATE("수정 권한이 없습니다.", HttpStatus.FORBIDDEN),

// 404
NOT_FOUND_MEMBER("회원이 존재하지 않습니다.", HttpStatus.NOT_FOUND);
NOT_FOUND_MEMBER("회원이 존재하지 않습니다.", HttpStatus.NOT_FOUND),
NOT_FOUND_ITEM("상품이 존재하지 않습니다.", HttpStatus.NOT_FOUND),
NOT_FOUND_PROVIDER("지원하지 않는 소셜 로그인 플랫폼 입니다.", HttpStatus.NOT_FOUND),
NOT_FOUND_EMAIL_TOKEN("이메일 인증 토큰이 존재하지 않습니다.", HttpStatus.NOT_FOUND),

ALREADY_JOINED("이미 존재하는 회원입니다.", HttpStatus.CONFLICT),

// 게시판 관련
BAD_REQUEST("잘못된 요청입니다.", HttpStatus.BAD_REQUEST),
UNAUTHORIZED("로그인해 주세요.", HttpStatus.UNAUTHORIZED),
FORBIDDEN("접근 권한이 없습니다.", HttpStatus.FORBIDDEN),
ARTICLE_NOT_FOUND("존재하지 않는 게시글입니다.", HttpStatus.NOT_FOUND),
COMMENT_NOT_FOUND("존재하지 않는 댓글입니다.", HttpStatus.NOT_FOUND),
INTEREST_ARTICLE_ALREADY_EXISTS("이미 좋아한 게시글입니다.", HttpStatus.BAD_REQUEST),
INTEREST_ARTICLE_NOT_FOUND("좋아한 게시글이 아닙니다.", HttpStatus.NOT_FOUND),
UPLOAD_FAILED("파일 업로드에 실패하였습니다.", HttpStatus.INTERNAL_SERVER_ERROR),
;

private final String message;
private final HttpStatus status;
Expand All @@ -29,6 +54,4 @@ public enum ErrorCode {
this.message = message;
this.status = status;
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.api.trip.common.exception.custom_exception;

import com.api.trip.common.exception.CustomException;
import com.api.trip.common.exception.ErrorCode;

public class DuplicateException extends CustomException {
public DuplicateException(ErrorCode errorCode) {
super(errorCode);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.api.trip.common.exception.custom_exception;

import com.api.trip.common.exception.CustomException;
import com.api.trip.common.exception.ErrorCode;

public class ForbiddenException extends CustomException {
public ForbiddenException(ErrorCode errorCode) {
super(errorCode);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.api.trip.common.exception.custom_exception;

import com.api.trip.common.exception.CustomException;
import com.api.trip.common.exception.ErrorCode;

public class NotMatchException extends CustomException {
public NotMatchException(ErrorCode errorCode) {
super(errorCode);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.api.trip.common.security.oauth;

import com.api.trip.common.exception.ErrorCode;
import com.api.trip.common.exception.custom_exception.NotFoundException;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
Expand All @@ -26,7 +28,7 @@ static OAuth2Attribute of(String provider, String attributeKey, Map<String, Obje
case "google" -> google(attributeKey, attributes);
case "kakao" -> kakao(attributeKey, attributes);
case "naver" -> naver(attributeKey, attributes);
default -> throw new RuntimeException();
default -> throw new NotFoundException(ErrorCode.NOT_FOUND_PROVIDER);
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ private static String createCookie(String name, String value) {
.path("/")
.httpOnly(true)
.sameSite("None")
.secure(true)
.build()
.toString();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.api.trip.domain.article.controller.dto;

import com.api.trip.domain.article.model.Article;
import com.api.trip.domain.member.model.Member;
import lombok.Getter;

import java.util.List;
Expand All @@ -12,12 +10,4 @@ public class CreateArticleRequest {
private String title;
private List<String> tags;
private String content;

public Article toEntity(Member writer) {
return Article.builder()
.writer(writer)
.title(title)
.content(content)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.api.trip.domain.article.service;

import com.api.trip.common.exception.CustomException;
import com.api.trip.common.exception.ErrorCode;
import com.api.trip.domain.article.controller.dto.*;
import com.api.trip.domain.article.model.Article;
import com.api.trip.domain.article.repository.ArticleRepository;
Expand All @@ -19,24 +21,28 @@
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;

@Service
@Transactional
@RequiredArgsConstructor
public class ArticleService {

private final ArticleRepository articleRepository;
private final MemberRepository memberRepository;
private final ArticleRepository articleRepository;
private final ArticleTagRepository articleTagRepository;
private final TagRepository tagRepository;
private final InterestArticleRepository interestArticleRepository;
private final ArticleFileRepository articleFileRepository;
private final InterestArticleRepository interestArticleRepository;

public Long createArticle(CreateArticleRequest request, String email) {
Member member = memberRepository.findByEmail(email).orElseThrow();
Member member = memberRepository.findByEmail(email)
.orElseThrow(() -> new CustomException(ErrorCode.UNAUTHORIZED));

final Article article = request.toEntity(member);
final Article article = Article.builder()
.writer(member)
.title(request.getTitle())
.content(request.getContent())
.build();

articleRepository.save(article);

Expand All @@ -58,11 +64,14 @@ public Long createArticle(CreateArticleRequest request, String email) {
}

public void updateArticle(Long articleId, UpdateArticleRequest request, String email) {
Member member = memberRepository.findByEmail(email).orElseThrow();
Member member = memberRepository.findByEmail(email)
.orElseThrow(() -> new CustomException(ErrorCode.UNAUTHORIZED));

Article article = articleRepository.findById(articleId)
.orElseThrow(() -> new CustomException(ErrorCode.ARTICLE_NOT_FOUND));

Article article = articleRepository.findById(articleId).orElseThrow();
if (article.getWriter() != member) {
throw new RuntimeException("수정 권한이 없습니다.");
throw new CustomException(ErrorCode.FORBIDDEN);
}

articleTagRepository.deleteAllByArticle(article);
Expand All @@ -85,11 +94,14 @@ public void updateArticle(Long articleId, UpdateArticleRequest request, String e
}

public void deleteArticle(Long articleId, String email) {
Member member = memberRepository.findByEmail(email).orElseThrow();
Member member = memberRepository.findByEmail(email)
.orElseThrow(() -> new CustomException(ErrorCode.UNAUTHORIZED));

Article article = articleRepository.findById(articleId)
.orElseThrow(() -> new CustomException(ErrorCode.ARTICLE_NOT_FOUND));

Article article = articleRepository.findById(articleId).orElseThrow();
if (article.getWriter() != member) {
throw new RuntimeException("삭제 권한이 없습니다.");
throw new CustomException(ErrorCode.FORBIDDEN);
}

articleTagRepository.deleteAllByArticle(article);
Expand All @@ -100,14 +112,15 @@ public void deleteArticle(Long articleId, String email) {
}

public ReadArticleResponse readArticle(Long articleId, String email) {
Article article = articleRepository.findArticle(articleId).orElseThrow();
Article article = articleRepository.findArticle(articleId)
.orElseThrow(() -> new CustomException(ErrorCode.ARTICLE_NOT_FOUND));

List<ArticleTag> articleTags = articleTagRepository.findArticleTags(article);

InterestArticle interestArticle = null;
if (!Objects.equals(email, "anonymousUser")) {
Member member = memberRepository.findByEmail(email).orElseThrow();
interestArticle = interestArticleRepository.findByMemberAndArticle(member, article);
Member member = memberRepository.findByEmail(email).orElse(null);
if (member != null) {
interestArticle = interestArticleRepository.findByMemberAndArticle(member, article).orElse(null);
}

articleRepository.increaseViewCount(article);
Expand All @@ -132,7 +145,8 @@ public GetArticlesResponse getArticles(Pageable pageable, int sortCode, String c

@Transactional(readOnly = true)
public GetMyArticlesResponse getMyArticles(String email) {
Member member = memberRepository.findByEmail(email).orElseThrow();
Member member = memberRepository.findByEmail(email)
.orElseThrow(() -> new CustomException(ErrorCode.UNAUTHORIZED));

List<Article> articles = articleRepository.findAllByWriterOrderByIdDesc(member);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,43 +1,54 @@
package com.api.trip.domain.articlefile.service;

import com.api.trip.common.exception.CustomException;
import com.api.trip.common.exception.ErrorCode;
import com.api.trip.domain.articlefile.model.ArticleFile;
import com.api.trip.domain.articlefile.repository.ArticleFileRepository;
import com.api.trip.domain.articlefile.uploader.ArticleFileUploader;
import com.api.trip.domain.member.repository.MemberRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

@Service
@Transactional
@RequiredArgsConstructor
public class ArticleFileService {

private final MemberRepository memberRepository;
private final ArticleFileRepository articleFileRepository;
private final ArticleFileUploader articleFileUploader;

public String upload(MultipartFile multipartFile, String email) {
if (Objects.equals(email, "anonymousUser")) {
throw new RuntimeException("접근 권한이 없습니다.");
memberRepository.findByEmail(email)
.orElseThrow(() -> new CustomException(ErrorCode.UNAUTHORIZED));

String url = null;
try {
url = articleFileUploader.upload(multipartFile, UUID.randomUUID().toString());
} catch (IOException e) {
throw new CustomException(ErrorCode.UPLOAD_FAILED);
}

String url = articleFileUploader.upload(multipartFile, UUID.randomUUID().toString());

ArticleFile articleFile = ArticleFile.builder()
.url(url)
.build();

return articleFileRepository.save(articleFile).getUrl();
return articleFileRepository.save(
ArticleFile.builder()
.url(url)
.build()
)
.getUrl();
}

public void deleteTemporaryArticleFilesBefore(LocalDateTime localDateTime) {
List<ArticleFile> articleFiles = articleFileRepository.findAllByArticleNullAndCreatedAtBefore(localDateTime);

articleFileRepository.deleteAllInBatch(articleFiles);

articleFiles.forEach(articleFile -> articleFileUploader.delete(articleFile.getUrl()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,8 @@ public class ArticleFileUploader {
@Value("${cloud.aws.s3.bucket}")
private String bucket;

public String upload(MultipartFile multipartFile, String fileName) {
InputStream inputStream;
try {
inputStream = multipartFile.getInputStream();
} catch (IOException e) {
throw new RuntimeException(e);
}
public String upload(MultipartFile multipartFile, String fileName) throws IOException {
InputStream inputStream = multipartFile.getInputStream();

ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentType(multipartFile.getContentType());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
package com.api.trip.domain.comment.controller.dto;

import com.api.trip.domain.article.model.Article;
import com.api.trip.domain.comment.model.Comment;
import com.api.trip.domain.member.model.Member;
import lombok.Getter;

@Getter
Expand All @@ -11,13 +8,4 @@ public class CreateCommentRequest {
private Long articleId;
private Long parentId;
private String content;

public Comment toEntity(Member writer, Article article, Comment parent) {
return Comment.builder()
.writer(writer)
.article(article)
.content(content)
.parent(parent)
.build();
}
}
Loading

0 comments on commit d61f41d

Please sign in to comment.