Skip to content
Open
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
17 changes: 13 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,23 @@ repositories {

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
// implementation 'org.springframework.boot:spring-boot-starter-jdbc'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation "org.springframework.boot:spring-boot-starter-validation"
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
implementation 'io.jsonwebtoken:jjwt-api:0.12.3'
implementation 'org.springframework.security:spring-security-crypto'
implementation 'org.projectlombok:lombok'

runtimeOnly 'com.mysql:mysql-connector-j'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.3'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.3'

testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

developmentOnly 'org.springframework.boot:spring-boot-docker-compose'

annotationProcessor 'org.projectlombok:lombok'
}

tasks.named('test') {
Expand Down
21 changes: 18 additions & 3 deletions src/main/java/com/example/devSns/GlobalExceptionHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@


import com.example.devSns.dto.ErrorDto;
import com.example.devSns.exception.InvalidRequestException;
import com.example.devSns.exception.NotFoundException;
import com.example.devSns.exception.RequestConflictException;
import com.example.devSns.exception.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingRequestCookieException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.client.HttpClientErrorException;
Expand Down Expand Up @@ -49,6 +48,17 @@ public ResponseEntity<ErrorDto> handleRequestConflictException(RequestConflictEx
return ResponseEntity.status(409).body(new ErrorDto(e.getMessage()));
}

@ExceptionHandler(UnauthorizedException.class)
public ResponseEntity<ErrorDto> handleUnauthorizedException(UnauthorizedException e) {
return ResponseEntity.status(401).body(new ErrorDto(e.getMessage()));
}

@ExceptionHandler(ForbiddenException.class)
public ResponseEntity<ErrorDto> handleForbiddenException(ForbiddenException e) {
return ResponseEntity.status(403).body(new ErrorDto(e.getMessage()));
}


@ExceptionHandler(NoResourceFoundException.class)
public ResponseEntity<ErrorDto> handleNoResource(NoResourceFoundException e) {
// 필요하면 logger.debug로만 남기기
Expand All @@ -61,6 +71,11 @@ public ResponseEntity<ErrorDto> handleHttpRequestMethodNotSupportedException(Htt
return ResponseEntity.status(404).body(new ErrorDto("Not Found"));
}

@ExceptionHandler(MissingRequestCookieException.class)
public ResponseEntity<ErrorDto> handleMissingRequestCookieException(MissingRequestCookieException e) {
return ResponseEntity.status(400).body(new ErrorDto("Invalid Request"));
}

@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorDto> handleException(Exception e) {

Expand Down
11 changes: 11 additions & 0 deletions src/main/java/com/example/devSns/annotation/LoginUser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.example.devSns.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginUser {
}
54 changes: 54 additions & 0 deletions src/main/java/com/example/devSns/config/WebConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.example.devSns.config;

import com.example.devSns.interceptor.JwtInterceptor;
import com.example.devSns.resolver.LoginUserArgumentResolver;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;
import java.util.Set;

@Configuration
public class WebConfig implements WebMvcConfigurer {
private final JwtInterceptor jwtInterceptor;
private final LoginUserArgumentResolver loginUserArgumentResolver;

public WebConfig(JwtInterceptor jwtInterceptor, LoginUserArgumentResolver loginUserArgumentResolver) {
this.loginUserArgumentResolver = loginUserArgumentResolver;
this.jwtInterceptor = jwtInterceptor;
}

@Override
public void addInterceptors(InterceptorRegistry registry) {
jwtInterceptor.setMethodAllows("/posts", Set.of(HttpMethod.GET));
jwtInterceptor.setMethodAllows("/posts/{postId}/comments", Set.of(HttpMethod.GET));
jwtInterceptor.setMethodAllows("/members", Set.of(HttpMethod.POST));
jwtInterceptor.setMethodAllows("/", Set.of(HttpMethod.GET));

registry.addInterceptor(jwtInterceptor)
.addPathPatterns("/**")
.excludePathPatterns(
"/auth/login",
"/auth/logout",
"/auth",
"/",
"/index.html",
"/favicon.ico",
"/error",
"/static/**",
"/css/**",
"/js/**",
"/images/**"

);

}

@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(loginUserArgumentResolver);
}
}
57 changes: 57 additions & 0 deletions src/main/java/com/example/devSns/controller/AuthController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.example.devSns.controller;

import com.example.devSns.dto.GenericDataDto;
import com.example.devSns.dto.auth.AuthResponseDto;
import com.example.devSns.dto.auth.LoginDto;
import com.example.devSns.service.AuthService;
import com.example.devSns.util.JwtUtil;
import jakarta.validation.Valid;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseCookie;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/auth")
public class AuthController {
private final AuthService authService;
private final JwtUtil jwtUtil;

public AuthController(AuthService authService, JwtUtil jwtUtil) {
this.authService = authService;
this.jwtUtil = jwtUtil;
}

@PostMapping("/login")
public ResponseEntity<GenericDataDto<String>> login(@RequestBody @Valid LoginDto loginDto) {
AuthResponseDto authResponse = authService.login(loginDto);
ResponseCookie cookie = ResponseCookie
.from("refresh_token", authResponse.refreshToken())
.httpOnly(true)
.secure(false) // 개발환경
.sameSite("Strict")
.path("/auth")
.maxAge(jwtUtil.getRefreshExpiration())
.build();

return ResponseEntity.ok()
.header(HttpHeaders.SET_COOKIE, cookie.toString())
.body(new GenericDataDto<>(authResponse.accessToken()));
}

@GetMapping("/logout")
public ResponseEntity<Void> logout(@CookieValue("refresh_token") String refreshToken) {
authService.logout(refreshToken);
return ResponseEntity.noContent().build();
}


@GetMapping
public ResponseEntity<GenericDataDto<String>> reAuthByRefreshToken(@CookieValue("refresh_token") String refreshToken) {
GenericDataDto<String> accessToken = authService.reAuth(refreshToken);
return ResponseEntity.ok().body(accessToken);
}


}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.example.devSns.controller;

import com.example.devSns.annotation.LoginUser;
import com.example.devSns.dto.GenericDataDto;
import com.example.devSns.dto.comment.CommentCreateDto;
import com.example.devSns.dto.comment.CommentResponseDto;
import com.example.devSns.dto.post.PostResponseDto;
import com.example.devSns.service.CommentService;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Positive;
Expand All @@ -28,8 +28,8 @@ public CommentController(CommentService commentService) {


@PostMapping
public ResponseEntity<GenericDataDto<Long>> create(@RequestBody @Valid CommentCreateDto commentCreateDto) {
Long id = commentService.create(commentCreateDto);
public ResponseEntity<GenericDataDto<Long>> create(@RequestBody @Valid CommentCreateDto commentCreateDto, @LoginUser Long memberId) {
Long id = commentService.create(commentCreateDto, memberId);

URI uri = ServletUriComponentsBuilder
.fromCurrentRequest()
Expand All @@ -42,20 +42,21 @@ public ResponseEntity<GenericDataDto<Long>> create(@RequestBody @Valid CommentCr

@GetMapping("/{id}")
public ResponseEntity<CommentResponseDto> getOne(@PathVariable @Positive Long id) {
CommentResponseDto comment = commentService.findOne(id);
CommentResponseDto comment = commentService.findCommentById(id);
return ResponseEntity.ok().body(comment);
}

@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable @Positive Long id) {
commentService.delete(id);
public ResponseEntity<Void> delete(@PathVariable @Positive Long id, @LoginUser Long memberId) {
commentService.delete(id, memberId);
return ResponseEntity.noContent().build();
}

@PatchMapping("/{id}/contents")
public ResponseEntity<CommentResponseDto> contents(@PathVariable @Positive Long id,
@RequestBody @Valid GenericDataDto<String> contentsDto) {
CommentResponseDto comment = commentService.updateContent(id, contentsDto);
@RequestBody @Valid GenericDataDto<String> contentsDto,
@LoginUser Long memberId) {
CommentResponseDto comment = commentService.updateContent(id, contentsDto, memberId);
return ResponseEntity.ok().body(comment);
}

Expand Down
42 changes: 0 additions & 42 deletions src/main/java/com/example/devSns/controller/FollowsController.java

This file was deleted.

10 changes: 6 additions & 4 deletions src/main/java/com/example/devSns/controller/LikeController.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package com.example.devSns.controller;


import com.example.devSns.annotation.LoginUser;
import com.example.devSns.dto.GenericDataDto;
import com.example.devSns.dto.likes.LikesRequestDto;
import com.example.devSns.dto.member.MemberResponseDto;
import com.example.devSns.dto.post.PostResponseDto;
import com.example.devSns.service.LikesService;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Positive;
import lombok.extern.java.Log;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
Expand All @@ -23,14 +25,14 @@ public LikeController(LikesService<T> likeService) {
}

@PostMapping("/{id}/likes")
public ResponseEntity<Void> like(@PathVariable @Positive Long id, @RequestBody @Valid GenericDataDto<Long> memberIdDto) {
likeService.like(new LikesRequestDto(id, memberIdDto.data()));
public ResponseEntity<Void> like(@PathVariable @Positive Long id, @LoginUser Long memberId) {
likeService.like(new LikesRequestDto(id, memberId));
return ResponseEntity.noContent().build();
}

@DeleteMapping("/{id}/likes")
public ResponseEntity<Void> unlike(@PathVariable @Positive Long id, @RequestBody @Valid GenericDataDto<Long> memberIdDto) {
likeService.unlike(new LikesRequestDto(id, memberIdDto.data()));
public ResponseEntity<Void> unlike(@PathVariable @Positive Long id, @LoginUser Long memberId) {
likeService.unlike(new LikesRequestDto(id, memberId));
return ResponseEntity.noContent().build();
}

Expand Down
Loading