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

[3주차과제] 이원규 #43

Open
wants to merge 24 commits into
base: OneK-2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
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
40 changes: 40 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Spring-JPA-study
D-Coding 백엔드 스터디

## 1주차 과제 제출(23-01-21)
스프링 입문 강의 정리

## 2~4주차 과제
- 간단한 ‘당근마켓’ 벡엔드 구현해보기
### 요구 사항

- 회원가입/로그인 기능
- 상품등록 기능
- 상품페이지 기능
- 마이 페이지(나의 당근 페이지) 기능

### 제한 사항

- Spring 또는 Spring Boot Framework를 사용해야합니다.
- JPA를 사용해야합니다. (Spring data jpa 활용 가능)
- 인증/인가 방식은 JWT & Spring Security 를 활용해야합니다.

### 2주차

- 요구사항대로 당근마켓 ERD 그려보기
- 요구사항 API 구현 (가능한 만큼)
- jwt, security 이용하여 로그인, 회원가입 기능 구현


![dcoding-erd](https://user-images.githubusercontent.com/85729858/215239770-a2ac0b3a-cd5b-443d-b7a3-d026ce9ae5c5.png)


### 3주차

- 피드백 반영하여 카테고리를 enum으로 처리하도록 하고, createdDate와 updatedDate추가
- 로그인 기능 리펙토링
- 회원가입 기능 추가
- 상품 관련 엔티티, 레포지토리, 서비스 추가
- 상태, 카테고리 enum추가

![image](https://user-images.githubusercontent.com/85729858/216071539-42dc3af6-452e-464f-9a68-c52364c5fc3f.png)
13 changes: 11 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
plugins {
id 'java'
id 'org.springframework.boot' version '3.0.1'
id 'org.springframework.boot' version '2.7.8'
id 'io.spring.dependency-management' version '1.1.0'
}

group = 'com.dku'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'
sourceCompatibility = '11'

configurations {
compileOnly {
Expand All @@ -27,6 +27,15 @@ dependencies {
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'

runtimeOnly 'com.h2database:h2'
//implementation 'com.auth0:java-jwt:3.18.2'
// jwt
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
implementation 'io.jsonwebtoken:jjwt-impl:0.11.5'
implementation 'io.jsonwebtoken:jjwt-jackson:0.11.5'

implementation 'org.springframework.boot:spring-boot-starter-validation'
}

tasks.named('test') {
Expand Down
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.data.jpa.repository.config.EnableJpaAuditing;

@EnableJpaAuditing
@SpringBootApplication
public class SpringStudyApplication {

Expand Down
46 changes: 46 additions & 0 deletions src/main/java/com/dku/springstudy/config/SecurityConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.dku.springstudy.config;

import com.dku.springstudy.jwt.JwtAuthenticationFilter;
import com.dku.springstudy.jwt.JwtTokenProvider;
import lombok.RequiredArgsConstructor;
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.config.http.SessionCreationPolicy;

import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;


@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
private final JwtTokenProvider jwtTokenProvider;

@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.httpBasic().disable()
.formLogin().disable()
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/v1/**").permitAll()
//.antMatchers("/api/v1/").hasRole("USER")
//.anyRequest().authenticated()
.anyRequest().permitAll()
.and()
.addFilterBefore(new JwtAuthenticationFilter(jwtTokenProvider), UsernamePasswordAuthenticationFilter.class);
return http.build();
}

@Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
}
23 changes: 23 additions & 0 deletions src/main/java/com/dku/springstudy/domain/BaseTimeEntity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.dku.springstudy.domain;

import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import java.time.LocalDateTime;

@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
@Getter
public class BaseTimeEntity {
@CreatedDate
@Column(updatable = false)
private LocalDateTime createdDate;

@LastModifiedDate
private LocalDateTime lastModifiedDate;
}
4 changes: 4 additions & 0 deletions src/main/java/com/dku/springstudy/domain/like/like.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.dku.springstudy.domain.like;

public class like {
}
36 changes: 36 additions & 0 deletions src/main/java/com/dku/springstudy/domain/product/Category.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.dku.springstudy.domain.product;

import lombok.Getter;

@Getter
public enum Category {
/*
‘디지털기기’, ‘생활가전’, ‘가구/인테리어’, ‘유아동’, ‘생활/가공식품’,
‘유아도서’, ‘스포츠/레저’, ‘여성잡화’, ‘여성의류’, ‘남성패션/잡화’,
‘게임/취미’, ‘뷰티/미용’, ‘반려동물용품’, ‘도서/티켓/음반’, ‘식물’,
‘기타 중고물품’, ‘중고차’
*/
DIGITAL_DEVICE("디지털기기"),
HOME_ELECTRONIC("생활가전"),
FURNITURE_INTERIOR("가구/인테리어"),
CHILD("유아동"),
LIVING_PROCESSED_FOODS("생활/가공식품"),
CHILD_BOOK("유아도서"),
SPORTS_LEISURE("스포츠/레저"),
WOMAN_GOODS("여성잡화"),
WOMAN_CLOTHES("여성의류"),
MAN_FASHION_GOODS("남성패션/잡화"),
GAME_HOBBY("게임/취미"),
BEAUTY("뷰티/미용"),
PET_GOODS("반려동물용품"),
BOOK_TICKET_RECORD("도서/티켓/음반"),
PLANT("식물"),
USED_ETC("기타 중고물품"),
USED_CAR("중고차");

private final String korCategory;

Category(String korCategory) {
this.korCategory = korCategory;
}
}
35 changes: 35 additions & 0 deletions src/main/java/com/dku/springstudy/domain/product/Product.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.dku.springstudy.domain.product;

import com.dku.springstudy.domain.BaseTimeEntity;
import com.dku.springstudy.domain.user.User;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

import javax.persistence.*;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Product extends BaseTimeEntity {
@Id
@GeneratedValue
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;

private String productName;
private String productImgUrl;
private Integer cost;
private String contents;

@Enumerated(EnumType.STRING)
private ProductStatus status;

@Enumerated(EnumType.STRING)
private Category category;


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.dku.springstudy.domain.product;

import lombok.Getter;

@Getter
public enum ProductStatus {
ON_SALE("판매중"), SOLD_OUT("판매완료"), RESERVED("예약중");

private final String korStatus;

ProductStatus(String korStatus) {
this.korStatus = korStatus;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.dku.springstudy.domain.product.repository;

import com.dku.springstudy.domain.product.Product;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ProductRepository extends JpaRepository<Product, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.dku.springstudy.domain.product.service;

import com.dku.springstudy.domain.product.repository.ProductRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class ProductService {
private final ProductRepository productRepository;
}
5 changes: 5 additions & 0 deletions src/main/java/com/dku/springstudy/domain/user/Role.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.dku.springstudy.domain.user;

public enum Role {
USER, ADMIN
}
43 changes: 43 additions & 0 deletions src/main/java/com/dku/springstudy/domain/user/User.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.dku.springstudy.domain.user;

import com.dku.springstudy.domain.BaseTimeEntity;
import com.dku.springstudy.domain.product.Product;
import lombok.*;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class User extends BaseTimeEntity {

@Id
@GeneratedValue
private Long id;

@OneToMany(mappedBy = "user")
private List<Product> products = new ArrayList<>();

private String email;
private String password;
private String username;
private String phoneNumber;
private String nickname;
private String profileImgUrl;

@Enumerated(EnumType.STRING)
private Role role;

@Builder
public User(String email, String password, String username, String phoneNumber, String nickname, String profileImgUrl) {
this.email = email;
this.password = password;
this.username = username;
this.phoneNumber = phoneNumber;
this.nickname = nickname;
this.profileImgUrl = profileImgUrl;
this.role = Role.USER;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.dku.springstudy.domain.user.controller;


import com.dku.springstudy.domain.user.dto.LoginRequestDto;
import com.dku.springstudy.domain.user.dto.SignUpRequestDTO;
import com.dku.springstudy.domain.user.service.UserService;
import com.dku.springstudy.jwt.TokenDto;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1")
public class UserController {
private final UserService userService;

@PostMapping("/signup")
public ResponseEntity<String> signUp(@Valid @RequestBody SignUpRequestDTO requestDTO){
userService.signUp(requestDTO);

return ResponseEntity.status(HttpStatus.CREATED).body(null);
}

@PostMapping("/login")
public TokenDto login(@Valid @RequestBody LoginRequestDto loginRequestDto) {
String email = loginRequestDto.getEmail();
String password = loginRequestDto.getPassword();
return userService.login(email, password);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.dku.springstudy.domain.user.dto;

import lombok.Data;

@Data
public class LoginRequestDto {
private String email;
private String password;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.dku.springstudy.domain.user.dto;

import com.dku.springstudy.domain.user.User;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.NonNull;

@Data
@NoArgsConstructor
public class SignUpRequestDTO {
@NonNull
private String email;
@NonNull
private String password;
@NonNull
private String username;
@NonNull
private String phoneNumber;
@NonNull
private String nickname;

public User toEntity() {
return User.builder()
.email(email)
.password(password)
.username(username)
.phoneNumber(phoneNumber)
.nickname(nickname)
.build();
}
}
Loading