Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

부산대 BE_정진택 2주차 과제 (3단계) #394

Open
wants to merge 54 commits into
base: jjt4515
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 51 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
93ec964
spring-gift-product -> spring-gift-wishlist
jjt4515 Jul 3, 2024
1e6e759
Update README.md
jjt4515 Jul 3, 2024
deb4438
fix: ProductDBRepository의 save 로직 수정
jjt4515 Jul 3, 2024
38b1f06
chore: validation 의존성 추가
jjt4515 Jul 4, 2024
de9e5fc
feat: ProductRequest validation 추가
jjt4515 Jul 4, 2024
6679f10
feat: ProductService 예외 처리 로직 추가
jjt4515 Jul 4, 2024
803f1fa
feat: ProductController 로직 수정
jjt4515 Jul 4, 2024
8bcde30
style: ProductDBRepository 로직 수정
jjt4515 Jul 4, 2024
12cb6f4
fix: test 코드 수정
jjt4515 Jul 4, 2024
ed41371
feat: GlobalExceptionHandler 추가
jjt4515 Jul 4, 2024
1716379
feat: InvalidProductDataException, ProductNotFoundException 추가
jjt4515 Jul 4, 2024
39e7ddd
feat: validation 수정
jjt4515 Jul 4, 2024
680146d
Update README.md
jjt4515 Jul 4, 2024
178cbc0
conflict
jjt4515 Jul 4, 2024
b07581e
Update README.md
jjt4515 Jul 4, 2024
26d234a
confilct resolve
jjt4515 Jul 4, 2024
ba19b03
Update README.md
jjt4515 Jul 4, 2024
ac6aeed
Update README.md
jjt4515 Jul 5, 2024
027c703
Update README.md
jjt4515 Jul 5, 2024
2a06e9d
feat: Member클래스 추가
jjt4515 Jul 5, 2024
8119157
feat: MemeberJDBCRepository 추가
jjt4515 Jul 5, 2024
58ab529
feat: MemberService 추가
jjt4515 Jul 5, 2024
4d600ca
feat: CustomUserDetailsService 추가
jjt4515 Jul 5, 2024
9f80601
feat: MemberController 추가
jjt4515 Jul 5, 2024
dcaa848
feat: Member Service 예외 처리
jjt4515 Jul 5, 2024
c837e34
feat: MemberController, MemberService 로직 수정
jjt4515 Jul 5, 2024
3d8bab4
Update README.md
jjt4515 Jul 5, 2024
48acd30
feat: AccessDeniedException 추가
jjt4515 Jul 5, 2024
f5b6b2a
Merge branch 'step2' of https://github.com/jjt4515/spring-gift-wishli…
jjt4515 Jul 5, 2024
5a001e9
Update README.md
jjt4515 Jul 5, 2024
26fd667
feat: WishlistItem추가
jjt4515 Jul 5, 2024
b6c5192
feat: WishlistJDBCRepository 추가
jjt4515 Jul 5, 2024
aa49dda
feat: WishlistService 추가
jjt4515 Jul 5, 2024
5d302bd
feat: WishlistController 추가
jjt4515 Jul 5, 2024
54fbd1a
feat: LoginMember 추가
jjt4515 Jul 5, 2024
3c00aa0
feat: WishlistJDBCRepository 로직 수정
jjt4515 Jul 5, 2024
2a2d357
Merge branch 'step3' of https://github.com/jjt4515/spring-gift-wishli…
jjt4515 Jul 5, 2024
2dd7945
Update README.md
jjt4515 Jul 5, 2024
4899053
feat: schema.sql 수정
jjt4515 Jul 5, 2024
34489c8
Merge branch 'step3' of https://github.com/jjt4515/spring-gift-wishli…
jjt4515 Jul 5, 2024
153d72b
style: ProductService 수정
jjt4515 Jul 7, 2024
49b4ec8
refactor: 모든 Request 수정
jjt4515 Jul 8, 2024
c94767f
refactor: Exception Handler 수정
jjt4515 Jul 8, 2024
962ce6d
chore: dto 패키지 추가
jjt4515 Jul 8, 2024
61825ac
refactor: kakao포함 문구 에러 처리
jjt4515 Jul 8, 2024
5329fb1
docs: schema.sql 수정
jjt4515 Jul 8, 2024
87f5010
refactor: secretKey 변경
jjt4515 Jul 8, 2024
748dfb9
refactor: generateJwtToken 수정
jjt4515 Jul 8, 2024
73410f6
refactor: 토큰 인증 수정
jjt4515 Jul 8, 2024
889881d
refactor: 이메일 중복 에러 처리
jjt4515 Jul 8, 2024
8eaf29a
refactor: 위시리스트 컨트롤러, 서비스 수정
jjt4515 Jul 8, 2024
147d1ad
refactor: 토큰인증 수정
jjt4515 Jul 8, 2024
7228fad
refactor: ProductService 예외 처리 추가
jjt4515 Jul 8, 2024
5a4f6a4
fix: 충돌 해결
jjt4515 Jul 8, 2024
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
55 changes: 54 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,57 @@
# spring-gift-wishlist

