Skip to content
Open
Show file tree
Hide file tree
Changes from 7 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
8 changes: 8 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'jakarta.persistence:jakarta.persistence-api:3.1.0'
implementation 'org.springframework.boot:spring-boot-starter-security'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testCompileOnly 'org.projectlombok:lombok'
testAnnotationProcessor 'org.projectlombok:lombok'
runtimeOnly 'com.mysql:mysql-connector-j'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
Expand Down
70 changes: 70 additions & 0 deletions src/main/java/com/example/demo/AOPexception/ExceptHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package com.example.demo.AOPexception;

import com.example.demo.AOPexception.Exception.*;
import org.apache.coyote.BadRequestException;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.HashMap;
import java.util.Map;

@RestControllerAdvice
public class ExceptHandler {
@ExceptionHandler
public ResponseEntity<ErrorResponse> handleException(GetNotFoundException e) {
return new ResponseEntity<>(new ErrorResponse(e.getMessage()),HttpStatus.NOT_FOUND);
}
@ExceptionHandler
public ResponseEntity<ErrorResponse> handleException(PutDuplicatedException e) {
return new ResponseEntity<>(new ErrorResponse(e.getMessage()),HttpStatus.CONFLICT);
}
Comment on lines +22 to +25

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

얘는 httpstatus가 conflict가 적절한 것이 맞을까요?

@ExceptionHandler
public ResponseEntity<ErrorResponse> handleException(PutNotFoundException e) {
return new ResponseEntity<>(new ErrorResponse(e.getMessage()),HttpStatus.BAD_REQUEST);
}
@ExceptionHandler
public ResponseEntity<ErrorResponse> handleException(PostIllegalArgumemtException e) {
return new ResponseEntity<>(new ErrorResponse(e.getMessage()),HttpStatus.BAD_REQUEST);
}
@ExceptionHandler
public ResponseEntity<ErrorResponse> handleException(PostNotFoundException e) {
return new ResponseEntity<>(new ErrorResponse(e.getMessage()),HttpStatus.BAD_REQUEST);
}
@ExceptionHandler
public ResponseEntity<ErrorResponse> handleException(DeleteExistedExcepton e) {
return new ResponseEntity<>(new ErrorResponse(e.getMessage()),HttpStatus.BAD_REQUEST);
}

Comment on lines +26 to +42

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 친구들은 bad request라고 생각한 이유가 있나요?
왜 get에서 나오는 not found는 status가 not found이고 put이나 post할 때 나오는 not found는 bad request라고 생각하신 걸까요?

@ExceptionHandler
public ResponseEntity<ErrorResponse> handleException(RuntimeException e) {
return new ResponseEntity<>(new ErrorResponse(e.getMessage()),HttpStatus.BAD_REQUEST);
}

@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Map<String, String>> handleValidationExceptions(MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getAllErrors().forEach(error -> {
String fieldName = ((FieldError) error).getField();
String errorMessage = error.getDefaultMessage();
errors.put(fieldName, errorMessage);
});
return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
}

static class ErrorResponse {
String message;

ErrorResponse(String message) {
this.message = message;
}

public String getMessage() {
return message;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.example.demo.AOPexception.Exception;

public class DeleteExistedExcepton extends RuntimeException{
public DeleteExistedExcepton(String msg)
{
super(msg);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.example.demo.AOPexception.Exception;

public class GetNotFoundException extends RuntimeException{
public GetNotFoundException(String msg)
{
super(msg);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.example.demo.AOPexception.Exception;

public class PostIllegalArgumemtException extends RuntimeException{
public PostIllegalArgumemtException(String msg)
{
super(msg);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.example.demo.AOPexception.Exception;

public class PostNotFoundException extends RuntimeException{
public PostNotFoundException(String msg)
{
super(msg);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.example.demo.AOPexception.Exception;

public class PutDuplicatedException extends RuntimeException{
public PutDuplicatedException(String msg)
{
super(msg);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.example.demo.AOPexception.Exception;

public class PutNotFoundException extends RuntimeException{
public PutNotFoundException(String msg)
{
super(msg);
}
}
2 changes: 2 additions & 0 deletions src/main/java/com/example/demo/DemoApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@EnableAspectJAutoProxy
@SpringBootApplication
public class DemoApplication {

Expand Down
14 changes: 14 additions & 0 deletions src/main/java/com/example/demo/config/AppConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.example.demo.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class AppConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
}
33 changes: 33 additions & 0 deletions src/main/java/com/example/demo/config/SecurityConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.example.demo.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.csrf(AbstractHttpConfigurer::disable)
.formLogin(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(authorize -> authorize
.requestMatchers("/members/**").permitAll()
.anyRequest().authenticated())
.exceptionHandling(configurer -> {
configurer.authenticationEntryPoint(((request, response, authException) -> {

}));
configurer.accessDeniedHandler(((request, response, accessDeniedException) -> {

}));
});
return httpSecurity.build();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

@RestController
public class BoardController {

// 과제 수행함
private final BoardService boardService;

public BoardController(BoardService boardService) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

단일 정보를 가져오는 api들이 boards라는 이름을 갖고 있는 것이 적절할까요?

Expand Down
57 changes: 52 additions & 5 deletions src/main/java/com/example/demo/controller/MemberController.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,17 @@

import java.util.List;

import com.example.demo.controller.dto.request.MemberLoginRequest;
import com.example.demo.domain.Member;
import jakarta.servlet.http.HttpSession;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
Expand Down Expand Up @@ -31,34 +41,71 @@ public ResponseEntity<List<MemberResponse>> getMembers() {
return ResponseEntity.ok(response);
}

@PostMapping("/members/login")
public ResponseEntity<String> login(
@RequestBody MemberLoginRequest request,
HttpSession session
) {
Member existingUser = (Member) session.getAttribute("loginUser");
if (existingUser != null) {
return ResponseEntity.status(HttpStatus.FOUND)
.header(HttpHeaders.LOCATION, "/members/info")
.build();
}
Comment on lines +49 to +54

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

session은 컨트롤러에서 잘 처리하셨네요 👍👍


Member user = memberService.login(request);
if (user == null) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body("로그인 아이디 또는 비밀번호가 틀렸습니다.");
}
Comment on lines +56 to +60

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기까지는 욕심일 수도 있는데 user가 없다면 service로직이나 repository 에러를 반환하고 exception handler에서 캐치하는 방식으로 하면 더 깔끔하게 구현 할 수 있었을 것 같아요


session.setAttribute("loginUser", user);
return ResponseEntity.ok(String.format("loginId : %s login success!", user.getEmail()));
}

@GetMapping("/members/info")
public String userInfo(HttpSession session) {
Member loginUser = (Member) session.getAttribute("loginUser");
if (loginUser == null) {
return "로그인 상태가 아닙니다.";
}
return String.format("loginId : %s\nnickname : %s", loginUser.getEmail(), loginUser.getName());
}

@PostMapping("/members/logout")
public String logout(HttpSession session) {
session.invalidate();
return "로그아웃 되었습니다.";
}

@GetMapping("/members/{id}")
public ResponseEntity<MemberResponse> getMember(
@PathVariable Long id
@PathVariable Long id
) {
MemberResponse response = memberService.getById(id);
return ResponseEntity.ok(response);
}

@PostMapping("/members")
public ResponseEntity<MemberResponse> create(
@RequestBody MemberCreateRequest request
@Validated @RequestBody MemberCreateRequest request
) {
MemberResponse response = memberService.create(request);
return ResponseEntity.ok(response);
}

@PutMapping("/members/{id}")
public ResponseEntity<MemberResponse> updateMember(
@PathVariable Long id,
@RequestBody MemberUpdateRequest request
@PathVariable Long id,
@RequestBody MemberUpdateRequest request
) {
MemberResponse response = memberService.update(id, request);
return ResponseEntity.ok(response);
}

@DeleteMapping("/members/{id}")
public ResponseEntity<Void> deleteMember(
@PathVariable Long id
@PathVariable Long id
) {
memberService.delete(id);
return ResponseEntity.noContent().build();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
package com.example.demo.controller.dto.request;


import jakarta.validation.constraints.NotBlank;

public record MemberCreateRequest(
String name,
String email,
String password
@NotBlank(message = "이름을 입력해주세요.")
String name,

@NotBlank(message = "이메일을 입력해주세요.")
String email,

@NotBlank(message = "비밀번호를 입력해주세요.")
String password
) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.example.demo.controller.dto.request;

public record MemberLoginRequest(
String email,
String password
Comment on lines +3 to +5
Copy link

@seongjae6751 seongjae6751 Jul 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

membercreate dto에서는 필드 검증을 하고 여기서는 필드 검증을 하지 않은 이유가 있나요?

)
{
}
Loading