Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/DAILY-SNAP-BE-CD.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:

jobs:
build:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest

steps:
- name: Checkout code
Expand All @@ -29,4 +29,4 @@ jobs:

# prod 프로파일을 활성화하여 빌드 ( 테스트 코드 테스트 X )
- name: Build with Gradle
run: ./gradlew clean build -x test -Dspring.profiles.active=prod
run: ./gradlew clean build -x test -Dspring.profiles.active=prod
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ dependencies {
implementation 'org.redisson:redisson-spring-boot-starter:3.36.0'

implementation 'org.sejda.imageio:webp-imageio:0.1.6'

// oauth
implementation 'org.springframework.security:spring-security-oauth2-client:6.3.1'
}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import onepiece.dailysnapbackend.object.dto.CustomUserDetails;
import onepiece.dailysnapbackend.object.dto.CustomOAuth2User;
import onepiece.dailysnapbackend.object.dto.KeywordRequest;
import onepiece.dailysnapbackend.service.keyword.AdminKeywordService;
import onepiece.dailysnapbackend.util.log.LogMonitoringInvocation;
Expand Down Expand Up @@ -33,7 +33,7 @@ public class AdminController implements AdminControllerDocs {
@PostMapping
@LogMonitoringInvocation
public ResponseEntity<Void> addKeyword(
@AuthenticationPrincipal CustomUserDetails userDetails,
@AuthenticationPrincipal CustomOAuth2User userDetails,
@Valid @RequestBody KeywordRequest request) {
adminKeywordService.addKeyword(request);
log.info("[AdminController] 키워드 추가 완료");
Expand All @@ -47,7 +47,7 @@ public ResponseEntity<Void> addKeyword(
@DeleteMapping("/{keyword}")
@LogMonitoringInvocation
public ResponseEntity<Void> deleteKeyword(
@AuthenticationPrincipal CustomUserDetails userDetails,
@AuthenticationPrincipal CustomOAuth2User userDetails,
@PathVariable String keyword) {
adminKeywordService.deleteKeyword(keyword);
return ResponseEntity.ok().build();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package onepiece.dailysnapbackend.controller;

import io.swagger.v3.oas.annotations.Operation;
import onepiece.dailysnapbackend.object.dto.CustomUserDetails;
import onepiece.dailysnapbackend.object.dto.CustomOAuth2User;
import onepiece.dailysnapbackend.object.dto.KeywordRequest;
import org.springframework.http.ResponseEntity;

Expand All @@ -19,7 +19,7 @@ public interface AdminControllerDocs {
- `200 OK` → 성공
"""
)
ResponseEntity<Void> addKeyword(CustomUserDetails userDetails, KeywordRequest request);
ResponseEntity<Void> addKeyword(CustomOAuth2User userDetails, KeywordRequest request);

@Operation(
summary = "특정 키워드 삭제 (관리자 전용)",
Expand All @@ -33,5 +33,5 @@ public interface AdminControllerDocs {
- `200 OK` → 성공
"""
)
ResponseEntity<Void> deleteKeyword(CustomUserDetails userDetails, String keyword);
ResponseEntity<Void> deleteKeyword(CustomOAuth2User userDetails, String keyword);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,12 @@
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import onepiece.dailysnapbackend.object.dto.SignInRequest;
import onepiece.dailysnapbackend.object.dto.SignUpRequest;
import onepiece.dailysnapbackend.service.MemberService;
import onepiece.dailysnapbackend.service.keyword.AdminKeywordService;
import onepiece.dailysnapbackend.service.keyword.KeywordSelectionService;
import onepiece.dailysnapbackend.util.log.LogMonitoringInvocation;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
Expand All @@ -23,30 +17,20 @@
name = "인증 API",
description = "회원 인증 API 제공"
)
public class AuthController implements AuthControllerDocs{
public class AuthController implements AuthControllerDocs {

private final MemberService memberService;
private final KeywordSelectionService keywordSelectionService;
private final AdminKeywordService adminKeywordService;

// ===========================
// 인증 관련 API
// ===========================

// 회원가입
@Override
@PostMapping("/api/auth/sign-up")
@LogMonitoringInvocation
public ResponseEntity<Void> signUp(@Valid @RequestBody SignUpRequest request) {
memberService.signUp(request);
return ResponseEntity.ok().build();
}

// 로그인
@Override
@PostMapping(value = "/login", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@PostMapping(value = "/login")
@LogMonitoringInvocation
public ResponseEntity<Void> signIn(SignInRequest request) {
public ResponseEntity<Void> signIn(SignInRequest request, HttpServletResponse response) {
memberService.socialSignIn(request, response);
return ResponseEntity.ok().build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,63 +3,54 @@
import io.swagger.v3.oas.annotations.Operation;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import onepiece.dailysnapbackend.object.dto.SignInRequest;
import onepiece.dailysnapbackend.object.dto.SignUpRequest;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;

public interface AuthControllerDocs {

@Operation(
summary = "회원가입",
summary = "소셜 로그인",
description = """

이 API는 인증이 필요하지 않습니다.

### 요청 파라미터
- **username** (String): 사용자 이메일 (중복 불가)
- **password** (String): 사용자 비밀번호
- **nickname** (String): 사용자 닉네임 (중복 불가)

### 유의사항
- `username`과 `nickname`은 고유해야 합니다.

"""
)
ResponseEntity<Void> signUp(SignUpRequest request);
클라이언트에서 받은 accessToken을 이용하여 소셜 로그인 처리 후 JWT 토큰을 발급합니다.

### 요청 형식
- Content-Type: application/json

@Operation(
summary = "로그인",
description = """

이 API는 인증이 필요하지 않습니다.

### 요청 파라미터
- **username** (String): 사용자 이메일
- **password** (String): 사용자 비밀번호

"""
### 요청 바디 예시
```json
{
"provider": "KAKAO",
"username": "example@naver.com",
"accessToken": "ya29.A0ARrdaMExampleAccessToken1234567890",
"birth": "2004-01-01",
"nickname": "daily_snap_user"
}
```

### 응답
- `200 OK`: 로그인 또는 회원가입 성공. 응답 헤더에 JWT 토큰 포함

### 응답 헤더 예시
- `Authorization: Bearer <access_token>`
- `Set-Cookie: refresh_token=<refresh_token>; HttpOnly; Secure; SameSite=Strict; Max-Age=<expiration-time>`
"""
)
ResponseEntity<Void> signIn(SignInRequest request);
ResponseEntity<Void> signIn(@Valid @RequestBody SignInRequest request, HttpServletResponse response);

@Operation(
summary = "accessToken 재발급 요청",
description = """

이 API는 인증이 필요하지 않습니다.
요청 바디에 포함된 RefreshToken만으로 새로운 AccessToken을 발급할 수 있습니다.
요청 쿠키에 포함된 RefreshToken만으로 새로운 AccessToken을 발급할 수 있습니다.

### 요청 파라미터
- **Request Body**: JSON 형태의 요청 바디에 포함된 리프레시 토큰
- **Key**: `refreshToken`
- **Cookie**: JSON 형태의 요청 바디에 포함된 리프레시 토큰
- **Name**: `refresh_token`
- **Value**: `리프레시 토큰 값`

**요청 예시:**
```json
{
"refreshToken": "your-refresh-token-value"
}
```


### 반환값
- 새로운 액세스 토큰은 **JSON 응답 바디**에 포함되어 반환됩니다.

Expand All @@ -78,12 +69,12 @@ public interface AuthControllerDocs {
**응답 코드:**
- **200 OK**: 새로운 액세스 토큰 발급 성공 (헤더에 포함됨)
- **401 Unauthorized**: 리프레시 토큰이 유효하지 않거나 만료됨
- **400 Bad Request**: 요청 바디에 리프레시 토큰이 없음
- **400 Bad Request**: 요청에 쿠키가 없거나 리프레시 토큰이 없음

**추가 설명:**
- 이 API는 `HttpServletRequest`의 요청 바디에서 `refreshToken`을 추출하여 처리합니다.
- 이 API는 `HttpServletRequest`의 요청 쿠키에서 `refreshToken`을 추출하여 처리합니다.
- 클라이언트는 `application/json` 형식으로 요청해야 합니다.
"""
)
ResponseEntity<Void> reissue(HttpServletRequest request, HttpServletResponse response);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import jakarta.validation.Valid;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import onepiece.dailysnapbackend.object.dto.CustomUserDetails;
import onepiece.dailysnapbackend.object.dto.CustomOAuth2User;
import onepiece.dailysnapbackend.object.dto.FollowRequest;
import onepiece.dailysnapbackend.object.dto.MemberResponse;
import onepiece.dailysnapbackend.object.postgres.Member;
Expand Down Expand Up @@ -36,7 +36,7 @@ public class FollowController implements FollowControllerDocs{
@PostMapping("/follow")
@LogMonitoringInvocation
public ResponseEntity<Void> followMember(
@AuthenticationPrincipal CustomUserDetails userDetails,
@AuthenticationPrincipal CustomOAuth2User userDetails,
@RequestParam UUID followeeId) {
Member member = userDetails.getMember();
followService.followMember(member, followeeId);
Expand All @@ -47,7 +47,7 @@ public ResponseEntity<Void> followMember(
@DeleteMapping("/follow")
@LogMonitoringInvocation
public ResponseEntity<Void> unfollowMember(
@AuthenticationPrincipal CustomUserDetails userDetails,
@AuthenticationPrincipal CustomOAuth2User userDetails,
@RequestParam UUID followeeId) {
Member member = userDetails.getMember();
followService.unfollowMember(member, followeeId);
Expand All @@ -58,7 +58,7 @@ public ResponseEntity<Void> unfollowMember(
@GetMapping("/followers")
@LogMonitoringInvocation
public Page<MemberResponse> getFollowers(
@AuthenticationPrincipal CustomUserDetails userDetails,
@AuthenticationPrincipal CustomOAuth2User userDetails,
@Valid @ModelAttribute FollowRequest request) {
Member member = userDetails.getMember();
return followService.getFollowerList(member, request);
Expand All @@ -68,7 +68,7 @@ public Page<MemberResponse> getFollowers(
@GetMapping("/followings")
@LogMonitoringInvocation
public Page<MemberResponse> getFollowings(
@AuthenticationPrincipal CustomUserDetails userDetails,
@AuthenticationPrincipal CustomOAuth2User userDetails,
@Valid @ModelAttribute FollowRequest request) {
Member member = userDetails.getMember();
return followService.getFollowingList(member, request);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import io.swagger.v3.oas.annotations.Operation;
import java.util.UUID;
import onepiece.dailysnapbackend.object.dto.CustomUserDetails;
import onepiece.dailysnapbackend.object.dto.CustomOAuth2User;
import onepiece.dailysnapbackend.object.dto.FollowRequest;
import onepiece.dailysnapbackend.object.dto.MemberResponse;
import org.springframework.data.domain.Page;
Expand All @@ -22,7 +22,7 @@ public interface FollowControllerDocs {
- HTTP 200 OK: 팔로우 성공
"""
)
ResponseEntity<Void> followMember(CustomUserDetails userDetails, UUID followeeId);
ResponseEntity<Void> followMember(CustomOAuth2User userDetails, UUID followeeId);

@Operation(
summary = "사용자 언팔로우",
Expand All @@ -36,7 +36,7 @@ public interface FollowControllerDocs {
- HTTP 200 OK: 언팔로우 성공
"""
)
ResponseEntity<Void> unfollowMember(CustomUserDetails userDetails, UUID followeeId);
ResponseEntity<Void> unfollowMember(CustomOAuth2User userDetails, UUID followeeId);

@Operation(
summary = "팔로워 목록 조회",
Expand All @@ -53,7 +53,7 @@ public interface FollowControllerDocs {
- **`Page<MemberResponse>`**: 팔로워 목록 (페이지네이션 적용)
"""
)
Page<MemberResponse> getFollowers(CustomUserDetails userDetails, FollowRequest request);
Page<MemberResponse> getFollowers(CustomOAuth2User userDetails, FollowRequest request);

@Operation(
summary = "팔로잉 목록 조회",
Expand All @@ -70,5 +70,5 @@ public interface FollowControllerDocs {
- **`Page<MemberResponse>`**: 팔로잉 목록 (페이지네이션 적용)
"""
)
Page<MemberResponse> getFollowings(CustomUserDetails userDetails, FollowRequest request);
Page<MemberResponse> getFollowings(CustomOAuth2User userDetails, FollowRequest request);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import onepiece.dailysnapbackend.object.dto.CustomUserDetails;
import onepiece.dailysnapbackend.object.dto.CustomOAuth2User;
import onepiece.dailysnapbackend.object.dto.PostDetailRequest;
import onepiece.dailysnapbackend.object.postgres.Member;
import onepiece.dailysnapbackend.service.LikeService;
Expand All @@ -29,7 +29,7 @@ public class LikeController implements LikeControllerDocs{
@PostMapping
@LogMonitoringInvocation
public ResponseEntity<Integer> postLike(
@AuthenticationPrincipal CustomUserDetails userDetails,
@AuthenticationPrincipal CustomOAuth2User userDetails,
@RequestBody PostDetailRequest request) {
Member member = userDetails.getMember();
return ResponseEntity.ok(likeService.increaseLikes(request, member));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package onepiece.dailysnapbackend.controller;

import io.swagger.v3.oas.annotations.Operation;
import onepiece.dailysnapbackend.object.dto.CustomUserDetails;
import onepiece.dailysnapbackend.object.dto.CustomOAuth2User;
import onepiece.dailysnapbackend.object.dto.PostDetailRequest;
import org.springframework.http.ResponseEntity;

Expand All @@ -21,5 +21,5 @@ public interface LikeControllerDocs {

"""
)
ResponseEntity<Integer> postLike(CustomUserDetails userDetails, PostDetailRequest request);
ResponseEntity<Integer> postLike(CustomOAuth2User userDetails, PostDetailRequest request);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import jakarta.validation.Valid;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import onepiece.dailysnapbackend.object.dto.CustomUserDetails;
import onepiece.dailysnapbackend.object.dto.CustomOAuth2User;
import onepiece.dailysnapbackend.object.dto.PostFilteredRequest;
import onepiece.dailysnapbackend.object.dto.PostFilteredResponse;
import onepiece.dailysnapbackend.object.dto.PostRequest;
Expand Down Expand Up @@ -38,7 +38,7 @@ public class PostController implements PostControllerDocs {
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@LogMonitoringInvocation
public ResponseEntity<PostResponse> uploadPost(
@AuthenticationPrincipal CustomUserDetails userDetails,
@AuthenticationPrincipal CustomOAuth2User userDetails,
@Valid @ModelAttribute PostRequest request) {
Member member = userDetails.getMember();
return ResponseEntity.ok(postService.uploadPost(request, member));
Expand All @@ -48,7 +48,7 @@ public ResponseEntity<PostResponse> uploadPost(
@GetMapping
@LogMonitoringInvocation
public ResponseEntity<Page<PostFilteredResponse>> filteredPosts(
@AuthenticationPrincipal CustomUserDetails userDetails,
@AuthenticationPrincipal CustomOAuth2User userDetails,
@Valid @ModelAttribute PostFilteredRequest request) {
return ResponseEntity.ok(postService.getFilteredPosts(request));
}
Expand Down
Loading