## step1

### 기능 요구 사항
상품을 추가하거나 수정하는 경우, 클라이언트로부터 잘못된 값이 전달될 수 있다. 잘못된 값이 전달되면 클라이언트가 어떤 부분이 왜 잘못되었는지 인지할 수 있도록 응답을 제공한다.

- 상품 이름은 공백을 포함하여 최대 15자까지 입력할 수 있다.
- 특수 문자
- 가능: ( ), [ ], +, -, &, /, _
- 그 외 특수 문자 사용 불가
- "카카오"가 포함된 문구는 담당 MD와 협의한 경우에만 사용할 수 있다.

### 구현 기능 목록

- validation
- 상품이름 글자수 최대 15자
- 상품이름 특수 문자 일부만 사용가능( ), [ ], +, -, &, /, _
- 상품이름에 "카카오"가 포함된 문구 제한
- 가격은 양의 정수
- 예외처리
- 존재하지 않는 상품인 경우
- 상품 데이터가 유효하지 않는 경우

## step2

### 기능 요구 사항
상품 관리 코드를 옮겨 온다. 코드를 옮기는 방법에는 디렉터리의 모든 파일을 직접 복사하여 붙여 넣는 것부터 필요한 일부 파일만 이동하는 것, Git을 사용하는 것까지 여러 가지 방법이 있다. 코드 이동 시 반드시 리소스 파일, 프로퍼티 파일, 테스트 코드 등을 함께 이동한다.
사용자가 회원 가입, 로그인, 추후 회원별 기능을 이용할 수 있도록 구현한다.

- 회원은 이메일과 비밀번호를 입력하여 가입한다.
- 토큰을 받으려면 이메일과 비밀번호를 보내야 하며, 가입한 이메일과 비밀번호가 일치하면 토큰이 발급된다.
- 토큰을 생성하는 방법에는 여러 가지가 있다. 방법 중 하나를 선택한다.
- (선택) 회원을 조회, 추가, 수정, 삭제할 수 있는 관리자 화면을 구현한다.

### 구현 기능 목록
- 멤버 회원가입
- 토큰 반환
- 예외 처리
- 멤버 로그인
- 토큰 반환
- 예외 처리

## step3

### 기능 요구 사항
이전 단계에서 로그인 후 받은 토큰을 사용하여 사용자별 위시 리스트 기능을 구현한다.

- 위시 리스트에 등록된 상품 목록을 조회할 수 있다.
- 위시 리스트에 상품을 추가할 수 있다.
- 위시 리스트에 담긴 상품을 삭제할 수 있다.

### 구현 기능 목록
- 멤버별 위시 리스트
- 위시 리스트 상품 목록 조회
- 위시 리스트 상품 추가
- 위시 리스트 상품 삭제
- 예외 처리
6 changes: 6 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,15 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-security'
runtimeOnly 'com.h2database:h2'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
compileOnly 'io.jsonwebtoken:jjwt-api:0.12.6'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.6'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.6'

}

