diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..5743d62 Binary files /dev/null and b/.DS_Store differ diff --git a/build.gradle b/build.gradle index ebecd2d..06e10b3 100644 --- a/build.gradle +++ b/build.gradle @@ -22,6 +22,11 @@ repositories { } dependencies { + //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-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-web' diff --git a/gradle/.DS_Store b/gradle/.DS_Store new file mode 100644 index 0000000..7c2841e Binary files /dev/null and b/gradle/.DS_Store differ diff --git a/src/.DS_Store b/src/.DS_Store new file mode 100644 index 0000000..73ec863 Binary files /dev/null and b/src/.DS_Store differ diff --git a/src/main/.DS_Store b/src/main/.DS_Store new file mode 100644 index 0000000..e1ed025 Binary files /dev/null and b/src/main/.DS_Store differ diff --git a/src/main/java/com/hanaro/starbucks/config/JwtAuthenticationFilter.java b/src/main/java/com/hanaro/starbucks/config/JwtAuthenticationFilter.java new file mode 100644 index 0000000..c78cc73 --- /dev/null +++ b/src/main/java/com/hanaro/starbucks/config/JwtAuthenticationFilter.java @@ -0,0 +1,30 @@ +package com.hanaro.starbucks.config; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.filter.GenericFilterBean; + +import java.io.IOException; + +@RequiredArgsConstructor +public class JwtAuthenticationFilter extends GenericFilterBean { + + private final JwtUtil jwtTokenProvider; + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException { + String token = jwtTokenProvider.resolveToken((HttpServletRequest) request); + + if (token != null && jwtTokenProvider.validateToken(token)) { + Authentication authentication = jwtTokenProvider.getAuthentication(token); + SecurityContextHolder.getContext().setAuthentication(authentication); + } + filterChain.doFilter(request, response); + } +} diff --git a/src/main/java/com/hanaro/starbucks/config/JwtUtil.java b/src/main/java/com/hanaro/starbucks/config/JwtUtil.java new file mode 100644 index 0000000..71defae --- /dev/null +++ b/src/main/java/com/hanaro/starbucks/config/JwtUtil.java @@ -0,0 +1,72 @@ +package com.hanaro.starbucks.config; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jws; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import jakarta.annotation.PostConstruct; +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.stereotype.Component; + +import java.util.Base64; +import java.util.Date; +import java.util.List; + +@Component +@RequiredArgsConstructor +public class JwtUtil { + @Value("${jwt.secretKey}") + private String secretKey; + + @Value("${jwt.expiration_time}") + private long expireTime; + + private final UserDetailsService userDetailsService; + + @PostConstruct + protected void init() { + secretKey = Base64.getEncoder().encodeToString(secretKey.getBytes()); + } + + public String createToken(String userId, List roleList) { + Claims claims = Jwts.claims().setSubject(userId); + claims.put("roles", roleList); + Date now = new Date(); + return Jwts.builder() + .setClaims(claims) + .setIssuedAt(now) + .setExpiration(new Date(now.getTime() + expireTime)) + .signWith(SignatureAlgorithm.HS256, secretKey) + .compact(); + } + + public Authentication getAuthentication(String token) { + String userId = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody().getSubject(); + UserDetails userDetails = userDetailsService.loadUserByUsername(userId); + return new UsernamePasswordAuthenticationToken( + userDetails, "", userDetails.getAuthorities() + ); + } + + public String resolveToken(HttpServletRequest request) { + return request.getHeader("X-AUTH-TOKEN"); + } + + public boolean validateToken(String token){ + try{ + Jws claims = Jwts.parser().setSigningKey(secretKey) + .parseClaimsJws(token); + return claims.getBody().getExpiration().before(new Date()) == false; + } + catch (Exception e){ + return false; + } + } + +} diff --git a/src/main/java/com/hanaro/starbucks/config/PasswordEncoderConfig.java b/src/main/java/com/hanaro/starbucks/config/PasswordEncoderConfig.java new file mode 100644 index 0000000..8147c95 --- /dev/null +++ b/src/main/java/com/hanaro/starbucks/config/PasswordEncoderConfig.java @@ -0,0 +1,13 @@ +package com.hanaro.starbucks.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; + +@Configuration +public class PasswordEncoderConfig { + @Bean + public BCryptPasswordEncoder bCryptPasswordEncoder() { + return new BCryptPasswordEncoder(); + } +} diff --git a/src/main/java/com/hanaro/starbucks/config/SecurityConfig.java b/src/main/java/com/hanaro/starbucks/config/SecurityConfig.java new file mode 100644 index 0000000..2ffc000 --- /dev/null +++ b/src/main/java/com/hanaro/starbucks/config/SecurityConfig.java @@ -0,0 +1,77 @@ +package com.hanaro.starbucks.config; + +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.web.SecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.CorsConfigurationSource; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; + +import java.util.Collections; + +@Configuration +@EnableWebSecurity +@RequiredArgsConstructor +public class SecurityConfig { + private final JwtUtil jwtConfig; + + @Bean + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + http + .csrf((auth) -> auth.disable()) + .cors((cors) -> cors.configurationSource(corsConfigurationSource())) + +// .authorizeHttpRequests((auth) -> auth +// // 로그인과 회원가입은 모든 사용자에게 허용한다. +// .requestMatchers( +// new AntPathRequestMatcher("/login"), +// new AntPathRequestMatcher("/signup") +// ).permitAll() // 권한이 있든 말든 모두 접근 가능 +// // admin일 경우에만 /admin에 대한 요청에서 접근을 허용한다. +// .requestMatchers("/admin").hasRole("ADMIN") +// // 그 외 모든 요청은 인증된 사용자에게만 허용한다. +// .anyRequest().authenticated() +// ) +// .formLogin((formLogin) -> formLogin +// .loginProcessingUrl("/login") +// .successHandler(((request, response, authentication) -> { +// System.out.println("로그인 성공했습니다."); +// response.sendRedirect("/"); +// })) +// .permitAll() +// ); + + .authorizeHttpRequests( (auth) -> auth + .requestMatchers( new AntPathRequestMatcher("/**") ) + .permitAll()) + + .sessionManagement(sessionManagement -> + sessionManagement.sessionCreationPolicy( + SessionCreationPolicy.STATELESS // 세션에 저장하지 않겠다. 기본이 세션에 저장하는 것 + )) + .addFilterBefore(new JwtAuthenticationFilter(jwtConfig), + UsernamePasswordAuthenticationFilter.class); + + + return http.build(); + } + + @Bean + CorsConfigurationSource corsConfigurationSource() { + CorsConfiguration config = new CorsConfiguration(); + config.setAllowedHeaders(Collections.singletonList("*")); // 허용할 HTTP header + config.setAllowedMethods(Collections.singletonList("*")); // 허용할 HTTP method + config.setAllowedOriginPatterns(Collections.singletonList("http://localhost:5173")); // 허용할 출처 + config.setAllowCredentials(true); // 쿠키 인증 요청 허용 + + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", config); + return source; + } +} diff --git a/src/main/java/com/hanaro/starbucks/controller/MemberController.java b/src/main/java/com/hanaro/starbucks/controller/MemberController.java new file mode 100644 index 0000000..8d73808 --- /dev/null +++ b/src/main/java/com/hanaro/starbucks/controller/MemberController.java @@ -0,0 +1,68 @@ +package com.hanaro.starbucks.controller; + +import com.hanaro.starbucks.config.JwtUtil; +import com.hanaro.starbucks.dto.member.LoginReqDto; +import com.hanaro.starbucks.dto.member.MemberResDto; +import com.hanaro.starbucks.dto.member.SignupReqDto; +import com.hanaro.starbucks.dto.member.MemberUpdateReqDto; +import com.hanaro.starbucks.service.MemberService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.Arrays; +import java.util.List; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/users") +public class MemberController { + private final MemberService memberService; + private final JwtUtil jwtUtil; + + @GetMapping("") + public List getUsers(){ + return memberService.getUsers(); + } + @GetMapping("/{userIdx}") + public MemberResDto getUser(@PathVariable int userIdx){ + return memberService.getUser(userIdx); + } + + @PostMapping("/signup") + @ResponseBody + public ResponseEntity signup(@RequestBody SignupReqDto user) { + System.out.println(user); + boolean findUser = memberService.findUserByUserId(user.getUserId()); + System.out.println(findUser); + if (!findUser) { + MemberResDto newUser = memberService.createUser(user); + return ResponseEntity.ok(newUser.getUserId()); + } + return ResponseEntity.status(HttpStatus.CONFLICT).body("이미 존재하는 사용자입니다."); + } + + @PostMapping("/login") + @ResponseBody + public ResponseEntity login(@RequestBody LoginReqDto user) { + MemberResDto findUser = memberService.findUserByUserIdAndUserPw(user.getUserId(), user.getUserPw()); + if (findUser != null) { + String token = jwtUtil.createToken(findUser.getUserId(), Arrays.asList(findUser.getUserRole())); + return ResponseEntity.ok(token); + } else { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("로그인에 실패하였습니다. 아이디와 비밀번호를 확인해주세요."); + } + } + + @PutMapping("/admin/{userIdx}") + public void updateUser(@PathVariable int userIdx, @RequestBody MemberUpdateReqDto user){ + memberService.updateUser(userIdx, user); + } + + @DeleteMapping("/admin/{userIdx}") + public void deleteUser(@PathVariable int userIdx){ + memberService.deleteUser(userIdx); + } + +} diff --git a/src/main/java/com/hanaro/starbucks/controller/MenuController.java b/src/main/java/com/hanaro/starbucks/controller/MenuController.java index 33b52bc..063c438 100644 --- a/src/main/java/com/hanaro/starbucks/controller/MenuController.java +++ b/src/main/java/com/hanaro/starbucks/controller/MenuController.java @@ -12,10 +12,12 @@ import java.util.List; +import static com.hanaro.starbucks.util.APIConstant.API_VERSION; + @RestController -@RequestMapping("api/v1/products") -@CrossOrigin(origins = "http://localhost:5173") +@RequestMapping(API_VERSION + "/products") @RequiredArgsConstructor +@CrossOrigin("http://localhost:5173") public class MenuController { private final MenuService menuService; private final CategoryService categoryService; @@ -35,13 +37,13 @@ public MenuResDto getMenuByMenuIdx(@PathVariable int menuIdx) throws Exception{ return menuService.getMenuByMenuIdx(menuIdx); } - @DeleteMapping("/{menuIdx}") + @DeleteMapping("/admin/{menuIdx}") public void deleteMenuByMenuIdx(@PathVariable int menuIdx) throws Exception{ menuService.deleteMenuByMenuIdx(menuIdx); } - @PutMapping(value = "/{menuIdx}", consumes = {MediaType.APPLICATION_JSON_VALUE, "multipart/form-data"}) - public void updateMenu(@PathVariable int menuIdx, @RequestPart(value = "dto") MenuReqDto menuReqDto, @RequestPart(value = "menuImg") MultipartFile img) throws Exception{ + @PutMapping(value = "/admin/{menuIdx}", consumes = {MediaType.APPLICATION_JSON_VALUE, "multipart/form-data"}) + public void updateMenu(@PathVariable int menuIdx, @RequestPart(value = "dto") MenuReqDto menuReqDto, @RequestPart(value = "menuImg", required = false) MultipartFile img) throws Exception{ menuService.updateMenu(menuIdx, menuReqDto, img); } diff --git a/src/main/java/com/hanaro/starbucks/controller/OrderController.java b/src/main/java/com/hanaro/starbucks/controller/OrderController.java index b0744e7..a4ebc5c 100644 --- a/src/main/java/com/hanaro/starbucks/controller/OrderController.java +++ b/src/main/java/com/hanaro/starbucks/controller/OrderController.java @@ -8,9 +8,12 @@ import java.util.List; +import static com.hanaro.starbucks.util.APIConstant.API_VERSION; + @RestController @RequiredArgsConstructor -@RequestMapping("api/v1/orders") +@RequestMapping(API_VERSION + "/orders") +@CrossOrigin("http://localhost:5173") public class OrderController { private final OrderService orderService; @@ -23,12 +26,12 @@ public OrderResDto getOrder(@PathVariable int orderIdx) { return orderService.getOrder(orderIdx); } - @PutMapping("/{orderIdx}") + @PutMapping("/admin/{orderIdx}") public void updateOrder(@PathVariable int orderIdx, @RequestBody OrderEditReqDto orderEditReqDto) { orderService.updateOrder(orderIdx, orderEditReqDto); } - @DeleteMapping("/{orderIdx}") + @DeleteMapping("/admin/{orderIdx}") public void deleteOrder(@PathVariable int orderIdx) { orderService.deleteOrder(orderIdx); } diff --git a/src/main/java/com/hanaro/starbucks/dto/member/LoginReqDto.java b/src/main/java/com/hanaro/starbucks/dto/member/LoginReqDto.java new file mode 100644 index 0000000..a747a8e --- /dev/null +++ b/src/main/java/com/hanaro/starbucks/dto/member/LoginReqDto.java @@ -0,0 +1,12 @@ +package com.hanaro.starbucks.dto.member; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class LoginReqDto { + private String userId, userPw; +} diff --git a/src/main/java/com/hanaro/starbucks/dto/member/MemberResDto.java b/src/main/java/com/hanaro/starbucks/dto/member/MemberResDto.java new file mode 100644 index 0000000..6b54e55 --- /dev/null +++ b/src/main/java/com/hanaro/starbucks/dto/member/MemberResDto.java @@ -0,0 +1,36 @@ +package com.hanaro.starbucks.dto.member; + +import com.hanaro.starbucks.entity.Member; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDate; + +@Getter +@NoArgsConstructor +public class MemberResDto { + private int userIdx; + + private String userId; + + private String userPw; + + private String userNickname; + + private String userRole; + + private int userPoint; + + private LocalDate userJoinDate; + + @Builder + public MemberResDto(Member user){ + this.userId = user.getUserId(); + this.userPw = user.getUserPw(); + this.userNickname = user.getUserNickname(); + this.userRole = user.getUserRole(); + this.userPoint = user.getUserPoint(); + this.userJoinDate = user.getUserJoinDate(); + } +} diff --git a/src/main/java/com/hanaro/starbucks/dto/member/MemberUpdateReqDto.java b/src/main/java/com/hanaro/starbucks/dto/member/MemberUpdateReqDto.java new file mode 100644 index 0000000..ffd353f --- /dev/null +++ b/src/main/java/com/hanaro/starbucks/dto/member/MemberUpdateReqDto.java @@ -0,0 +1,15 @@ +package com.hanaro.starbucks.dto.member; + +import lombok.Getter; + +import java.time.LocalDate; + +@Getter +public class MemberUpdateReqDto { + private String userId; + private String userPw; + private String userNickname; + private String userRole; + private Integer userPoint; + private LocalDate userJoinDate; +} \ No newline at end of file diff --git a/src/main/java/com/hanaro/starbucks/dto/member/SignupReqDto.java b/src/main/java/com/hanaro/starbucks/dto/member/SignupReqDto.java new file mode 100644 index 0000000..53a0b87 --- /dev/null +++ b/src/main/java/com/hanaro/starbucks/dto/member/SignupReqDto.java @@ -0,0 +1,17 @@ +package com.hanaro.starbucks.dto.member; + +import jakarta.validation.constraints.NotBlank; +import lombok.*; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class SignupReqDto { + @NotBlank(message = "아이디는 필수 입력 값입니다.") + private String userId; + @NotBlank(message = "비밀번호는 필수 입력 값입니다.") + private String userPw; + @NotBlank(message = "닉네임은 필수 입력 값입니다.") + private String userNickname; +} diff --git a/src/main/java/com/hanaro/starbucks/dto/menu/MenuReqDto.java b/src/main/java/com/hanaro/starbucks/dto/menu/MenuReqDto.java index 8dfab3c..aad6e89 100644 --- a/src/main/java/com/hanaro/starbucks/dto/menu/MenuReqDto.java +++ b/src/main/java/com/hanaro/starbucks/dto/menu/MenuReqDto.java @@ -11,5 +11,5 @@ public class MenuReqDto { private int menuPrice; - private int category_idx; + private int categoryIdx; } diff --git a/src/main/java/com/hanaro/starbucks/dto/menu/MenuResDto.java b/src/main/java/com/hanaro/starbucks/dto/menu/MenuResDto.java index 031207e..eaf648b 100644 --- a/src/main/java/com/hanaro/starbucks/dto/menu/MenuResDto.java +++ b/src/main/java/com/hanaro/starbucks/dto/menu/MenuResDto.java @@ -22,7 +22,7 @@ public class MenuResDto { private LocalDate menuDate; - private int category_idx; + private int categoryIdx; public MenuResDto(Menu menu) { this.menuIdx = menu.getMenuIdx(); @@ -31,6 +31,6 @@ public MenuResDto(Menu menu) { this.menuPrice = menu.getMenuPrice(); this.menuImage = menu.getMenuImage(); this.menuDate = menu.getMenuDate(); - this.category_idx = menu.getCategory().getCategoryIdx(); + this.categoryIdx = menu.getCategory().getCategoryIdx(); } } diff --git a/src/main/java/com/hanaro/starbucks/dto/orders/OrderResDto.java b/src/main/java/com/hanaro/starbucks/dto/orders/OrderResDto.java index 10cc1e0..171b2d1 100644 --- a/src/main/java/com/hanaro/starbucks/dto/orders/OrderResDto.java +++ b/src/main/java/com/hanaro/starbucks/dto/orders/OrderResDto.java @@ -5,18 +5,18 @@ import lombok.Getter; import java.time.LocalDate; +import java.time.LocalDateTime; @Builder @Getter public class OrderResDto { + private Integer userIdx; + private String userNickname; private int orderIdx; - private String orderId; private Integer totalPrice; - private String orderStatus; - - private LocalDate orderDate; + private LocalDateTime orderDate; } diff --git a/src/main/java/com/hanaro/starbucks/entity/Member.java b/src/main/java/com/hanaro/starbucks/entity/Member.java new file mode 100644 index 0000000..23397d2 --- /dev/null +++ b/src/main/java/com/hanaro/starbucks/entity/Member.java @@ -0,0 +1,57 @@ +package com.hanaro.starbucks.entity; + +import com.hanaro.starbucks.dto.member.MemberUpdateReqDto; +import jakarta.persistence.*; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDate; + +@Entity +@Getter +@NoArgsConstructor +@Table(name = "user") +public class Member { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "user_idx") + private int userIdx; + + @Column(name = "user_id") + private String userId; + + @Column(name = "user_pw") + private String userPw; + + @Column(name = "user_nickname") + private String userNickname; + + @Column(name = "user_role") + private String userRole; + + @Column(name = "user_point") + private int userPoint; + + @Column(name = "user_join_date") + private LocalDate userJoinDate; + + @Builder + public Member(String userId, String userPw, String userNickname) { + this.userId = userId; + this.userPw = userPw; + this.userNickname = userNickname; + this.userRole = "USER"; + this.userPoint = 0; + } + + public void update(MemberUpdateReqDto dto) { + this.userId = dto.getUserId(); + this.userNickname=dto.getUserNickname(); + this.userPw = dto.getUserPw(); + this.userRole = dto.getUserRole(); + this.userPoint = dto.getUserPoint(); + this.userJoinDate = LocalDate.now(); + } +} \ No newline at end of file diff --git a/src/main/java/com/hanaro/starbucks/entity/Orders.java b/src/main/java/com/hanaro/starbucks/entity/Orders.java index 78955e3..eb63417 100644 --- a/src/main/java/com/hanaro/starbucks/entity/Orders.java +++ b/src/main/java/com/hanaro/starbucks/entity/Orders.java @@ -4,6 +4,7 @@ import lombok.Getter; import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.List; @Entity @@ -23,11 +24,11 @@ public class Orders { private String orderStatus; @Column(name = "order_date") - private LocalDate orderDate; + private LocalDateTime orderDate; @ManyToOne - @JoinColumn(name = "user_idx") - private User user; + @JoinColumn(name = "user_idx", nullable = true) + private Member user; @OneToMany(mappedBy = "orders", cascade = CascadeType.ALL) private List orderDetails; diff --git a/src/main/java/com/hanaro/starbucks/entity/User.java b/src/main/java/com/hanaro/starbucks/entity/User.java deleted file mode 100644 index 2b7737a..0000000 --- a/src/main/java/com/hanaro/starbucks/entity/User.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.hanaro.starbucks.entity; - -import jakarta.persistence.*; - -import java.time.LocalDateTime; - -@Entity -@Table(name = "user") -public class User { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "user_idx") - private int userIdx; - - @Column(name = "user_id") - private String userId; - - @Column(name = "user_pw") - private String userPw; - - @Column(name = "user_nickname") - private String userNickname; - - @Column(name = "user_role") - private String userRole; - - @Column(name = "user_point") - private int userPoint; - - @Column(name = "user_join_date") - private LocalDateTime userJoinDate; - -} \ No newline at end of file diff --git a/src/main/java/com/hanaro/starbucks/repository/MemberRepository.java b/src/main/java/com/hanaro/starbucks/repository/MemberRepository.java new file mode 100644 index 0000000..816c268 --- /dev/null +++ b/src/main/java/com/hanaro/starbucks/repository/MemberRepository.java @@ -0,0 +1,14 @@ +package com.hanaro.starbucks.repository; + +import com.hanaro.starbucks.entity.Member; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Optional; + +@Repository +public interface MemberRepository extends JpaRepository { + Optional findByUserId(String userId); + boolean existsByUserId(String userId); +} diff --git a/src/main/java/com/hanaro/starbucks/repository/OrderRepository.java b/src/main/java/com/hanaro/starbucks/repository/OrderRepository.java index 39d4ce4..c06b9db 100644 --- a/src/main/java/com/hanaro/starbucks/repository/OrderRepository.java +++ b/src/main/java/com/hanaro/starbucks/repository/OrderRepository.java @@ -4,6 +4,9 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.List; + @Repository public interface OrderRepository extends JpaRepository { + List findAllByOrderByOrderIdxDesc(); } diff --git a/src/main/java/com/hanaro/starbucks/service/MemberService.java b/src/main/java/com/hanaro/starbucks/service/MemberService.java new file mode 100644 index 0000000..ef478b3 --- /dev/null +++ b/src/main/java/com/hanaro/starbucks/service/MemberService.java @@ -0,0 +1,84 @@ +package com.hanaro.starbucks.service; + +import com.hanaro.starbucks.dto.member.MemberResDto; +import com.hanaro.starbucks.dto.member.SignupReqDto; +import com.hanaro.starbucks.dto.member.MemberUpdateReqDto; +import com.hanaro.starbucks.entity.Member; +import com.hanaro.starbucks.repository.MemberRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +public class MemberService { + private final MemberRepository memberRepository; + private final BCryptPasswordEncoder bCryptPasswordEncoder; + + @Transactional + public List getUsers(){ + return memberRepository.findAll().stream().map(MemberResDto::new).collect(Collectors.toList()); + } + + @Transactional + public MemberResDto getUser(int idx){ + + Optional optionalMember = memberRepository.findById(idx); + if(optionalMember.isEmpty()){ + throw new IllegalArgumentException("존재하지 않는 회원입니다."); + } + return new MemberResDto(optionalMember.get()); + } + + @Transactional + public boolean findUserByUserId(String userId) { + return memberRepository.existsByUserId(userId); + } + + @Transactional + public MemberResDto createUser(SignupReqDto user) { + Member saveEntity = Member.builder() + .userId(user.getUserId()) + .userPw(bCryptPasswordEncoder.encode(user.getUserPw())) + .userNickname(user.getUserNickname()) + .build(); + Member newEntity = memberRepository.save(saveEntity); + return MemberResDto.builder() + .user(newEntity) + .build(); + } + + @Transactional + public MemberResDto findUserByUserIdAndUserPw(String userId, String userPw) { + Member findUser = memberRepository.findByUserId(userId) + .orElseThrow(() -> new BadCredentialsException("아이디에 맞는 회원 정보를 찾을 수 없습니다.")); + + if (bCryptPasswordEncoder.matches(userPw, findUser.getUserPw())) { + return MemberResDto.builder() + .user(findUser) + .build(); + } else { + throw new BadCredentialsException("비밀번호가 일치하지 않습니다."); + } + } + + public void updateUser(int userIdx, MemberUpdateReqDto user){ + Optional optional = memberRepository.findById(userIdx); + if(optional.isEmpty()){ + throw new IllegalArgumentException("존재하지 않는 회원입니다."); + } + Member member = optional.get(); + member.update(user); + memberRepository.save(member); + } + + public void deleteUser(int userIdx){ + memberRepository.deleteById(userIdx); + } +} diff --git a/src/main/java/com/hanaro/starbucks/service/MenuService.java b/src/main/java/com/hanaro/starbucks/service/MenuService.java index c1cebb6..5ae4469 100644 --- a/src/main/java/com/hanaro/starbucks/service/MenuService.java +++ b/src/main/java/com/hanaro/starbucks/service/MenuService.java @@ -50,6 +50,7 @@ public void deleteMenuByMenuIdx(int menuIdx) throws Exception { if (optionalMenu.isEmpty()) { throw new Exception("존재하지 않는 메뉴입니다."); } + s3Uploader.deleteFile(optionalMenu.get().getMenuImage()); menuRepository.deleteById(menuIdx); } @@ -60,15 +61,16 @@ public void updateMenu(int menuIdx, MenuReqDto menuReqDto, MultipartFile img) th throw new Exception("존재하지 않는 메뉴입니다."); } Menu menu = optionalMenu.get(); - Optional optionalCategory = categoryRepository.findById(menuReqDto.getCategory_idx()); + Optional optionalCategory = categoryRepository.findById(menuReqDto.getCategoryIdx()); if (optionalCategory.isEmpty()) { - throw new Exception("존재하지 않는 카테고리입니다."); + throw new Exception("존재하지 않는 카테고리입니다."+ menuReqDto.getCategoryIdx()); } - log.info("메뉴 검색 완"); - String url = s3Uploader.updateFile(img, menu.getMenuImage(), optionalCategory.get().getCategoryName()); - log.info(url); + String url; + + if(img==null || img.isEmpty()) url=menu.getMenuImage(); + else url = s3Uploader.updateFile(img, menu.getMenuImage(), optionalCategory.get().getCategoryName()); + menu.update(menuReqDto, url); - log.info("업데이트 완"); menuRepository.save(menu); } } diff --git a/src/main/java/com/hanaro/starbucks/service/OrderService.java b/src/main/java/com/hanaro/starbucks/service/OrderService.java index a2de661..4b3ae90 100644 --- a/src/main/java/com/hanaro/starbucks/service/OrderService.java +++ b/src/main/java/com/hanaro/starbucks/service/OrderService.java @@ -21,12 +21,16 @@ public class OrderService { private final OrderDetailRepository orderDetailRepository; public List getOrders() { - List orders = orderRepository.findAll(); - List orderResDtos = orders.stream() + List orders = orderRepository.findAllByOrderByOrderIdxDesc(); + return orders.stream() .map(order -> { List orderDetails = order.getOrderDetails(); int totalPrice = calculateTotalPrice(orderDetails); + Integer userIdx = order.getUser() != null ? order.getUser().getUserIdx() : null; + String userNickname = order.getUser()!=null? order.getUser().getUserNickname() : null ; return OrderResDto.builder() + .userIdx(userIdx) + .userNickname(userNickname) .orderIdx(order.getOrderIdx()) .orderId(order.getOrderId()) .totalPrice(totalPrice) @@ -35,12 +39,15 @@ public List getOrders() { .build(); }) .collect(Collectors.toList()); - return orderResDtos; } public OrderResDto getOrder(int orderIdx) { Orders order = findOrderById(orderIdx); + Integer userIdx = order.getUser() != null ? order.getUser().getUserIdx() : null; + String userNickname = order.getUser()!=null? order.getUser().getUserNickname() : null ; return OrderResDto.builder() + .userIdx(userIdx) + .userNickname(userNickname) .orderIdx(order.getOrderIdx()) .orderId(order.getOrderId()) .totalPrice(calculateTotalPrice(order.getOrderDetails())) diff --git a/src/main/java/com/hanaro/starbucks/service/S3Uploader.java b/src/main/java/com/hanaro/starbucks/service/S3Uploader.java index a4235e0..dbd8be6 100644 --- a/src/main/java/com/hanaro/starbucks/service/S3Uploader.java +++ b/src/main/java/com/hanaro/starbucks/service/S3Uploader.java @@ -1,7 +1,7 @@ package com.hanaro.starbucks.service; - import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.model.CannedAccessControlList; +import com.amazonaws.services.s3.model.DeleteObjectRequest; import com.amazonaws.services.s3.model.PutObjectRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -12,7 +12,7 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; +import java.net.URL; import java.net.URLDecoder; import java.util.UUID; @@ -26,13 +26,12 @@ public class S3Uploader { // MultipartFile을 전달받아 File로 전환한 후 S3에 업로드 public String upload(MultipartFile multipartFile, String dirName) throws IOException { - File uploadFile = convert(multipartFile); // 파일 변환할 수 없으면 에러 - String fileName = dirName + "/" + uploadFile.getName(); + String safeDirName = dirName.replace("/", "_"); + String fileName = safeDirName + "/" + uploadFile.getName(); String uploadImageUrl = putS3(uploadFile, fileName); removeNewFile(uploadFile); // 로컬에 생성된 File 삭제 (MultipartFile -> File 전환 하며 로컬에 파일 생성됨) - return uploadImageUrl; // 업로드된 파일의 S3 URL 주소 반환 } @@ -68,17 +67,23 @@ private File convert(MultipartFile file) throws IOException { } // 파일 삭제 - public void deleteFile(String fileName) { + public void deleteFile(String url) { try { - String decodedFileName = URLDecoder.decode(fileName, "UTF-8"); + // URL 객체 생성 + URL s3URL = new URL(url); + String path = s3URL.getPath(); + + if (path.startsWith("/")) { + path = path.substring(1); + } + String decodedFileName = URLDecoder.decode(path, "UTF-8"); log.info("Deleting file from S3: " + decodedFileName); - amazonS3Client.deleteObject(bucket, decodedFileName); - } catch (UnsupportedEncodingException e) { - log.error("Error while decoding the file name: {}", e.getMessage()); + amazonS3Client.deleteObject(new DeleteObjectRequest(bucket, decodedFileName)); + } catch (Exception e) { + log.error("Error deleting file from S3: " + e.getMessage()); } } - // 파일 확장자 추출 private String extractExt(String originalFilename) { int pos = originalFilename.lastIndexOf("."); diff --git a/src/main/java/com/hanaro/starbucks/util/APIConstant.java b/src/main/java/com/hanaro/starbucks/util/APIConstant.java new file mode 100644 index 0000000..ac4c6f8 --- /dev/null +++ b/src/main/java/com/hanaro/starbucks/util/APIConstant.java @@ -0,0 +1,5 @@ +package com.hanaro.starbucks.util; + +public class APIConstant { + public static final String API_VERSION="api/v1"; +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index bab8ff6..f12f669 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -23,4 +23,4 @@ logging.level.org.hibernate.SQL=debug logging.level.org.hibernate.orm.jdbc.bind=trace #s3 -spring.profiles.include=private \ No newline at end of file +spring.profiles.include=private