tasks.named('test') {
Expand Down
40 changes: 40 additions & 0 deletions src/main/java/gift/config/FilterConfiguration.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package gift.config;

import gift.repository.TokenRepository;
import gift.filter.AuthFilter;
import gift.filter.LoginFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import jakarta.servlet.Filter;

@Configuration
public class FilterConfiguration {

private final TokenRepository tokenRepository;

@Autowired
public FilterConfiguration(TokenRepository tokenRepository) {
this.tokenRepository = tokenRepository;
}

@Bean(name = "authFilterBean")
public FilterRegistrationBean<Filter> authFilter() {
FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
filterRegistrationBean.setFilter(new AuthFilter(tokenRepository));
filterRegistrationBean.setOrder(1);
filterRegistrationBean.addUrlPatterns("/*");
return filterRegistrationBean;
}

@Bean(name = "loginFilterBean")
public FilterRegistrationBean<Filter> loginFilter() {
FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
filterRegistrationBean.setFilter(new LoginFilter(tokenRepository));
filterRegistrationBean.setOrder(2);
filterRegistrationBean.addUrlPatterns("/members/login");
return filterRegistrationBean;
}
}
14 changes: 14 additions & 0 deletions src/main/java/gift/controller/HomeController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package gift.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HomeController {

@GetMapping("/home")
public String home(){
return "HomePage";
}

}
45 changes: 45 additions & 0 deletions src/main/java/gift/controller/MemberController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package gift.controller;

import gift.dto.request.MemberRequest;
import gift.domain.Member;
import gift.service.MemberService;
import gift.service.TokenService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

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

@RestController
@RequestMapping("/members")
public class MemberController {

private final MemberService memberService;
private final TokenService tokenService;

@Autowired
public MemberController(MemberService memberService, TokenService tokenService) {
this.memberService = memberService;
this.tokenService = tokenService;
}

@PostMapping("/register")
public ResponseEntity<Map<String, String>> register(@RequestBody MemberRequest memberRequest) {
Member member = memberService.register(memberRequest);
String token = tokenService.saveToken(member);
Map<String, String> response = new HashMap<>();
response.put("token", token);
return ResponseEntity.ok(response);
}

@PostMapping("/login")
public ResponseEntity<Map<String, String>> login(@RequestBody MemberRequest memberRequest) {
Member member = memberService.authenticate(memberRequest);
String token = tokenService.saveToken(member);
Map<String, String> response = new HashMap<>();
response.put("token", token);
return ResponseEntity.ok(response);
}

}
17 changes: 7 additions & 10 deletions src/main/java/gift/controller/ProductController.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package gift.controller;

import gift.domain.Product;
import gift.dto.request.ProductRequest;
import gift.service.ProductService;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.*;

@Controller
//@RequestMapping("/api/products")
public class ProductController {
Expand Down Expand Up @@ -40,22 +40,19 @@ public String newProductForm(Model model){
}

@PostMapping("/api/products")
public String addProduct(@ModelAttribute ProductRequest productRequest) {
public String addProduct(@Valid @ModelAttribute ProductRequest productRequest) {
productService.register(productRequest);
return "redirect:/api/products";
}

@GetMapping("/api/products/edit/{id}")
public String editProductForm(@PathVariable long id, Model model){
Optional<Product> product = productService.findOne(id);
if (product.isPresent()){
model.addAttribute("product", product.get());
return "product-edit-form";
};
return "redirect:/api/products";
Product product = productService.findOne(id);
model.addAttribute("product", product);
return "product-edit-form";
}
@PostMapping("/api/products/edit/{id}")
public String updateProduct(@PathVariable Long id, @ModelAttribute ProductRequest productRequest) {
public String updateProduct(@PathVariable Long id, @Valid @ModelAttribute ProductRequest productRequest) {
productService.update(id, productRequest);
return "redirect:/api/products";
}
Expand Down
41 changes: 0 additions & 41 deletions src/main/java/gift/controller/ProductRequest.java

This file was deleted.

37 changes: 37 additions & 0 deletions src/main/java/gift/controller/WishlistController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package gift.controller;

import gift.domain.WishlistItem;
import gift.dto.request.WishlistNameRequest;
import gift.service.WishlistService;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/wishlist")
public class WishlistController {

private final WishlistService wishlistService;

@Autowired
public WishlistController(WishlistService wishlistService) {
this.wishlistService = wishlistService;
}

@PostMapping
public void addToWishlist(@Valid @RequestBody WishlistNameRequest request) {
wishlistService.addItemToWishlist(request);
}

@DeleteMapping("/{itemId}")
public void deleteFromWishlist(@PathVariable Long itemId, @RequestParam Long memberId) {
wishlistService.deleteItemFromWishlist(itemId, memberId);
}

@GetMapping("/{memberId}")
public List<WishlistItem> getWishlist(@PathVariable Long memberId) {
return wishlistService.getWishlistByMemberId(memberId);
}
}
52 changes: 52 additions & 0 deletions src/main/java/gift/domain/Member.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package gift.domain;

import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;

import java.util.UUID;

public class Member {

private Long id;
private String email;
private String password;

public Member() {}

public Member(Long id, String email, String password) {
this.id = id;
this.email = email;
this.password = password;
}

public Member(String email, String password) {
this.email = email;
this.password = password;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}


}
2 changes: 1 addition & 1 deletion src/main/java/gift/domain/Product.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package gift.domain;


import gift.controller.ProductRequest;
import gift.dto.request.ProductRequest;

public class Product {
private long id;
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/gift/domain/TokenAuth.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package gift.domain;

public class TokenAuth {
private String token;
private String email;
public TokenAuth(String token, String email){
this.token = token;
this.email = email;
}
}
Loading