From add5ffdd71407d98ddfe16fbd045c59754b3d15b Mon Sep 17 00:00:00 2001 From: manirDev <mhtnourmhtmjr@gmail.com> Date: Fri, 11 Nov 2022 17:09:50 +0300 Subject: [PATCH 01/16] Shopping cart response and code refactor is done successfully :) --- .../controller/ShoppingCartController.java | 23 ++--- .../dto/CartItemDto.java | 4 + .../service/CommonService.java | 5 ++ .../service/Impl/CommonServiceImpl.java | 16 ++++ .../service/Impl/ShoppingCartServiceImpl.java | 87 ++++++++++--------- .../service/ShoppingCartService.java | 10 +-- 6 files changed, 87 insertions(+), 58 deletions(-) diff --git a/src/main/java/com/manir/springbootecommercerestapi/controller/ShoppingCartController.java b/src/main/java/com/manir/springbootecommercerestapi/controller/ShoppingCartController.java index 73e8ada..1880715 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/controller/ShoppingCartController.java +++ b/src/main/java/com/manir/springbootecommercerestapi/controller/ShoppingCartController.java @@ -1,6 +1,7 @@ package com.manir.springbootecommercerestapi.controller; import com.manir.springbootecommercerestapi.dto.CartItemDto; +import com.manir.springbootecommercerestapi.response.CartItemResponse; import com.manir.springbootecommercerestapi.service.ShoppingCartService; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -18,29 +19,29 @@ public class ShoppingCartController { //find by customer api @GetMapping("/findByCustomer/{customerId}") - public List<CartItemDto> findByCustomerId(@PathVariable Long customerId){ - List<CartItemDto> responseCartItems = shoppingCartService.findByCustomerId(customerId); + public CartItemResponse findByCustomerId(@PathVariable Long customerId){ + CartItemResponse responseCartItems = shoppingCartService.findByCustomerId(customerId); return responseCartItems; } //add item to the cart api @PostMapping("/addItem/{customerId}/{productId}/{quantity}") - public ResponseEntity<CartItemDto> addCartItem(@PathVariable Long customerId, - @PathVariable Long productId, - @PathVariable Integer quantity){ - CartItemDto responseCartItem = shoppingCartService.addCartItem(customerId, productId, quantity); + public ResponseEntity<CartItemResponse> addCartItem(@PathVariable Long customerId, + @PathVariable Long productId, + @PathVariable Integer quantity){ + CartItemResponse responseCartItem = shoppingCartService.addCartItem(customerId, productId, quantity); return new ResponseEntity<>(responseCartItem, HttpStatus.CREATED); } //update item quantity api @PutMapping("/updateItemQuantity/{customerId}/{productId}/{quantity}") - public ResponseEntity<CartItemDto> updateItemQuantity(@PathVariable Long customerId, - @PathVariable Long productId, - @PathVariable Integer quantity){ + public ResponseEntity<CartItemResponse> updateItemQuantity(@PathVariable Long customerId, + @PathVariable Long productId, + @PathVariable Integer quantity){ - CartItemDto responseCartItem = shoppingCartService.updateItemQuantity(customerId, productId, quantity); + CartItemResponse responseCartItem = shoppingCartService.updateItemQuantity(customerId, productId, quantity); return new ResponseEntity<>(responseCartItem, HttpStatus.OK); } @@ -49,6 +50,6 @@ public ResponseEntity<CartItemDto> updateItemQuantity(@PathVariable Long custome @DeleteMapping("/deleteItemProduct/{customerId}/{productId}") public ResponseEntity<String> deleteItemProduct(@PathVariable Long customerId, @PathVariable Long productId){ shoppingCartService.deleteItemProduct(customerId, productId); - return ResponseEntity.ok("Product deleted successfully from cart item"); + return ResponseEntity.ok("Product with id = " + productId +" is deleted successfully from your shopping cart"); } } diff --git a/src/main/java/com/manir/springbootecommercerestapi/dto/CartItemDto.java b/src/main/java/com/manir/springbootecommercerestapi/dto/CartItemDto.java index 62776fd..b5baf24 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/dto/CartItemDto.java +++ b/src/main/java/com/manir/springbootecommercerestapi/dto/CartItemDto.java @@ -1,5 +1,7 @@ package com.manir.springbootecommercerestapi.dto; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.manir.springbootecommercerestapi.model.Product; import lombok.Data; @Data @@ -7,4 +9,6 @@ public class CartItemDto { private Long id; private Integer quantity; private String status; + @JsonIgnore + private Product product; } diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/CommonService.java b/src/main/java/com/manir/springbootecommercerestapi/service/CommonService.java index 08f4c32..1dfce02 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/service/CommonService.java +++ b/src/main/java/com/manir/springbootecommercerestapi/service/CommonService.java @@ -1,5 +1,7 @@ package com.manir.springbootecommercerestapi.service; +import com.manir.springbootecommercerestapi.dto.CartItemDto; +import com.manir.springbootecommercerestapi.response.CartItemResponse; import com.manir.springbootecommercerestapi.response.CommonResponse; import org.springframework.data.domain.Page; @@ -9,4 +11,7 @@ public interface CommonService<T> { //CommonResponse getAllCategoryOrProduct(int pageNo, int pageSize, String sortBy, String sortDir); CommonResponse getResponseContent(Page<T> page, List<T> dtoList); + + //cart iem response handler + CartItemResponse getResponse(CartItemDto cartItemDto); } diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/CommonServiceImpl.java b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/CommonServiceImpl.java index 35f6107..de3fec7 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/CommonServiceImpl.java +++ b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/CommonServiceImpl.java @@ -1,5 +1,7 @@ package com.manir.springbootecommercerestapi.service.Impl; +import com.manir.springbootecommercerestapi.dto.CartItemDto; +import com.manir.springbootecommercerestapi.response.CartItemResponse; import com.manir.springbootecommercerestapi.response.CommonResponse; import com.manir.springbootecommercerestapi.service.CommonService; import lombok.extern.slf4j.Slf4j; @@ -8,6 +10,7 @@ import org.springframework.data.domain.Page; import org.springframework.stereotype.Service; +import java.util.ArrayList; import java.util.List; @Service @@ -29,4 +32,17 @@ public CommonResponse getResponseContent(Page page, List dtoList) { return commonResponse; } + + @Override + public CartItemResponse getResponse(CartItemDto cartItemDto) { + + CartItemResponse cartItemResponse = new CartItemResponse(); + + double totalPrice = cartItemDto.getProduct().getPrice() * cartItemDto.getQuantity(); + List<CartItemDto> cartItemDtoList = new ArrayList<>(); + cartItemDtoList.add(cartItemDto); + cartItemResponse.setContent(cartItemDtoList); + cartItemResponse.setTotalCost(totalPrice); + return cartItemResponse; + } } diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/ShoppingCartServiceImpl.java b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/ShoppingCartServiceImpl.java index 165d37b..9dbe839 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/ShoppingCartServiceImpl.java +++ b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/ShoppingCartServiceImpl.java @@ -9,6 +9,8 @@ import com.manir.springbootecommercerestapi.repository.CartItemRepository; import com.manir.springbootecommercerestapi.repository.CustomerRepository; import com.manir.springbootecommercerestapi.repository.ProductRepository; +import com.manir.springbootecommercerestapi.response.CartItemResponse; +import com.manir.springbootecommercerestapi.service.CommonService; import com.manir.springbootecommercerestapi.service.ShoppingCartService; import lombok.extern.slf4j.Slf4j; import org.modelmapper.ModelMapper; @@ -17,12 +19,13 @@ import javax.annotation.Resource; import javax.transaction.Transactional; +import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; +import java.util.stream.DoubleStream; @Service @Slf4j - public class ShoppingCartServiceImpl implements ShoppingCartService { @Resource @@ -33,9 +36,10 @@ public class ShoppingCartServiceImpl implements ShoppingCartService { private ProductRepository productRepository; @Resource private CustomerRepository customerRepository; - + @Resource + private CommonService commonService; @Override - public List<CartItemDto> findByCustomerId(Long customerId) { + public CartItemResponse findByCustomerId(Long customerId) { List<CartItem> cartItems = cartItemRepository.findByCustomerId(customerId); @@ -46,21 +50,19 @@ public List<CartItemDto> findByCustomerId(Long customerId) { List<CartItemDto> cartItemDtoList = cartItems.stream() .map(cartItem -> mapToDto(cartItem)) .collect(Collectors.toList()); - - return cartItemDtoList; + DoubleStream totalPrice = cartItemDtoList.stream() + .mapToDouble(cartItemDto -> cartItemDto.getProduct().getPrice() * cartItemDto.getQuantity()); + CartItemResponse cartItemResponse = new CartItemResponse(); + cartItemResponse.setContent(cartItemDtoList); + cartItemResponse.setTotalCost(totalPrice.sum()); + return cartItemResponse; } @Override - public CartItemDto addCartItem(Long customerId, Long productId, Integer quantity) { + public CartItemResponse addCartItem(Long customerId, Long productId, Integer quantity) { Integer addedQuantity = quantity; - Customer customer = customerRepository.findById(customerId) - .orElseThrow( - () -> new ResourceNotFoundException("Customer", customerId) - ); - Product product = productRepository.findById(productId) - .orElseThrow( - () -> new ResourceNotFoundException("Product", productId) - ); + Customer customer = findCustomerById(customerId); + Product product = findProductById(productId); CartItem cartItem = cartItemRepository.findByCustomerIdAndProductId(customerId, productId); if(cartItem != null){ @@ -74,49 +76,36 @@ public CartItemDto addCartItem(Long customerId, Long productId, Integer quantity } CartItem addedCartItem = cartItemRepository.save(cartItem); + CartItemDto cartItemDto = mapToDto(addedCartItem); - return mapToDto(addedCartItem); + CartItemResponse cartItemResponse = commonService.getResponse(cartItemDto); + return cartItemResponse; } @Override - public CartItemDto updateItemQuantity(Long customerId, Long productId, Integer quantity) { - - Customer customer = customerRepository.findById(customerId) - .orElseThrow( - () -> new ResourceNotFoundException("Customer", customerId) - ); - Product product = productRepository.findById(productId) - .orElseThrow( - () -> new ResourceNotFoundException("Product", productId) - ); + public CartItemResponse updateItemQuantity(Long customerId, Long productId, Integer quantity) { CartItem cartItem = cartItemRepository.findByCustomerIdAndProductId(customerId, productId); - if (!cartItem.getCustomer().getId().equals(customer.getId()) || !cartItem.getProduct().getId().equals(product.getId())){ - throw new EcommerceApiException(" this cart item does not belong to Customer or Product ", HttpStatus.BAD_REQUEST); + if (cartItem == null){ + throw new EcommerceApiException("Product is not in the cart item", HttpStatus.BAD_REQUEST); } cartItem.setQuantity(quantity); CartItem updatedItemQuantity = cartItemRepository.save(cartItem); - return mapToDto(updatedItemQuantity); + CartItemDto cartItemDto = mapToDto(updatedItemQuantity); + + CartItemResponse cartItemResponse = commonService.getResponse(cartItemDto); + return cartItemResponse; } @Override @Transactional public void deleteItemProduct(Long customerId, Long productId) { - Customer customer = customerRepository.findById(customerId) - .orElseThrow( - () -> new ResourceNotFoundException("Customer", customerId) - ); - Product product = productRepository.findById(productId) - .orElseThrow( - () -> new ResourceNotFoundException("Product", productId) - ); + CartItem cartItem = cartItemRepository.findByCustomerIdAndProductId(customerId, productId); - if (cartItem != null){ - cartItemRepository.deleteByCustomerIdAndProductId(customerId, productId); - } - if (!cartItem.getCustomer().getId().equals(customer.getId()) || !cartItem.getProduct().getId().equals(product.getId())){ - throw new EcommerceApiException(" this cart item does not belong to Customer or Product ", HttpStatus.BAD_REQUEST); + if (cartItem == null){ + throw new EcommerceApiException("Product is not in the cart item", HttpStatus.BAD_REQUEST); } + cartItemRepository.deleteByCustomerIdAndProductId(customerId, productId); } //map to dto @@ -130,4 +119,20 @@ private CartItem mapToEntity(CartItemDto cartItemDto){ CartItem cartItem = modelMapper.map(cartItemDto, CartItem.class); return cartItem; } + + private Customer findCustomerById(Long customerId){ + Customer customer = customerRepository.findById(customerId) + .orElseThrow( + () -> new ResourceNotFoundException("Customer", customerId) + ); + return customer; + } + + private Product findProductById(Long productId){ + Product product = productRepository.findById(productId) + .orElseThrow( + () -> new ResourceNotFoundException("Product", productId) + ); + return product; + } } diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/ShoppingCartService.java b/src/main/java/com/manir/springbootecommercerestapi/service/ShoppingCartService.java index 8f6b5d9..7520bbf 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/service/ShoppingCartService.java +++ b/src/main/java/com/manir/springbootecommercerestapi/service/ShoppingCartService.java @@ -1,16 +1,14 @@ package com.manir.springbootecommercerestapi.service; -import com.manir.springbootecommercerestapi.dto.CartItemDto; - -import java.util.List; +import com.manir.springbootecommercerestapi.response.CartItemResponse; public interface ShoppingCartService { - List<CartItemDto> findByCustomerId(Long customerId); + CartItemResponse findByCustomerId(Long customerId); - CartItemDto addCartItem(Long customerId, Long productId, Integer quantity); + CartItemResponse addCartItem(Long customerId, Long productId, Integer quantity); - CartItemDto updateItemQuantity(Long customerId, Long productId, Integer quantity); + CartItemResponse updateItemQuantity(Long customerId, Long productId, Integer quantity); void deleteItemProduct(Long customerId, Long productId); } From ef48c9322fca4662d7e6c5fb67596a894c3c82b5 Mon Sep 17 00:00:00 2001 From: Mahamat Nour Mahamat Abdraman <42040735+manirDev@users.noreply.github.com> Date: Fri, 11 Nov 2022 17:11:51 +0300 Subject: [PATCH 02/16] Create README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..70a9e4a --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# Spring-boot-e-commerce-rest-api +Spring Boot E-commerce Rest Api From 0de93eeda6aa9ff9bed4593451feb08491a7c7b6 Mon Sep 17 00:00:00 2001 From: manirDev <mhtnourmhtmjr@gmail.com> Date: Mon, 14 Nov 2022 11:06:30 +0300 Subject: [PATCH 03/16] Spring Boot Security, In Memory auth and end Points security is done. --- pom.xml | 5 +- .../config/SecurityConfig.java | 54 +++++++++++++++++++ .../controller/CategoryController.java | 4 ++ .../controller/ProductController.java | 5 ++ .../service/Impl/ShoppingCartServiceImpl.java | 2 + src/main/resources/application.properties | 7 ++- 6 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/manir/springbootecommercerestapi/config/SecurityConfig.java diff --git a/pom.xml b/pom.xml index 7881907..1cd8705 100644 --- a/pom.xml +++ b/pom.xml @@ -48,7 +48,10 @@ <artifactId>modelmapper</artifactId> <version>3.1.0</version> </dependency> - + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-security</artifactId> + </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> diff --git a/src/main/java/com/manir/springbootecommercerestapi/config/SecurityConfig.java b/src/main/java/com/manir/springbootecommercerestapi/config/SecurityConfig.java new file mode 100644 index 0000000..08e6a9f --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/config/SecurityConfig.java @@ -0,0 +1,54 @@ +package com.manir.springbootecommercerestapi.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.provisioning.InMemoryUserDetailsManager; + +@Configuration +@EnableWebSecurity +/*** + global security is used for enable security at method level for example permitting get methods + Ex: PreAuthorize("hasRole('ADMIN')") + ***/ +@EnableGlobalMethodSecurity(prePostEnabled = true) +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .csrf().disable() + .authorizeRequests() + //to permit all get request and secure post put and delete methods + .antMatchers(HttpMethod.GET, "/api/**").permitAll() + .anyRequest() + .authenticated() + .and() + .httpBasic(); + + } + + //In memory Auth + @Override + @Bean + protected UserDetailsService userDetailsService() { + UserDetails user = User.builder().username("user").password(passwordEncoder().encode("user")).roles("USER").build(); + UserDetails admin = User.builder().username("admin").password(passwordEncoder().encode("admin")).roles("ADMIN").build(); + + return new InMemoryUserDetailsManager(user, admin); + } + + @Bean + PasswordEncoder passwordEncoder(){ + return new BCryptPasswordEncoder(); + } +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/controller/CategoryController.java b/src/main/java/com/manir/springbootecommercerestapi/controller/CategoryController.java index 1bcef5a..23544d0 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/controller/CategoryController.java +++ b/src/main/java/com/manir/springbootecommercerestapi/controller/CategoryController.java @@ -7,6 +7,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; @@ -18,6 +19,7 @@ public class CategoryController { private CategoryService categoryService; //create category api + @PreAuthorize("hasRole('ADMIN')") @PostMapping("/createCategory") public ResponseEntity<CategoryDto> createCategory(@RequestBody CategoryDto categoryDto){ CategoryDto responseCategory = categoryService.createCategory(categoryDto); @@ -42,6 +44,7 @@ public ResponseEntity<CategoryDto> getCatecoryById(@PathVariable Long categoryId } //update category api + @PreAuthorize("hasRole('ADMIN')") @PutMapping("/updateCategory/{categoryId}") public ResponseEntity<CategoryDto> updateCategory(@RequestBody CategoryDto categoryDto, @PathVariable Long categoryId){ @@ -50,6 +53,7 @@ public ResponseEntity<CategoryDto> updateCategory(@RequestBody CategoryDto categ } //delete category api + @PreAuthorize("hasRole('ADMIN')") @DeleteMapping("/deleteCategory/{categoryId}") public ResponseEntity<String> deleteCategory(@PathVariable Long categoryId){ categoryService.deleteCategory(categoryId); diff --git a/src/main/java/com/manir/springbootecommercerestapi/controller/ProductController.java b/src/main/java/com/manir/springbootecommercerestapi/controller/ProductController.java index d7b56b5..d5e2605 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/controller/ProductController.java +++ b/src/main/java/com/manir/springbootecommercerestapi/controller/ProductController.java @@ -9,6 +9,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -22,6 +23,7 @@ public class ProductController { private ProductService productService; //product create api + @PreAuthorize("hasRole('ADMIN')") @RequestMapping(value = "/createProduct", method = RequestMethod.POST, consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.MULTIPART_FORM_DATA_VALUE}) public ResponseEntity<ProductDto> createProduct(@RequestPart("productDto") ProductDto productDto, @RequestPart("file") MultipartFile file){ @@ -30,6 +32,7 @@ public ResponseEntity<ProductDto> createProduct(@RequestPart("productDto") Produ } //create product with category + @PreAuthorize("hasRole('ADMIN')") @PostMapping("/{categoryId}/saveProductByCategoryId") public ResponseEntity<ProductDto> saveProductByCategoryId(@PathVariable Long categoryId, @RequestBody ProductDto productDto){ @@ -57,6 +60,7 @@ public ResponseEntity<ProductDto> getProductById(@PathVariable Long productId){ } //update product api + @PreAuthorize("hasRole('ADMIN')") @PutMapping("/{categoryId}/updateProduct/{productId}") public ResponseEntity<ProductDto> updateProduct(@PathVariable Long categoryId, @RequestBody ProductDto productDto, @@ -66,6 +70,7 @@ public ResponseEntity<ProductDto> updateProduct(@PathVariable Long categoryId, } //delete product api + @PreAuthorize("hasRole('ADMIN')") @DeleteMapping("/deleteProduct/{productId}") public ResponseEntity<String> deleteProduct(@PathVariable Long productId){ productService.deleteProduct(productId); diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/ShoppingCartServiceImpl.java b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/ShoppingCartServiceImpl.java index 9dbe839..e695637 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/ShoppingCartServiceImpl.java +++ b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/ShoppingCartServiceImpl.java @@ -135,4 +135,6 @@ private Product findProductById(Long productId){ ); return product; } + + } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index f4d8fbb..87078d1 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -6,5 +6,10 @@ spring.datasource.username=root spring.datasource.url=jdbc:mysql://localhost:3306/springBootEcommerceRestApi?serverTimezone=UTC spring.jpa.hibernate.ddl-auto=update -#logging.level.org.springframework.security=DEBUG +#TO see security is working on the console +logging.level.org.springframework.security=DEBUG +#Spring security default auth credential +#spring.security.user.password= user +#spring.security.user.name= user +#spring.security.user.roles= ADMIN From 425ced43bf093264d3a1272fdb79f25694289f39 Mon Sep 17 00:00:00 2001 From: manirDev <mhtnourmhtmjr@gmail.com> Date: Mon, 14 Nov 2022 13:26:52 +0300 Subject: [PATCH 04/16] Spring Boot Security,DB Auth and Custom UserService. --- .../config/SecurityConfig.java | 28 +++++++++--- .../controller/ShoppingCartController.java | 6 +++ .../model/CartItem.java | 6 +-- .../model/Role.java | 17 ++++++++ .../model/{Customer.java => User.java} | 14 ++++-- .../repository/CartItemRepository.java | 2 +- .../repository/CustomerRepository.java | 8 ---- .../repository/RoleRepository.java | 10 +++++ .../repository/UserRepository.java | 16 +++++++ .../security/CustomUserDetailsService.java | 43 +++++++++++++++++++ .../service/Impl/ShoppingCartServiceImpl.java | 21 +++++---- .../utils/PasswordEncoderGenerator.java | 12 ++++++ .../utils/isAuthenticatedAsAdminOrUser.java | 11 +++++ src/main/resources/application.properties | 6 +-- 14 files changed, 163 insertions(+), 37 deletions(-) create mode 100644 src/main/java/com/manir/springbootecommercerestapi/model/Role.java rename src/main/java/com/manir/springbootecommercerestapi/model/{Customer.java => User.java} (56%) delete mode 100644 src/main/java/com/manir/springbootecommercerestapi/repository/CustomerRepository.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/repository/RoleRepository.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/repository/UserRepository.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/security/CustomUserDetailsService.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/utils/PasswordEncoderGenerator.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/utils/isAuthenticatedAsAdminOrUser.java diff --git a/src/main/java/com/manir/springbootecommercerestapi/config/SecurityConfig.java b/src/main/java/com/manir/springbootecommercerestapi/config/SecurityConfig.java index 08e6a9f..81e3fd8 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/config/SecurityConfig.java +++ b/src/main/java/com/manir/springbootecommercerestapi/config/SecurityConfig.java @@ -1,8 +1,11 @@ package com.manir.springbootecommercerestapi.config; +import com.manir.springbootecommercerestapi.security.CustomUserDetailsService; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; @@ -14,6 +17,8 @@ import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.provisioning.InMemoryUserDetailsManager; +import javax.annotation.Resource; + @Configuration @EnableWebSecurity /*** @@ -23,6 +28,9 @@ @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter { + @Autowired + private CustomUserDetailsService customUserDetailsService; + @Override protected void configure(HttpSecurity http) throws Exception { http @@ -38,13 +46,21 @@ protected void configure(HttpSecurity http) throws Exception { } //In memory Auth - @Override - @Bean - protected UserDetailsService userDetailsService() { - UserDetails user = User.builder().username("user").password(passwordEncoder().encode("user")).roles("USER").build(); - UserDetails admin = User.builder().username("admin").password(passwordEncoder().encode("admin")).roles("ADMIN").build(); + /** + @Override + @Bean + protected UserDetailsService userDetailsService() { + UserDetails user = User.builder().username("customer").password(passwordEncoder().encode("customer")).roles("USER").build(); + UserDetails admin = User.builder().username("admin").password(passwordEncoder().encode("admin")).roles("ADMIN").build(); + + return new InMemoryUserDetailsManager(user, admin); + } + **/ - return new InMemoryUserDetailsManager(user, admin); + //DB Auth + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder()); } @Bean diff --git a/src/main/java/com/manir/springbootecommercerestapi/controller/ShoppingCartController.java b/src/main/java/com/manir/springbootecommercerestapi/controller/ShoppingCartController.java index 1880715..4859845 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/controller/ShoppingCartController.java +++ b/src/main/java/com/manir/springbootecommercerestapi/controller/ShoppingCartController.java @@ -3,8 +3,10 @@ import com.manir.springbootecommercerestapi.dto.CartItemDto; import com.manir.springbootecommercerestapi.response.CartItemResponse; import com.manir.springbootecommercerestapi.service.ShoppingCartService; +import com.manir.springbootecommercerestapi.utils.isAuthenticatedAsAdminOrUser; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; @@ -18,6 +20,7 @@ public class ShoppingCartController { private ShoppingCartService shoppingCartService; //find by customer api + @isAuthenticatedAsAdminOrUser @GetMapping("/findByCustomer/{customerId}") public CartItemResponse findByCustomerId(@PathVariable Long customerId){ CartItemResponse responseCartItems = shoppingCartService.findByCustomerId(customerId); @@ -26,6 +29,7 @@ public CartItemResponse findByCustomerId(@PathVariable Long customerId){ } //add item to the cart api + @isAuthenticatedAsAdminOrUser @PostMapping("/addItem/{customerId}/{productId}/{quantity}") public ResponseEntity<CartItemResponse> addCartItem(@PathVariable Long customerId, @PathVariable Long productId, @@ -36,6 +40,7 @@ public ResponseEntity<CartItemResponse> addCartItem(@PathVariable Long customerI } //update item quantity api + @isAuthenticatedAsAdminOrUser @PutMapping("/updateItemQuantity/{customerId}/{productId}/{quantity}") public ResponseEntity<CartItemResponse> updateItemQuantity(@PathVariable Long customerId, @PathVariable Long productId, @@ -47,6 +52,7 @@ public ResponseEntity<CartItemResponse> updateItemQuantity(@PathVariable Long cu } //delete item product api + @isAuthenticatedAsAdminOrUser @DeleteMapping("/deleteItemProduct/{customerId}/{productId}") public ResponseEntity<String> deleteItemProduct(@PathVariable Long customerId, @PathVariable Long productId){ shoppingCartService.deleteItemProduct(customerId, productId); diff --git a/src/main/java/com/manir/springbootecommercerestapi/model/CartItem.java b/src/main/java/com/manir/springbootecommercerestapi/model/CartItem.java index 0dfa585..70155da 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/model/CartItem.java +++ b/src/main/java/com/manir/springbootecommercerestapi/model/CartItem.java @@ -1,12 +1,10 @@ package com.manir.springbootecommercerestapi.model; -import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import javax.persistence.*; -import java.util.Set; @AllArgsConstructor @NoArgsConstructor @@ -27,9 +25,9 @@ public class CartItem { @JoinColumn(name = "product_id") private Product product; - //relation with user + //relation with customer @ManyToOne() @JoinColumn(name = "customer_id") - private Customer customer; + private User customer; } diff --git a/src/main/java/com/manir/springbootecommercerestapi/model/Role.java b/src/main/java/com/manir/springbootecommercerestapi/model/Role.java new file mode 100644 index 0000000..3ad1a0e --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/model/Role.java @@ -0,0 +1,17 @@ +package com.manir.springbootecommercerestapi.model; + +import lombok.Data; + +import javax.persistence.*; + +@Data +@Entity +@Table(name = "roles") +public class Role { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + @Column(length = 60) + private String name; +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/model/Customer.java b/src/main/java/com/manir/springbootecommercerestapi/model/User.java similarity index 56% rename from src/main/java/com/manir/springbootecommercerestapi/model/Customer.java rename to src/main/java/com/manir/springbootecommercerestapi/model/User.java index b2d3d99..5f92a22 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/model/Customer.java +++ b/src/main/java/com/manir/springbootecommercerestapi/model/User.java @@ -1,6 +1,5 @@ package com.manir.springbootecommercerestapi.model; -import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.Data; import javax.persistence.*; @@ -8,10 +7,10 @@ @Data @Entity -@Table(name = "customers", uniqueConstraints = {@UniqueConstraint(columnNames = {"userName"}), +@Table(name = "users", uniqueConstraints = {@UniqueConstraint(columnNames = {"userName"}), @UniqueConstraint(columnNames = {"email"}) }) -public class Customer { +public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @@ -25,4 +24,11 @@ public class Customer { fetch = FetchType.LAZY, orphanRemoval = true, mappedBy = "customer") private Set<CartItem> cartItems; -} + + //relation with role + @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL) + @JoinTable(name = "user_roles", + joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), + inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id")) + private Set<Role> roles; + } diff --git a/src/main/java/com/manir/springbootecommercerestapi/repository/CartItemRepository.java b/src/main/java/com/manir/springbootecommercerestapi/repository/CartItemRepository.java index 4d4482b..d315263 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/repository/CartItemRepository.java +++ b/src/main/java/com/manir/springbootecommercerestapi/repository/CartItemRepository.java @@ -11,7 +11,7 @@ public interface CartItemRepository extends JpaRepository<CartItem, Long> { List<CartItem> findByCustomerId(Long customerId); - //CartItem findByCustomerAndProduct(Customer customer, Product product); + //CartItem findByCustomerAndProduct(User customer, Product product); CartItem findByCustomerIdAndProductId(Long customerId, Long productId); @Query("UPDATE CartItem c SET c.quantity = ?3 WHERE c.product.id = ?2 AND c.customer.id = ?1") diff --git a/src/main/java/com/manir/springbootecommercerestapi/repository/CustomerRepository.java b/src/main/java/com/manir/springbootecommercerestapi/repository/CustomerRepository.java deleted file mode 100644 index ae617c2..0000000 --- a/src/main/java/com/manir/springbootecommercerestapi/repository/CustomerRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.manir.springbootecommercerestapi.repository; - -import com.manir.springbootecommercerestapi.model.Customer; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface CustomerRepository extends JpaRepository<Customer, Long>{ - -} diff --git a/src/main/java/com/manir/springbootecommercerestapi/repository/RoleRepository.java b/src/main/java/com/manir/springbootecommercerestapi/repository/RoleRepository.java new file mode 100644 index 0000000..1681e21 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/repository/RoleRepository.java @@ -0,0 +1,10 @@ +package com.manir.springbootecommercerestapi.repository; + +import com.manir.springbootecommercerestapi.model.Role; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface RoleRepository extends JpaRepository<Role, Long> { + Optional<Role> findByName(String name); +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/repository/UserRepository.java b/src/main/java/com/manir/springbootecommercerestapi/repository/UserRepository.java new file mode 100644 index 0000000..9b9bc19 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/repository/UserRepository.java @@ -0,0 +1,16 @@ +package com.manir.springbootecommercerestapi.repository; + +import com.manir.springbootecommercerestapi.model.User; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface UserRepository extends JpaRepository<User, Long>{ + + Optional<User> findByEmail(String email); + Optional<User> findByUserNameOrEmail(String username, String email); + Optional<User> findByUserName(String username); + Boolean existsByUserName(String username); + Boolean existsByEmail(String email); + +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/security/CustomUserDetailsService.java b/src/main/java/com/manir/springbootecommercerestapi/security/CustomUserDetailsService.java new file mode 100644 index 0000000..a21131b --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/security/CustomUserDetailsService.java @@ -0,0 +1,43 @@ +package com.manir.springbootecommercerestapi.security; + +import com.manir.springbootecommercerestapi.model.Role; +import com.manir.springbootecommercerestapi.model.User; +import com.manir.springbootecommercerestapi.repository.UserRepository; +import lombok.AllArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.Collection; +import java.util.Set; +import java.util.stream.Collectors; + +@Service +@AllArgsConstructor +public class CustomUserDetailsService implements UserDetailsService { + private final UserRepository userRepository; + + @Override + public UserDetails loadUserByUsername(String userNameOrEmail) throws UsernameNotFoundException { + User user = userRepository.findByUserNameOrEmail(userNameOrEmail, userNameOrEmail) + .orElseThrow( + () -> new UsernameNotFoundException("User not found with username or email: " + userNameOrEmail) + ); + return new org.springframework.security.core.userdetails.User( + user.getEmail(), + user.getPassword(), + mapRolesToAuthorities(user.getRoles()) + ); + } + + private Collection<? extends GrantedAuthority> mapRolesToAuthorities(Set<Role> roles){ + return roles.stream() + .map(role -> new SimpleGrantedAuthority(role.getName())) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/ShoppingCartServiceImpl.java b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/ShoppingCartServiceImpl.java index e695637..a35796b 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/ShoppingCartServiceImpl.java +++ b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/ShoppingCartServiceImpl.java @@ -4,10 +4,10 @@ import com.manir.springbootecommercerestapi.exception.EcommerceApiException; import com.manir.springbootecommercerestapi.exception.ResourceNotFoundException; import com.manir.springbootecommercerestapi.model.CartItem; -import com.manir.springbootecommercerestapi.model.Customer; +import com.manir.springbootecommercerestapi.model.User; import com.manir.springbootecommercerestapi.model.Product; import com.manir.springbootecommercerestapi.repository.CartItemRepository; -import com.manir.springbootecommercerestapi.repository.CustomerRepository; +import com.manir.springbootecommercerestapi.repository.UserRepository; import com.manir.springbootecommercerestapi.repository.ProductRepository; import com.manir.springbootecommercerestapi.response.CartItemResponse; import com.manir.springbootecommercerestapi.service.CommonService; @@ -19,7 +19,6 @@ import javax.annotation.Resource; import javax.transaction.Transactional; -import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; import java.util.stream.DoubleStream; @@ -35,7 +34,7 @@ public class ShoppingCartServiceImpl implements ShoppingCartService { @Resource private ProductRepository productRepository; @Resource - private CustomerRepository customerRepository; + private UserRepository userRepository; @Resource private CommonService commonService; @Override @@ -44,7 +43,7 @@ public CartItemResponse findByCustomerId(Long customerId) { List<CartItem> cartItems = cartItemRepository.findByCustomerId(customerId); if (cartItems.size() == 0){ - throw new EcommerceApiException("Customer has no product in cart item", HttpStatus.BAD_REQUEST); + throw new EcommerceApiException("User has no product in cart item", HttpStatus.BAD_REQUEST); } List<CartItemDto> cartItemDtoList = cartItems.stream() @@ -61,7 +60,7 @@ public CartItemResponse findByCustomerId(Long customerId) { @Override public CartItemResponse addCartItem(Long customerId, Long productId, Integer quantity) { Integer addedQuantity = quantity; - Customer customer = findCustomerById(customerId); + User user = findCustomerById(customerId); Product product = findProductById(productId); CartItem cartItem = cartItemRepository.findByCustomerIdAndProductId(customerId, productId); @@ -70,7 +69,7 @@ public CartItemResponse addCartItem(Long customerId, Long productId, Integer qua cartItem.setQuantity(addedQuantity); }else { cartItem = new CartItem(); - cartItem.setCustomer(customer); + cartItem.setCustomer(user); cartItem.setProduct(product); cartItem.setQuantity(quantity); } @@ -120,12 +119,12 @@ private CartItem mapToEntity(CartItemDto cartItemDto){ return cartItem; } - private Customer findCustomerById(Long customerId){ - Customer customer = customerRepository.findById(customerId) + private User findCustomerById(Long customerId){ + User user = userRepository.findById(customerId) .orElseThrow( - () -> new ResourceNotFoundException("Customer", customerId) + () -> new ResourceNotFoundException("User", customerId) ); - return customer; + return user; } private Product findProductById(Long productId){ diff --git a/src/main/java/com/manir/springbootecommercerestapi/utils/PasswordEncoderGenerator.java b/src/main/java/com/manir/springbootecommercerestapi/utils/PasswordEncoderGenerator.java new file mode 100644 index 0000000..e466684 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/utils/PasswordEncoderGenerator.java @@ -0,0 +1,12 @@ +package com.manir.springbootecommercerestapi.utils; + +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +public class PasswordEncoderGenerator { + public static void main(String[] args) { + PasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + System.out.println("ADMIN: " + passwordEncoder.encode("admin")); + System.out.println("USER: " + passwordEncoder.encode("user")); + } +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/utils/isAuthenticatedAsAdminOrUser.java b/src/main/java/com/manir/springbootecommercerestapi/utils/isAuthenticatedAsAdminOrUser.java new file mode 100644 index 0000000..83c6333 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/utils/isAuthenticatedAsAdminOrUser.java @@ -0,0 +1,11 @@ +package com.manir.springbootecommercerestapi.utils; + +import org.springframework.security.access.prepost.PreAuthorize; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +@PreAuthorize("hasRole('ADMIN') || hasRole('USER')") +public @interface isAuthenticatedAsAdminOrUser { +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 87078d1..8c3a84b 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -9,7 +9,7 @@ spring.jpa.hibernate.ddl-auto=update #TO see security is working on the console logging.level.org.springframework.security=DEBUG #Spring security default auth credential -#spring.security.user.password= user -#spring.security.user.name= user -#spring.security.user.roles= ADMIN +#spring.security.customer.password= customer +#spring.security.customer.name= customer +#spring.security.customer.roles= ADMIN From e9d33c26dbe99df04258ec5c906657d73bacafc5 Mon Sep 17 00:00:00 2001 From: manirDev <mhtnourmhtmjr@gmail.com> Date: Mon, 14 Nov 2022 14:57:52 +0300 Subject: [PATCH 05/16] Sign-In and Sign-Up is successfully done. --- .../config/SecurityConfig.java | 10 +++ .../controller/AuthController.java | 61 +++++++++++++++++++ .../dto/LoginDto.java | 9 +++ .../dto/SignUpDto.java | 11 ++++ .../service/Impl/UserRegisterServiceImpl.java | 57 +++++++++++++++++ .../service/UserRegisterService.java | 7 +++ 6 files changed, 155 insertions(+) create mode 100644 src/main/java/com/manir/springbootecommercerestapi/controller/AuthController.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/dto/LoginDto.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/dto/SignUpDto.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/service/Impl/UserRegisterServiceImpl.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/service/UserRegisterService.java diff --git a/src/main/java/com/manir/springbootecommercerestapi/config/SecurityConfig.java b/src/main/java/com/manir/springbootecommercerestapi/config/SecurityConfig.java index 81e3fd8..baf3107 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/config/SecurityConfig.java +++ b/src/main/java/com/manir/springbootecommercerestapi/config/SecurityConfig.java @@ -5,6 +5,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; +import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; @@ -38,6 +39,8 @@ protected void configure(HttpSecurity http) throws Exception { .authorizeRequests() //to permit all get request and secure post put and delete methods .antMatchers(HttpMethod.GET, "/api/**").permitAll() + //authorize singIn and signUp + .antMatchers("/api/v1/auth/**").permitAll() .anyRequest() .authenticated() .and() @@ -67,4 +70,11 @@ protected void configure(AuthenticationManagerBuilder auth) throws Exception { PasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder(); } + + //User authentication manager bean + @Override + @Bean + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } } diff --git a/src/main/java/com/manir/springbootecommercerestapi/controller/AuthController.java b/src/main/java/com/manir/springbootecommercerestapi/controller/AuthController.java new file mode 100644 index 0000000..82257aa --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/controller/AuthController.java @@ -0,0 +1,61 @@ +package com.manir.springbootecommercerestapi.controller; + +import com.manir.springbootecommercerestapi.dto.LoginDto; +import com.manir.springbootecommercerestapi.dto.SignUpDto; +import com.manir.springbootecommercerestapi.repository.UserRepository; +import com.manir.springbootecommercerestapi.service.UserRegisterService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +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; + + + +@RestController +@RequestMapping(value = "api/v1/auth") +public class AuthController { + + @Autowired + private AuthenticationManager authenticationManager; + @Autowired + private UserRepository userRepository; + @Autowired + private UserRegisterService userRegisterService; + + //login api + @PostMapping("/login") + public ResponseEntity<String> authenticateUser(@RequestBody LoginDto loginDto){ + + Authentication authentication = authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken( + loginDto.getUserNameOrEmail(), + loginDto.getPassword() + ) + ); + SecurityContextHolder.getContext().setAuthentication(authentication); + return new ResponseEntity<>("User sign-In successfully", HttpStatus.OK); + } + + //register api + @PostMapping("/register") + public ResponseEntity<?> registerUser(@RequestBody SignUpDto signUpDto){ + + //check for username exists in DB + if (userRepository.existsByUserName(signUpDto.getUsername())){ + return new ResponseEntity<>("Username already exists", HttpStatus.BAD_REQUEST); + } + if (userRepository.existsByEmail(signUpDto.getEmail())){ + return new ResponseEntity<>("Email already exists", HttpStatus.BAD_REQUEST); + } + SignUpDto registeredUser = userRegisterService.registerUser(signUpDto); + return new ResponseEntity<>("User is successfully registered", HttpStatus.OK); + } + +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/dto/LoginDto.java b/src/main/java/com/manir/springbootecommercerestapi/dto/LoginDto.java new file mode 100644 index 0000000..1c3c8a1 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/dto/LoginDto.java @@ -0,0 +1,9 @@ +package com.manir.springbootecommercerestapi.dto; + +import lombok.Data; + +@Data +public class LoginDto { + private String userNameOrEmail; + private String password; +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/dto/SignUpDto.java b/src/main/java/com/manir/springbootecommercerestapi/dto/SignUpDto.java new file mode 100644 index 0000000..a2e2eaa --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/dto/SignUpDto.java @@ -0,0 +1,11 @@ +package com.manir.springbootecommercerestapi.dto; + +import lombok.Data; + +@Data +public class SignUpDto { + private String name; + private String username; + private String email; + private String password; +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/UserRegisterServiceImpl.java b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/UserRegisterServiceImpl.java new file mode 100644 index 0000000..7458041 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/UserRegisterServiceImpl.java @@ -0,0 +1,57 @@ +package com.manir.springbootecommercerestapi.service.Impl; + +import com.manir.springbootecommercerestapi.dto.SignUpDto; +import com.manir.springbootecommercerestapi.model.Role; +import com.manir.springbootecommercerestapi.model.User; +import com.manir.springbootecommercerestapi.repository.RoleRepository; +import com.manir.springbootecommercerestapi.repository.UserRepository; +import com.manir.springbootecommercerestapi.service.UserRegisterService; +import org.modelmapper.ModelMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; + +import java.util.Collections; + +@Service +public class UserRegisterServiceImpl implements UserRegisterService { + + @Autowired + private UserRepository userRepository; + @Autowired + private RoleRepository roleRepository; + @Autowired + private PasswordEncoder passwordEncoder; + @Autowired + private ModelMapper modelMapper; + + @Override + public SignUpDto registerUser(SignUpDto signUpDto) { + + //convert dto to entity + User user = mapToEntity(signUpDto); + //save user to db + User registeredUser = userRepository.save(user); + return mapToDto(registeredUser); + } + + //map to dto + private SignUpDto mapToDto(User user){ + SignUpDto signUpDto = modelMapper.map(user, SignUpDto.class); + return signUpDto; + } + + //map to entity + private User mapToEntity(SignUpDto signUpDto){ + User user = new User(); + user.setName(signUpDto.getName()); + user.setUserName(signUpDto.getUsername()); + user.setEmail(signUpDto.getEmail()); + user.setPassword(passwordEncoder.encode(signUpDto.getPassword())); + + //add role to the user + Role role = roleRepository.findByName("ROLE_USER").get(); + user.setRoles(Collections.singleton(role)); + return user; + } +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/UserRegisterService.java b/src/main/java/com/manir/springbootecommercerestapi/service/UserRegisterService.java new file mode 100644 index 0000000..9096440 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/service/UserRegisterService.java @@ -0,0 +1,7 @@ +package com.manir.springbootecommercerestapi.service; + +import com.manir.springbootecommercerestapi.dto.SignUpDto; + +public interface UserRegisterService { + SignUpDto registerUser(SignUpDto signUpDto); +} From 67233d517945423ade8c0a31ed3aab6e0e70aa46 Mon Sep 17 00:00:00 2001 From: manirDev <mhtnourmhtmjr@gmail.com> Date: Tue, 15 Nov 2022 11:20:33 +0300 Subject: [PATCH 06/16] ShoppingCart changed with customer authentication --- .../controller/AuthController.java | 2 +- .../controller/ShoppingCartController.java | 82 ++++++++++++++----- .../dto/OrderDto.java | 15 ++++ .../model/Order.java | 37 +++++++++ .../model/OrderProducts.java | 38 +++++++++ .../model/Product.java | 6 ++ .../model/User.java | 12 +++ .../repository/CartItemRepository.java | 8 +- .../security/CustomUserDetails.java | 53 ++++++++++++ .../service/Impl/ShoppingCartServiceImpl.java | 25 +++--- .../service/ShoppingCartService.java | 9 +- 11 files changed, 244 insertions(+), 43 deletions(-) create mode 100644 src/main/java/com/manir/springbootecommercerestapi/dto/OrderDto.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/model/Order.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/model/OrderProducts.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/security/CustomUserDetails.java diff --git a/src/main/java/com/manir/springbootecommercerestapi/controller/AuthController.java b/src/main/java/com/manir/springbootecommercerestapi/controller/AuthController.java index 82257aa..2bf09f2 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/controller/AuthController.java +++ b/src/main/java/com/manir/springbootecommercerestapi/controller/AuthController.java @@ -54,7 +54,7 @@ public ResponseEntity<?> registerUser(@RequestBody SignUpDto signUpDto){ if (userRepository.existsByEmail(signUpDto.getEmail())){ return new ResponseEntity<>("Email already exists", HttpStatus.BAD_REQUEST); } - SignUpDto registeredUser = userRegisterService.registerUser(signUpDto); + userRegisterService.registerUser(signUpDto); return new ResponseEntity<>("User is successfully registered", HttpStatus.OK); } diff --git a/src/main/java/com/manir/springbootecommercerestapi/controller/ShoppingCartController.java b/src/main/java/com/manir/springbootecommercerestapi/controller/ShoppingCartController.java index 4859845..593ffe0 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/controller/ShoppingCartController.java +++ b/src/main/java/com/manir/springbootecommercerestapi/controller/ShoppingCartController.java @@ -1,16 +1,22 @@ package com.manir.springbootecommercerestapi.controller; -import com.manir.springbootecommercerestapi.dto.CartItemDto; +import com.manir.springbootecommercerestapi.exception.EcommerceApiException; +import com.manir.springbootecommercerestapi.model.User; +import com.manir.springbootecommercerestapi.repository.UserRepository; import com.manir.springbootecommercerestapi.response.CartItemResponse; import com.manir.springbootecommercerestapi.service.ShoppingCartService; import com.manir.springbootecommercerestapi.utils.isAuthenticatedAsAdminOrUser; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.authentication.AnonymousAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; -import java.util.List; @RestController @RequestMapping("api/v1/cart") @@ -19,43 +25,75 @@ public class ShoppingCartController { @Resource private ShoppingCartService shoppingCartService; + @Autowired + private UserRepository userRepository; + + //find by customer api @isAuthenticatedAsAdminOrUser - @GetMapping("/findByCustomer/{customerId}") - public CartItemResponse findByCustomerId(@PathVariable Long customerId){ - CartItemResponse responseCartItems = shoppingCartService.findByCustomerId(customerId); + @GetMapping("/findByCustomer") + public CartItemResponse findByCustomerId(@AuthenticationPrincipal Authentication authentication){ + authentication = SecurityContextHolder.getContext().getAuthentication(); + if (!(authentication instanceof AnonymousAuthenticationToken)) { + String currentUserEmail = authentication.getName(); + //System.out.println("Name:" + currentUserEmail); + User customer = userRepository.findByEmail(currentUserEmail).orElseThrow(()-> new UsernameNotFoundException("Customer not found")); + CartItemResponse responseCartItems = shoppingCartService.findByCustomer(customer); + return responseCartItems; + + }else{ + throw new EcommerceApiException("User not authenticated", HttpStatus.BAD_REQUEST); + } - return responseCartItems; } //add item to the cart api @isAuthenticatedAsAdminOrUser - @PostMapping("/addItem/{customerId}/{productId}/{quantity}") - public ResponseEntity<CartItemResponse> addCartItem(@PathVariable Long customerId, + @PostMapping("/addItem/{productId}/{quantity}") + public ResponseEntity<CartItemResponse> addCartItem(@AuthenticationPrincipal Authentication authentication, @PathVariable Long productId, @PathVariable Integer quantity){ - CartItemResponse responseCartItem = shoppingCartService.addCartItem(customerId, productId, quantity); - - return new ResponseEntity<>(responseCartItem, HttpStatus.CREATED); + authentication = SecurityContextHolder.getContext().getAuthentication(); + if (!(authentication instanceof AnonymousAuthenticationToken)){ + String currentUserEmail = authentication.getName(); + User customer = userRepository.findByEmail(currentUserEmail).orElseThrow(() -> new UsernameNotFoundException("Customer not found")); + CartItemResponse responseCartItem = shoppingCartService.addCartItem(customer, productId, quantity); + return new ResponseEntity<>(responseCartItem, HttpStatus.CREATED); + }else { + throw new EcommerceApiException("User not authenticated", HttpStatus.BAD_REQUEST); + } } //update item quantity api @isAuthenticatedAsAdminOrUser - @PutMapping("/updateItemQuantity/{customerId}/{productId}/{quantity}") - public ResponseEntity<CartItemResponse> updateItemQuantity(@PathVariable Long customerId, + @PutMapping("/updateItemQuantity/{productId}/{quantity}") + public ResponseEntity<CartItemResponse> updateItemQuantity(@AuthenticationPrincipal Authentication authentication, @PathVariable Long productId, @PathVariable Integer quantity){ - - CartItemResponse responseCartItem = shoppingCartService.updateItemQuantity(customerId, productId, quantity); - - return new ResponseEntity<>(responseCartItem, HttpStatus.OK); + authentication = SecurityContextHolder.getContext().getAuthentication(); + if (!(authentication instanceof AnonymousAuthenticationToken)){ + String currentUserEmail = authentication.getName(); + User customer = userRepository.findByEmail(currentUserEmail).orElseThrow(() -> new UsernameNotFoundException("Customer Not found")); + CartItemResponse responseCartItem = shoppingCartService.updateItemQuantity(customer, productId, quantity); + return new ResponseEntity<>(responseCartItem, HttpStatus.OK); + }else{ + throw new EcommerceApiException("User not authenticated", HttpStatus.BAD_REQUEST); + } } //delete item product api @isAuthenticatedAsAdminOrUser - @DeleteMapping("/deleteItemProduct/{customerId}/{productId}") - public ResponseEntity<String> deleteItemProduct(@PathVariable Long customerId, @PathVariable Long productId){ - shoppingCartService.deleteItemProduct(customerId, productId); - return ResponseEntity.ok("Product with id = " + productId +" is deleted successfully from your shopping cart"); + @DeleteMapping("/deleteItemProduct/{productId}") + public ResponseEntity<String> deleteItemProduct(@AuthenticationPrincipal Authentication authentication, + @PathVariable Long productId){ + authentication = SecurityContextHolder.getContext().getAuthentication(); + if (!(authentication instanceof AnonymousAuthenticationToken)){ + String currentUserEmail = authentication.getName(); + User customer = userRepository.findByEmail(currentUserEmail).orElseThrow(() -> new UsernameNotFoundException("Customer Not found")); + shoppingCartService.deleteItemProduct(customer, productId); + return ResponseEntity.ok("Product with id = " + productId +" is deleted successfully from your shopping cart"); + }else{ + throw new EcommerceApiException("User not authenticated", HttpStatus.BAD_REQUEST); + } } } diff --git a/src/main/java/com/manir/springbootecommercerestapi/dto/OrderDto.java b/src/main/java/com/manir/springbootecommercerestapi/dto/OrderDto.java new file mode 100644 index 0000000..7f2cee5 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/dto/OrderDto.java @@ -0,0 +1,15 @@ +package com.manir.springbootecommercerestapi.dto; + +import lombok.Data; + +@Data +public class OrderDto { + private Long id; + private String name; + private String email; + private String phone; + private String address; + private double totalPrice; + private String note; + private String status; +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/model/Order.java b/src/main/java/com/manir/springbootecommercerestapi/model/Order.java new file mode 100644 index 0000000..56054d5 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/model/Order.java @@ -0,0 +1,37 @@ +package com.manir.springbootecommercerestapi.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.*; +import java.util.Set; + +@AllArgsConstructor +@NoArgsConstructor +@Data +@Entity +@Table(name = "orders") +public class Order { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + private String name; + private String email; + private String phone; + private String address; + private double totalPrice; + private String note; + private String status; + + //relation with user + @ManyToOne() + @JoinColumn(name = "customer_id") + private User customer; + + //relation with order_products + @OneToMany(cascade = CascadeType.ALL, + fetch = FetchType.LAZY, orphanRemoval = true, + mappedBy = "order") + private Set<OrderProducts> orderProducts; +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/model/OrderProducts.java b/src/main/java/com/manir/springbootecommercerestapi/model/OrderProducts.java new file mode 100644 index 0000000..b9362c5 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/model/OrderProducts.java @@ -0,0 +1,38 @@ +package com.manir.springbootecommercerestapi.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.*; + +@AllArgsConstructor +@NoArgsConstructor +@Data +@Entity +@Table(name = "order_products") +public class OrderProducts { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + private double productPrice; + private Integer productQuantity; + private double totalPrice; + private String note; + private String status; + + //relation with user + @ManyToOne() + @JoinColumn(name = "customer_id") + private User customer; + + //relation with product + @ManyToOne() + @JoinColumn(name = "product_id") + private Product product; + + //relation with order + @ManyToOne() + @JoinColumn(name = "order_id") + private Order order; +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/model/Product.java b/src/main/java/com/manir/springbootecommercerestapi/model/Product.java index 77bc06e..78c7f3b 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/model/Product.java +++ b/src/main/java/com/manir/springbootecommercerestapi/model/Product.java @@ -54,4 +54,10 @@ public class Product { //relation to cart item @OneToMany(mappedBy = "product", cascade = CascadeType.ALL, orphanRemoval = true) private Set<CartItem> cartItems; + + //relation with order_products + @OneToMany(cascade = CascadeType.ALL, + fetch = FetchType.LAZY, orphanRemoval = true, + mappedBy = "product") + private Set<OrderProducts> orderProducts; } diff --git a/src/main/java/com/manir/springbootecommercerestapi/model/User.java b/src/main/java/com/manir/springbootecommercerestapi/model/User.java index 5f92a22..7489091 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/model/User.java +++ b/src/main/java/com/manir/springbootecommercerestapi/model/User.java @@ -31,4 +31,16 @@ public class User { joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id")) private Set<Role> roles; + + //relation with order + @OneToMany(cascade = CascadeType.ALL, + fetch = FetchType.LAZY, orphanRemoval = true, + mappedBy = "customer") + private Set<Order> orders; + + //relation with order_product + @OneToMany(cascade = CascadeType.ALL, + fetch = FetchType.LAZY, orphanRemoval = true, + mappedBy = "customer") + private Set<OrderProducts> orderProducts; } diff --git a/src/main/java/com/manir/springbootecommercerestapi/repository/CartItemRepository.java b/src/main/java/com/manir/springbootecommercerestapi/repository/CartItemRepository.java index d315263..0f1c119 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/repository/CartItemRepository.java +++ b/src/main/java/com/manir/springbootecommercerestapi/repository/CartItemRepository.java @@ -1,6 +1,8 @@ package com.manir.springbootecommercerestapi.repository; import com.manir.springbootecommercerestapi.model.CartItem; +import com.manir.springbootecommercerestapi.model.Product; +import com.manir.springbootecommercerestapi.model.User; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; @@ -9,16 +11,16 @@ public interface CartItemRepository extends JpaRepository<CartItem, Long> { - List<CartItem> findByCustomerId(Long customerId); + List<CartItem> findByCustomer(User customer); //CartItem findByCustomerAndProduct(User customer, Product product); - CartItem findByCustomerIdAndProductId(Long customerId, Long productId); + CartItem findByCustomerAndProduct(User customer, Product product); @Query("UPDATE CartItem c SET c.quantity = ?3 WHERE c.product.id = ?2 AND c.customer.id = ?1") void updateItemQuantity(Long customerId, Long productId, Integer quantity); @Query("DELETE FROM CartItem c WHERE c.customer.id = ?1 AND c.product.id = ?2") @Modifying - void deleteByCustomerIdAndProductId(Long customerId, Long productId); + void deleteByCustomerAndProduct(Long customerId, Long productId); } diff --git a/src/main/java/com/manir/springbootecommercerestapi/security/CustomUserDetails.java b/src/main/java/com/manir/springbootecommercerestapi/security/CustomUserDetails.java new file mode 100644 index 0000000..0fe8a10 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/security/CustomUserDetails.java @@ -0,0 +1,53 @@ +package com.manir.springbootecommercerestapi.security; + +import com.manir.springbootecommercerestapi.model.User; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.Collection; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class CustomUserDetails implements UserDetails { + private User user; + @Override + public Collection<? extends GrantedAuthority> getAuthorities() { + return null; + } + + @Override + public String getPassword() { + return null; + } + + @Override + public String getUsername() { + return user.getEmail(); + } + + @Override + public boolean isAccountNonExpired() { + return false; + } + + @Override + public boolean isAccountNonLocked() { + return false; + } + + @Override + public boolean isCredentialsNonExpired() { + return false; + } + + @Override + public boolean isEnabled() { + return false; + } + + +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/ShoppingCartServiceImpl.java b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/ShoppingCartServiceImpl.java index a35796b..cc98060 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/ShoppingCartServiceImpl.java +++ b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/ShoppingCartServiceImpl.java @@ -38,9 +38,9 @@ public class ShoppingCartServiceImpl implements ShoppingCartService { @Resource private CommonService commonService; @Override - public CartItemResponse findByCustomerId(Long customerId) { + public CartItemResponse findByCustomer(User customer) { - List<CartItem> cartItems = cartItemRepository.findByCustomerId(customerId); + List<CartItem> cartItems = cartItemRepository.findByCustomer(customer); if (cartItems.size() == 0){ throw new EcommerceApiException("User has no product in cart item", HttpStatus.BAD_REQUEST); @@ -58,18 +58,17 @@ public CartItemResponse findByCustomerId(Long customerId) { } @Override - public CartItemResponse addCartItem(Long customerId, Long productId, Integer quantity) { + public CartItemResponse addCartItem(User customer, Long productId, Integer quantity) { Integer addedQuantity = quantity; - User user = findCustomerById(customerId); Product product = findProductById(productId); - CartItem cartItem = cartItemRepository.findByCustomerIdAndProductId(customerId, productId); + CartItem cartItem = cartItemRepository.findByCustomerAndProduct(customer, product); if(cartItem != null){ addedQuantity = cartItem.getQuantity() + quantity; cartItem.setQuantity(addedQuantity); }else { cartItem = new CartItem(); - cartItem.setCustomer(user); + cartItem.setCustomer(customer); cartItem.setProduct(product); cartItem.setQuantity(quantity); } @@ -82,9 +81,9 @@ public CartItemResponse addCartItem(Long customerId, Long productId, Integer qua } @Override - public CartItemResponse updateItemQuantity(Long customerId, Long productId, Integer quantity) { - - CartItem cartItem = cartItemRepository.findByCustomerIdAndProductId(customerId, productId); + public CartItemResponse updateItemQuantity(User customer, Long productId, Integer quantity) { + Product product = findProductById(productId); + CartItem cartItem = cartItemRepository.findByCustomerAndProduct(customer, product); if (cartItem == null){ throw new EcommerceApiException("Product is not in the cart item", HttpStatus.BAD_REQUEST); } @@ -98,13 +97,13 @@ public CartItemResponse updateItemQuantity(Long customerId, Long productId, Inte @Override @Transactional - public void deleteItemProduct(Long customerId, Long productId) { - - CartItem cartItem = cartItemRepository.findByCustomerIdAndProductId(customerId, productId); + public void deleteItemProduct(User customer, Long productId) { + Product product = findProductById(productId); + CartItem cartItem = cartItemRepository.findByCustomerAndProduct(customer, product); if (cartItem == null){ throw new EcommerceApiException("Product is not in the cart item", HttpStatus.BAD_REQUEST); } - cartItemRepository.deleteByCustomerIdAndProductId(customerId, productId); + cartItemRepository.deleteByCustomerAndProduct(customer.getId(), productId); } //map to dto diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/ShoppingCartService.java b/src/main/java/com/manir/springbootecommercerestapi/service/ShoppingCartService.java index 7520bbf..f657c98 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/service/ShoppingCartService.java +++ b/src/main/java/com/manir/springbootecommercerestapi/service/ShoppingCartService.java @@ -1,14 +1,15 @@ package com.manir.springbootecommercerestapi.service; +import com.manir.springbootecommercerestapi.model.User; import com.manir.springbootecommercerestapi.response.CartItemResponse; public interface ShoppingCartService { - CartItemResponse findByCustomerId(Long customerId); + CartItemResponse findByCustomer(User customer); - CartItemResponse addCartItem(Long customerId, Long productId, Integer quantity); + CartItemResponse addCartItem(User customer, Long productId, Integer quantity); - CartItemResponse updateItemQuantity(Long customerId, Long productId, Integer quantity); + CartItemResponse updateItemQuantity(User customer, Long productId, Integer quantity); - void deleteItemProduct(Long customerId, Long productId); + void deleteItemProduct(User customer, Long productId); } From 4f28a19f8aa7b48ebad094d840bbbfb0013b970a Mon Sep 17 00:00:00 2001 From: manirDev <mhtnourmhtmjr@gmail.com> Date: Tue, 15 Nov 2022 14:52:20 +0300 Subject: [PATCH 07/16] order and ordered products is implemented successfully. --- .../controller/OrderController.java | 63 +++++++++++++ .../controller/ShoppingCartController.java | 9 +- .../dto/OrderDto.java | 3 + .../dto/OrderProductsDto.java | 13 +++ .../model/Order.java | 7 +- .../model/User.java | 7 +- .../repository/CartItemRepository.java | 4 + .../repository/OrderProductsRepository.java | 8 ++ .../repository/OrderRepository.java | 12 +++ .../Impl/OrderProductsServiceImpl.java | 22 +++++ .../service/Impl/OrderServiceImpl.java | 94 +++++++++++++++++++ .../service/OrderProductsService.java | 7 ++ .../service/OrderService.java | 13 +++ 13 files changed, 254 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/manir/springbootecommercerestapi/controller/OrderController.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/dto/OrderProductsDto.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/repository/OrderProductsRepository.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/repository/OrderRepository.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/service/Impl/OrderProductsServiceImpl.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/service/Impl/OrderServiceImpl.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/service/OrderProductsService.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/service/OrderService.java diff --git a/src/main/java/com/manir/springbootecommercerestapi/controller/OrderController.java b/src/main/java/com/manir/springbootecommercerestapi/controller/OrderController.java new file mode 100644 index 0000000..0805dee --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/controller/OrderController.java @@ -0,0 +1,63 @@ +package com.manir.springbootecommercerestapi.controller; + +import com.manir.springbootecommercerestapi.dto.OrderDto; +import com.manir.springbootecommercerestapi.exception.EcommerceApiException; +import com.manir.springbootecommercerestapi.model.Order; +import com.manir.springbootecommercerestapi.model.User; +import com.manir.springbootecommercerestapi.repository.UserRepository; +import com.manir.springbootecommercerestapi.service.OrderService; +import com.manir.springbootecommercerestapi.utils.isAuthenticatedAsAdminOrUser; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.authentication.AnonymousAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@RestController +@RequestMapping(value = "api/v1/order") +public class OrderController { + + @Autowired + private UserRepository userRepository; + @Autowired + private OrderService orderService; + + //place order complete order api + @isAuthenticatedAsAdminOrUser + @PostMapping("/placeOrder") + public ResponseEntity<?> placeOrder(@AuthenticationPrincipal Authentication authentication){ + authentication = SecurityContextHolder.getContext().getAuthentication(); + if (!(authentication instanceof AnonymousAuthenticationToken)){ + String currentUserEmail = authentication.getName(); + User customer = userRepository.findByEmail(currentUserEmail).orElseThrow(() -> new UsernameNotFoundException("Customer Not found")); + orderService.placeOrder(customer); + return new ResponseEntity<>("Order placed successfully", HttpStatus.CREATED); + }else{ + throw new EcommerceApiException("User not authenticated", HttpStatus.BAD_REQUEST); + } + } + + //find order by customer api + @isAuthenticatedAsAdminOrUser + @GetMapping("/findByCustomer") + public List<OrderDto> listOrdersByCustomer(@AuthenticationPrincipal Authentication authentication){ + authentication = SecurityContextHolder.getContext().getAuthentication(); + if (!(authentication instanceof AnonymousAuthenticationToken)){ + String currentUserEmail = authentication.getName(); + User customer = userRepository.findByEmail(currentUserEmail).orElseThrow(() -> new UsernameNotFoundException("Customer Not found")); + List<OrderDto> customerOrders = orderService.listOrdersByCustomer(customer); + return customerOrders; + }else{ + throw new EcommerceApiException("User not authenticated", HttpStatus.BAD_REQUEST); + } + } +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/controller/ShoppingCartController.java b/src/main/java/com/manir/springbootecommercerestapi/controller/ShoppingCartController.java index 593ffe0..7cac9e1 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/controller/ShoppingCartController.java +++ b/src/main/java/com/manir/springbootecommercerestapi/controller/ShoppingCartController.java @@ -4,6 +4,7 @@ import com.manir.springbootecommercerestapi.model.User; import com.manir.springbootecommercerestapi.repository.UserRepository; import com.manir.springbootecommercerestapi.response.CartItemResponse; +import com.manir.springbootecommercerestapi.service.OrderService; import com.manir.springbootecommercerestapi.service.ShoppingCartService; import com.manir.springbootecommercerestapi.utils.isAuthenticatedAsAdminOrUser; import org.springframework.beans.factory.annotation.Autowired; @@ -24,10 +25,10 @@ public class ShoppingCartController { @Resource private ShoppingCartService shoppingCartService; - @Autowired private UserRepository userRepository; - + @Autowired + private OrderService orderService; //find by customer api @isAuthenticatedAsAdminOrUser @@ -96,4 +97,8 @@ public ResponseEntity<String> deleteItemProduct(@AuthenticationPrincipal Authent throw new EcommerceApiException("User not authenticated", HttpStatus.BAD_REQUEST); } } + + + + } diff --git a/src/main/java/com/manir/springbootecommercerestapi/dto/OrderDto.java b/src/main/java/com/manir/springbootecommercerestapi/dto/OrderDto.java index 7f2cee5..a5c1332 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/dto/OrderDto.java +++ b/src/main/java/com/manir/springbootecommercerestapi/dto/OrderDto.java @@ -1,5 +1,6 @@ package com.manir.springbootecommercerestapi.dto; +import com.manir.springbootecommercerestapi.model.User; import lombok.Data; @Data @@ -12,4 +13,6 @@ public class OrderDto { private double totalPrice; private String note; private String status; + + private User customer; } diff --git a/src/main/java/com/manir/springbootecommercerestapi/dto/OrderProductsDto.java b/src/main/java/com/manir/springbootecommercerestapi/dto/OrderProductsDto.java new file mode 100644 index 0000000..166dad0 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/dto/OrderProductsDto.java @@ -0,0 +1,13 @@ +package com.manir.springbootecommercerestapi.dto; + +import lombok.Data; + +@Data +public class OrderProductsDto { + private Long id; + private double productPrice; + private Integer productQuantity; + private double totalPrice; + private String note; + private String status; +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/model/Order.java b/src/main/java/com/manir/springbootecommercerestapi/model/Order.java index 56054d5..73e9f68 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/model/Order.java +++ b/src/main/java/com/manir/springbootecommercerestapi/model/Order.java @@ -1,15 +1,14 @@ package com.manir.springbootecommercerestapi.model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; +import lombok.*; import javax.persistence.*; import java.util.Set; @AllArgsConstructor @NoArgsConstructor -@Data +@Getter +@Setter @Entity @Table(name = "orders") public class Order { diff --git a/src/main/java/com/manir/springbootecommercerestapi/model/User.java b/src/main/java/com/manir/springbootecommercerestapi/model/User.java index 7489091..edc66b9 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/model/User.java +++ b/src/main/java/com/manir/springbootecommercerestapi/model/User.java @@ -1,11 +1,14 @@ package com.manir.springbootecommercerestapi.model; -import lombok.Data; +import lombok.*; import javax.persistence.*; import java.util.Set; -@Data +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor @Entity @Table(name = "users", uniqueConstraints = {@UniqueConstraint(columnNames = {"userName"}), @UniqueConstraint(columnNames = {"email"}) diff --git a/src/main/java/com/manir/springbootecommercerestapi/repository/CartItemRepository.java b/src/main/java/com/manir/springbootecommercerestapi/repository/CartItemRepository.java index 0f1c119..5ff677a 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/repository/CartItemRepository.java +++ b/src/main/java/com/manir/springbootecommercerestapi/repository/CartItemRepository.java @@ -23,4 +23,8 @@ public interface CartItemRepository extends JpaRepository<CartItem, Long> { @Modifying void deleteByCustomerAndProduct(Long customerId, Long productId); + @Query("DELETE FROM CartItem c WHERE c.customer.id = ?1") + @Modifying + void deleteByCustomerId(Long customerId); + } diff --git a/src/main/java/com/manir/springbootecommercerestapi/repository/OrderProductsRepository.java b/src/main/java/com/manir/springbootecommercerestapi/repository/OrderProductsRepository.java new file mode 100644 index 0000000..4a4037b --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/repository/OrderProductsRepository.java @@ -0,0 +1,8 @@ +package com.manir.springbootecommercerestapi.repository; + +import com.manir.springbootecommercerestapi.model.OrderProducts; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface OrderProductsRepository extends JpaRepository<OrderProducts, Long> { + +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/repository/OrderRepository.java b/src/main/java/com/manir/springbootecommercerestapi/repository/OrderRepository.java new file mode 100644 index 0000000..d0e3573 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/repository/OrderRepository.java @@ -0,0 +1,12 @@ +package com.manir.springbootecommercerestapi.repository; + +import com.manir.springbootecommercerestapi.model.Order; +import com.manir.springbootecommercerestapi.model.User; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface OrderRepository extends JpaRepository<Order, Long> { + + List<Order> findByCustomer(User customer); +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/OrderProductsServiceImpl.java b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/OrderProductsServiceImpl.java new file mode 100644 index 0000000..a7fd767 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/OrderProductsServiceImpl.java @@ -0,0 +1,22 @@ +package com.manir.springbootecommercerestapi.service.Impl; + +import com.manir.springbootecommercerestapi.model.OrderProducts; +import com.manir.springbootecommercerestapi.repository.OrderProductsRepository; +import com.manir.springbootecommercerestapi.service.OrderProductsService; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; + +@Service +@AllArgsConstructor +public class OrderProductsServiceImpl implements OrderProductsService { + + @Resource(name = "orderProductsRepository") + private final OrderProductsRepository orderProductsRepository; + + @Override + public void addOrderProducts(OrderProducts orderProducts) { + orderProductsRepository.save(orderProducts); + } +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/OrderServiceImpl.java b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/OrderServiceImpl.java new file mode 100644 index 0000000..45d1970 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/OrderServiceImpl.java @@ -0,0 +1,94 @@ +package com.manir.springbootecommercerestapi.service.Impl; + +import com.manir.springbootecommercerestapi.dto.CartItemDto; +import com.manir.springbootecommercerestapi.dto.OrderDto; +import com.manir.springbootecommercerestapi.exception.EcommerceApiException; +import com.manir.springbootecommercerestapi.model.Order; +import com.manir.springbootecommercerestapi.model.OrderProducts; +import com.manir.springbootecommercerestapi.model.User; +import com.manir.springbootecommercerestapi.repository.CartItemRepository; +import com.manir.springbootecommercerestapi.repository.OrderRepository; +import com.manir.springbootecommercerestapi.response.CartItemResponse; +import com.manir.springbootecommercerestapi.service.OrderProductsService; +import com.manir.springbootecommercerestapi.service.OrderService; +import com.manir.springbootecommercerestapi.service.ShoppingCartService; +import lombok.AllArgsConstructor; +import org.modelmapper.ModelMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.List; +import java.util.stream.Collectors; + +@Service +@AllArgsConstructor +public class OrderServiceImpl implements OrderService { + + @Autowired + private final OrderRepository orderRepository; + @Autowired + private final OrderProductsService orderProductsService; + @Autowired + private final CartItemRepository cartItemRepository; + @Autowired + private final ShoppingCartService shoppingCartService; + @Autowired + private final ModelMapper modelMapper; + + @Override + @Transactional + public void placeOrder(User customer) { + CartItemResponse cartItemDto = shoppingCartService.findByCustomer(customer); + OrderDto orderDto = new OrderDto(); + orderDto.setTotalPrice(cartItemDto.getTotalCost()); + orderDto.setEmail(customer.getEmail()); + orderDto.setName(customer.getName()); + OrderDto savedOrder = saveOrder(orderDto, customer); + List<CartItemDto> cartItemDtoList = cartItemDto.getContent(); + for(CartItemDto cartItem : cartItemDtoList){ + OrderProducts orderProducts = new OrderProducts(); + orderProducts.setCustomer(customer); + orderProducts.setProduct(cartItem.getProduct()); + orderProducts.setOrder(mapToEntity(savedOrder)); + orderProducts.setProductPrice(cartItem.getProduct().getPrice()); + orderProducts.setProductQuantity(cartItem.getQuantity()); + orderProducts.setTotalPrice(cartItemDto.getTotalCost()); + orderProductsService.addOrderProducts(orderProducts); + } + cartItemRepository.deleteByCustomerId(customer.getId()); + } + + @Override + public OrderDto saveOrder(OrderDto orderDto, User customer) { + //convert to entity + Order order = mapToEntity(orderDto); + //save order to db + Order placedOrder = orderRepository.save(order); + return mapToDto(placedOrder); + } + + @Override + public List<OrderDto> listOrdersByCustomer(User customer) { + List<Order> orders = orderRepository.findByCustomer(customer); + if (orders.size() == 0){ + throw new EcommerceApiException("User has no order", HttpStatus.BAD_REQUEST); + } + List<OrderDto> orderDtoList = orders.stream() + .map(order -> mapToDto(order)) + .collect(Collectors.toList()); + return orderDtoList; + } + + //map to Entity + private Order mapToEntity(OrderDto orderDto){ + Order order = modelMapper.map(orderDto, Order.class); + return order; + } + //map to Dto + private OrderDto mapToDto(Order order){ + OrderDto orderDto = modelMapper.map(order, OrderDto.class); + return orderDto; + } +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/OrderProductsService.java b/src/main/java/com/manir/springbootecommercerestapi/service/OrderProductsService.java new file mode 100644 index 0000000..c198a83 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/service/OrderProductsService.java @@ -0,0 +1,7 @@ +package com.manir.springbootecommercerestapi.service; + +import com.manir.springbootecommercerestapi.model.OrderProducts; + +public interface OrderProductsService { + void addOrderProducts(OrderProducts orderProducts); +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/OrderService.java b/src/main/java/com/manir/springbootecommercerestapi/service/OrderService.java new file mode 100644 index 0000000..e2d9da9 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/service/OrderService.java @@ -0,0 +1,13 @@ +package com.manir.springbootecommercerestapi.service; + +import com.manir.springbootecommercerestapi.dto.OrderDto; +import com.manir.springbootecommercerestapi.model.User; + +import java.util.List; + +public interface OrderService { + + void placeOrder(User customer); + OrderDto saveOrder(OrderDto orderDto, User customer); + List<OrderDto> listOrdersByCustomer(User customer); +} From b02e91b2ddc40c2efb68a8d49498e90fd5768c32 Mon Sep 17 00:00:00 2001 From: manirDev <mhtnourmhtmjr@gmail.com> Date: Wed, 16 Nov 2022 11:05:37 +0300 Subject: [PATCH 08/16] Find Customer order and ordered items are done. --- .../config/SecurityConfig.java | 6 ---- .../controller/OrderController.java | 20 +++++++++++- .../dto/OrderDto.java | 2 ++ .../repository/OrderProductsRepository.java | 5 ++- .../Impl/OrderProductsServiceImpl.java | 31 +++++++++++++++++++ .../service/Impl/OrderServiceImpl.java | 3 +- .../service/OrderProductsService.java | 5 +++ 7 files changed, 63 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/manir/springbootecommercerestapi/config/SecurityConfig.java b/src/main/java/com/manir/springbootecommercerestapi/config/SecurityConfig.java index baf3107..8314f0e 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/config/SecurityConfig.java +++ b/src/main/java/com/manir/springbootecommercerestapi/config/SecurityConfig.java @@ -11,14 +11,8 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.core.userdetails.User; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.security.provisioning.InMemoryUserDetailsManager; - -import javax.annotation.Resource; @Configuration @EnableWebSecurity diff --git a/src/main/java/com/manir/springbootecommercerestapi/controller/OrderController.java b/src/main/java/com/manir/springbootecommercerestapi/controller/OrderController.java index 0805dee..172436f 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/controller/OrderController.java +++ b/src/main/java/com/manir/springbootecommercerestapi/controller/OrderController.java @@ -1,10 +1,11 @@ package com.manir.springbootecommercerestapi.controller; import com.manir.springbootecommercerestapi.dto.OrderDto; +import com.manir.springbootecommercerestapi.dto.OrderProductsDto; import com.manir.springbootecommercerestapi.exception.EcommerceApiException; -import com.manir.springbootecommercerestapi.model.Order; import com.manir.springbootecommercerestapi.model.User; import com.manir.springbootecommercerestapi.repository.UserRepository; +import com.manir.springbootecommercerestapi.service.OrderProductsService; import com.manir.springbootecommercerestapi.service.OrderService; import com.manir.springbootecommercerestapi.utils.isAuthenticatedAsAdminOrUser; import org.springframework.beans.factory.annotation.Autowired; @@ -30,6 +31,8 @@ public class OrderController { private UserRepository userRepository; @Autowired private OrderService orderService; + @Autowired + private OrderProductsService orderProductsService; //place order complete order api @isAuthenticatedAsAdminOrUser @@ -60,4 +63,19 @@ public List<OrderDto> listOrdersByCustomer(@AuthenticationPrincipal Authenticati throw new EcommerceApiException("User not authenticated", HttpStatus.BAD_REQUEST); } } + + //find ordered items by Customer + @isAuthenticatedAsAdminOrUser + @GetMapping("/findOrderedItemsByCustomer") + public List<OrderProductsDto> findOrderedItemsByCustomer(@AuthenticationPrincipal Authentication authentication){ + authentication = SecurityContextHolder.getContext().getAuthentication(); + if (!(authentication instanceof AnonymousAuthenticationToken)){ + String currentUserEmail = authentication.getName(); + User customer = userRepository.findByEmail(currentUserEmail).orElseThrow(() -> new UsernameNotFoundException("Customer Not found")); + List<OrderProductsDto> customerOrderedItems = orderProductsService.findOrderItemsByCustomer(customer); + return customerOrderedItems; + }else{ + throw new EcommerceApiException("User not authenticated", HttpStatus.BAD_REQUEST); + } + } } diff --git a/src/main/java/com/manir/springbootecommercerestapi/dto/OrderDto.java b/src/main/java/com/manir/springbootecommercerestapi/dto/OrderDto.java index a5c1332..e4c5156 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/dto/OrderDto.java +++ b/src/main/java/com/manir/springbootecommercerestapi/dto/OrderDto.java @@ -1,5 +1,6 @@ package com.manir.springbootecommercerestapi.dto; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.manir.springbootecommercerestapi.model.User; import lombok.Data; @@ -14,5 +15,6 @@ public class OrderDto { private String note; private String status; + @JsonIgnore private User customer; } diff --git a/src/main/java/com/manir/springbootecommercerestapi/repository/OrderProductsRepository.java b/src/main/java/com/manir/springbootecommercerestapi/repository/OrderProductsRepository.java index 4a4037b..03d331d 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/repository/OrderProductsRepository.java +++ b/src/main/java/com/manir/springbootecommercerestapi/repository/OrderProductsRepository.java @@ -1,8 +1,11 @@ package com.manir.springbootecommercerestapi.repository; import com.manir.springbootecommercerestapi.model.OrderProducts; +import com.manir.springbootecommercerestapi.model.User; import org.springframework.data.jpa.repository.JpaRepository; -public interface OrderProductsRepository extends JpaRepository<OrderProducts, Long> { +import java.util.List; +public interface OrderProductsRepository extends JpaRepository<OrderProducts, Long> { + List<OrderProducts> findByCustomer(User customer); } diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/OrderProductsServiceImpl.java b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/OrderProductsServiceImpl.java index a7fd767..0a3e532 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/OrderProductsServiceImpl.java +++ b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/OrderProductsServiceImpl.java @@ -1,12 +1,20 @@ package com.manir.springbootecommercerestapi.service.Impl; +import com.manir.springbootecommercerestapi.dto.OrderProductsDto; +import com.manir.springbootecommercerestapi.exception.EcommerceApiException; import com.manir.springbootecommercerestapi.model.OrderProducts; +import com.manir.springbootecommercerestapi.model.User; import com.manir.springbootecommercerestapi.repository.OrderProductsRepository; import com.manir.springbootecommercerestapi.service.OrderProductsService; import lombok.AllArgsConstructor; +import org.modelmapper.ModelMapper; +import org.modelmapper.convention.MatchingStrategies; +import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; import javax.annotation.Resource; +import java.util.List; +import java.util.stream.Collectors; @Service @AllArgsConstructor @@ -14,9 +22,32 @@ public class OrderProductsServiceImpl implements OrderProductsService { @Resource(name = "orderProductsRepository") private final OrderProductsRepository orderProductsRepository; + @Resource(name = "modelMapper") + private final ModelMapper modelMapper; @Override public void addOrderProducts(OrderProducts orderProducts) { orderProductsRepository.save(orderProducts); } + + @Override + public List<OrderProductsDto> findOrderItemsByCustomer(User customer) { + + List<OrderProducts> orderProducts = orderProductsRepository.findByCustomer(customer); + if (orderProducts.size() == 0){ + throw new EcommerceApiException("User has no ordered products", HttpStatus.BAD_REQUEST); + } + List<OrderProductsDto> orderProductsDtoList = orderProducts.stream() + .map(orderProduct -> mapToDto(orderProduct)) + .collect(Collectors.toList()); + return orderProductsDtoList; + } + + //map to dto + private OrderProductsDto mapToDto(OrderProducts orderProducts){ + modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT); + OrderProductsDto orderProductsDto = modelMapper.map(orderProducts, OrderProductsDto.class); + + return orderProductsDto; + } } diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/OrderServiceImpl.java b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/OrderServiceImpl.java index 45d1970..8b58f61 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/OrderServiceImpl.java +++ b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/OrderServiceImpl.java @@ -45,6 +45,7 @@ public void placeOrder(User customer) { orderDto.setTotalPrice(cartItemDto.getTotalCost()); orderDto.setEmail(customer.getEmail()); orderDto.setName(customer.getName()); + orderDto.setCustomer(customer); OrderDto savedOrder = saveOrder(orderDto, customer); List<CartItemDto> cartItemDtoList = cartItemDto.getContent(); for(CartItemDto cartItem : cartItemDtoList){ @@ -54,7 +55,7 @@ public void placeOrder(User customer) { orderProducts.setOrder(mapToEntity(savedOrder)); orderProducts.setProductPrice(cartItem.getProduct().getPrice()); orderProducts.setProductQuantity(cartItem.getQuantity()); - orderProducts.setTotalPrice(cartItemDto.getTotalCost()); + orderProducts.setTotalPrice(cartItem.getProduct().getPrice()*cartItem.getQuantity()); orderProductsService.addOrderProducts(orderProducts); } cartItemRepository.deleteByCustomerId(customer.getId()); diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/OrderProductsService.java b/src/main/java/com/manir/springbootecommercerestapi/service/OrderProductsService.java index c198a83..2fec5dc 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/service/OrderProductsService.java +++ b/src/main/java/com/manir/springbootecommercerestapi/service/OrderProductsService.java @@ -1,7 +1,12 @@ package com.manir.springbootecommercerestapi.service; +import com.manir.springbootecommercerestapi.dto.OrderProductsDto; import com.manir.springbootecommercerestapi.model.OrderProducts; +import com.manir.springbootecommercerestapi.model.User; + +import java.util.List; public interface OrderProductsService { void addOrderProducts(OrderProducts orderProducts); + List<OrderProductsDto> findOrderItemsByCustomer(User customer); } From b3e8afdda41c3c768c916142dc1a2cff82c5ce56 Mon Sep 17 00:00:00 2001 From: manirDev <mhtnourmhtmjr@gmail.com> Date: Wed, 16 Nov 2022 12:48:26 +0300 Subject: [PATCH 09/16] JWT token provider is implemented. --- pom.xml | 7 ++ .../config/SecurityConfig.java | 30 ++++++++- .../controller/AuthController.java | 12 +++- .../response/JWTAuthResponse.java | 15 +++++ .../security/JwtAuthenticationEntryPoint.java | 21 ++++++ .../security/JwtAuthenticationFilter.java | 57 ++++++++++++++++ .../security/JwtTokenProvider.java | 66 +++++++++++++++++++ src/main/resources/application.properties | 3 + 8 files changed, 207 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/manir/springbootecommercerestapi/response/JWTAuthResponse.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/security/JwtAuthenticationEntryPoint.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/security/JwtAuthenticationFilter.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/security/JwtTokenProvider.java diff --git a/pom.xml b/pom.xml index 1cd8705..083ab16 100644 --- a/pom.xml +++ b/pom.xml @@ -52,6 +52,13 @@ <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> + <!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt --> + <dependency> + <groupId>io.jsonwebtoken</groupId> + <artifactId>jjwt</artifactId> + <version>0.9.1</version> + </dependency> + <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> diff --git a/src/main/java/com/manir/springbootecommercerestapi/config/SecurityConfig.java b/src/main/java/com/manir/springbootecommercerestapi/config/SecurityConfig.java index 8314f0e..cb723b4 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/config/SecurityConfig.java +++ b/src/main/java/com/manir/springbootecommercerestapi/config/SecurityConfig.java @@ -1,6 +1,8 @@ package com.manir.springbootecommercerestapi.config; import com.manir.springbootecommercerestapi.security.CustomUserDetailsService; +import com.manir.springbootecommercerestapi.security.JwtAuthenticationEntryPoint; +import com.manir.springbootecommercerestapi.security.JwtAuthenticationFilter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -11,8 +13,10 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; @Configuration @EnableWebSecurity @@ -25,21 +29,43 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private CustomUserDetailsService customUserDetailsService; + @Autowired + private JwtAuthenticationEntryPoint authenticationEntryPoint; @Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() + /*-------------------------JWT Starts------------------------------*/ + .exceptionHandling() + .authenticationEntryPoint(authenticationEntryPoint) + .and() + .sessionManagement() + .sessionCreationPolicy(SessionCreationPolicy.STATELESS) + /*-------------------------JWT ends------------------------------*/ + .and() .authorizeRequests() //to permit all get request and secure post put and delete methods .antMatchers(HttpMethod.GET, "/api/**").permitAll() //authorize singIn and signUp .antMatchers("/api/v1/auth/**").permitAll() .anyRequest() - .authenticated() - .and() + .authenticated(); + + /** + Basic auth used before JWT implementation + .and() .httpBasic(); + **/ + http + .addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class); + + } + //Jwt auth filter method + @Bean + public JwtAuthenticationFilter jwtAuthenticationFilter(){ + return new JwtAuthenticationFilter(); } //In memory Auth diff --git a/src/main/java/com/manir/springbootecommercerestapi/controller/AuthController.java b/src/main/java/com/manir/springbootecommercerestapi/controller/AuthController.java index 2bf09f2..672f51a 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/controller/AuthController.java +++ b/src/main/java/com/manir/springbootecommercerestapi/controller/AuthController.java @@ -3,6 +3,8 @@ import com.manir.springbootecommercerestapi.dto.LoginDto; import com.manir.springbootecommercerestapi.dto.SignUpDto; import com.manir.springbootecommercerestapi.repository.UserRepository; +import com.manir.springbootecommercerestapi.response.JWTAuthResponse; +import com.manir.springbootecommercerestapi.security.JwtTokenProvider; import com.manir.springbootecommercerestapi.service.UserRegisterService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @@ -28,10 +30,12 @@ public class AuthController { private UserRepository userRepository; @Autowired private UserRegisterService userRegisterService; + @Autowired + private JwtTokenProvider tokenProvider; //login api @PostMapping("/login") - public ResponseEntity<String> authenticateUser(@RequestBody LoginDto loginDto){ + public ResponseEntity<JWTAuthResponse> authenticateUser(@RequestBody LoginDto loginDto){ Authentication authentication = authenticationManager.authenticate( new UsernamePasswordAuthenticationToken( @@ -40,7 +44,11 @@ public ResponseEntity<String> authenticateUser(@RequestBody LoginDto loginDto){ ) ); SecurityContextHolder.getContext().setAuthentication(authentication); - return new ResponseEntity<>("User sign-In successfully", HttpStatus.OK); + + //get token from token provider + String token = tokenProvider.generateToken(authentication); + + return new ResponseEntity<>(new JWTAuthResponse(token), HttpStatus.OK); } //register api diff --git a/src/main/java/com/manir/springbootecommercerestapi/response/JWTAuthResponse.java b/src/main/java/com/manir/springbootecommercerestapi/response/JWTAuthResponse.java new file mode 100644 index 0000000..52c7ae9 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/response/JWTAuthResponse.java @@ -0,0 +1,15 @@ +package com.manir.springbootecommercerestapi.response; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class JWTAuthResponse { + private String accessToken; + private String tokenType = "Bearer"; + + public JWTAuthResponse(String accessToken) { + this.accessToken = accessToken; + } +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/security/JwtAuthenticationEntryPoint.java b/src/main/java/com/manir/springbootecommercerestapi/security/JwtAuthenticationEntryPoint.java new file mode 100644 index 0000000..5b485e4 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/security/JwtAuthenticationEntryPoint.java @@ -0,0 +1,21 @@ +package com.manir.springbootecommercerestapi.security; + +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.stereotype.Component; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@Component +public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint { + @Override + public void commence(HttpServletRequest request, + HttpServletResponse response, + AuthenticationException authException) throws IOException, ServletException { + + response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage()); + } +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/security/JwtAuthenticationFilter.java b/src/main/java/com/manir/springbootecommercerestapi/security/JwtAuthenticationFilter.java new file mode 100644 index 0000000..620ef9e --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/security/JwtAuthenticationFilter.java @@ -0,0 +1,57 @@ +package com.manir.springbootecommercerestapi.security; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.util.StringUtils; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +public class JwtAuthenticationFilter extends OncePerRequestFilter { + + @Autowired + private JwtTokenProvider tokenProvider; + @Autowired + private CustomUserDetailsService userDetailsService; + + @Override + protected void doFilterInternal(HttpServletRequest request, + HttpServletResponse response, + FilterChain filterChain) throws ServletException, IOException { + + //get jwt token from http request + String token = getJWTFromToken(request); + //validate token + if (StringUtils.hasText(token) && tokenProvider.validateToken(token)){ + //retrieve user form token + String userName = tokenProvider.getUserNameFromToken(token); + //load user associated with the token + UserDetails userDetails = userDetailsService.loadUserByUsername(userName); + UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken( + userDetails, null, userDetails.getAuthorities() + ); + //set spring security + authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + SecurityContextHolder.getContext().setAuthentication(authenticationToken); + } + filterChain.doFilter(request, response); + } + + //get jwt from token + //Bearer <accessToken> + private String getJWTFromToken(HttpServletRequest request){ + + String bearerToken = request.getHeader("Authorization"); + if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")){ + return bearerToken.substring(7, bearerToken.length()); + } + return null; + } +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/security/JwtTokenProvider.java b/src/main/java/com/manir/springbootecommercerestapi/security/JwtTokenProvider.java new file mode 100644 index 0000000..5e18a26 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/security/JwtTokenProvider.java @@ -0,0 +1,66 @@ +package com.manir.springbootecommercerestapi.security; + +import com.manir.springbootecommercerestapi.exception.EcommerceApiException; +import io.jsonwebtoken.*; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Component; + +import java.util.Date; + +@Component +public class JwtTokenProvider { + + @Value("${app.jwt-secret}") + private String jwtSecret; + @Value("${app.jwt-expiration-milliseconds}") + private int jwtExpirationTime; + + //generate token method + + public String generateToken(Authentication authentication){ + String userName = authentication.getName(); + Date currentDate = new Date(); + Date expireDate = new Date(currentDate.getTime() + jwtExpirationTime); + + String token = Jwts.builder() + .setSubject(userName) + .setIssuedAt(new Date()) + .setExpiration(expireDate) + .signWith(SignatureAlgorithm.HS512, jwtSecret) + .compact(); + + return token; + } + + //get username from the token, retrieve username from generated token + public String getUserNameFromToken(String token){ + Claims claims = Jwts.parser() + .setSigningKey(jwtSecret) + .parseClaimsJws(token) + .getBody(); + + return claims.getSubject(); + } + + //validate JWT token + public boolean validateToken(String token){ + try { + Jwts.parser() + .setSigningKey(jwtSecret) + .parseClaimsJws(token); + return true; + }catch (SignatureException e){ + throw new EcommerceApiException("Invalid JWT signature", HttpStatus.BAD_REQUEST); + }catch (MalformedJwtException e){ + throw new EcommerceApiException("Invalid JWT token", HttpStatus.BAD_REQUEST); + }catch (ExpiredJwtException e){ + throw new EcommerceApiException("Expired JWT token", HttpStatus.BAD_REQUEST); + }catch (UnsupportedJwtException e){ + throw new EcommerceApiException("Unsupported JWT token", HttpStatus.BAD_REQUEST); + }catch (IllegalArgumentException e){ + throw new EcommerceApiException("JWT claims string is empty", HttpStatus.BAD_REQUEST); + } + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 8c3a84b..bf443c7 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -13,3 +13,6 @@ logging.level.org.springframework.security=DEBUG #spring.security.customer.name= customer #spring.security.customer.roles= ADMIN +#JWT properties +app.jwt-secret = JWTSecretKey +app.jwt-expiration-milliseconds = 604800000 From fe3785411599e58c630ffeb55187b7bdf173316b Mon Sep 17 00:00:00 2001 From: manirDev <mhtnourmhtmjr@gmail.com> Date: Wed, 16 Nov 2022 15:12:17 +0300 Subject: [PATCH 10/16] Some code refactors are done on getting authenticated user. --- .../controller/OrderController.java | 51 ++++++--------- .../controller/ShoppingCartController.java | 63 +++++-------------- .../service/CommonService.java | 5 ++ .../service/Impl/CommonServiceImpl.java | 30 +++++++++ .../service/Impl/OrderServiceImpl.java | 20 +++--- .../service/OrderService.java | 2 +- 6 files changed, 83 insertions(+), 88 deletions(-) diff --git a/src/main/java/com/manir/springbootecommercerestapi/controller/OrderController.java b/src/main/java/com/manir/springbootecommercerestapi/controller/OrderController.java index 172436f..302422b 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/controller/OrderController.java +++ b/src/main/java/com/manir/springbootecommercerestapi/controller/OrderController.java @@ -2,20 +2,17 @@ import com.manir.springbootecommercerestapi.dto.OrderDto; import com.manir.springbootecommercerestapi.dto.OrderProductsDto; -import com.manir.springbootecommercerestapi.exception.EcommerceApiException; import com.manir.springbootecommercerestapi.model.User; import com.manir.springbootecommercerestapi.repository.UserRepository; +import com.manir.springbootecommercerestapi.service.CommonService; import com.manir.springbootecommercerestapi.service.OrderProductsService; import com.manir.springbootecommercerestapi.service.OrderService; import com.manir.springbootecommercerestapi.utils.isAuthenticatedAsAdminOrUser; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; @@ -27,55 +24,43 @@ @RequestMapping(value = "api/v1/order") public class OrderController { - @Autowired - private UserRepository userRepository; @Autowired private OrderService orderService; @Autowired private OrderProductsService orderProductsService; + @Autowired + private CommonService commonService; //place order complete order api @isAuthenticatedAsAdminOrUser @PostMapping("/placeOrder") public ResponseEntity<?> placeOrder(@AuthenticationPrincipal Authentication authentication){ - authentication = SecurityContextHolder.getContext().getAuthentication(); - if (!(authentication instanceof AnonymousAuthenticationToken)){ - String currentUserEmail = authentication.getName(); - User customer = userRepository.findByEmail(currentUserEmail).orElseThrow(() -> new UsernameNotFoundException("Customer Not found")); - orderService.placeOrder(customer); - return new ResponseEntity<>("Order placed successfully", HttpStatus.CREATED); - }else{ - throw new EcommerceApiException("User not authenticated", HttpStatus.BAD_REQUEST); - } + User customer = commonService.getCurrentAuthenticatedUser(authentication); + orderService.placeOrder(customer); + return new ResponseEntity<>("Order placed successfully", HttpStatus.CREATED); } //find order by customer api @isAuthenticatedAsAdminOrUser @GetMapping("/findByCustomer") public List<OrderDto> listOrdersByCustomer(@AuthenticationPrincipal Authentication authentication){ - authentication = SecurityContextHolder.getContext().getAuthentication(); - if (!(authentication instanceof AnonymousAuthenticationToken)){ - String currentUserEmail = authentication.getName(); - User customer = userRepository.findByEmail(currentUserEmail).orElseThrow(() -> new UsernameNotFoundException("Customer Not found")); - List<OrderDto> customerOrders = orderService.listOrdersByCustomer(customer); - return customerOrders; - }else{ - throw new EcommerceApiException("User not authenticated", HttpStatus.BAD_REQUEST); - } + + User customer = commonService.getCurrentAuthenticatedUser(authentication); + + List<OrderDto> customerOrders = orderService.listOrdersByCustomer(customer); + return customerOrders; } + + //find ordered items by Customer @isAuthenticatedAsAdminOrUser @GetMapping("/findOrderedItemsByCustomer") public List<OrderProductsDto> findOrderedItemsByCustomer(@AuthenticationPrincipal Authentication authentication){ - authentication = SecurityContextHolder.getContext().getAuthentication(); - if (!(authentication instanceof AnonymousAuthenticationToken)){ - String currentUserEmail = authentication.getName(); - User customer = userRepository.findByEmail(currentUserEmail).orElseThrow(() -> new UsernameNotFoundException("Customer Not found")); - List<OrderProductsDto> customerOrderedItems = orderProductsService.findOrderItemsByCustomer(customer); - return customerOrderedItems; - }else{ - throw new EcommerceApiException("User not authenticated", HttpStatus.BAD_REQUEST); - } + User customer = commonService.getCurrentAuthenticatedUser(authentication); + List<OrderProductsDto> customerOrderedItems = orderProductsService.findOrderItemsByCustomer(customer); + return customerOrderedItems; } + + } diff --git a/src/main/java/com/manir/springbootecommercerestapi/controller/ShoppingCartController.java b/src/main/java/com/manir/springbootecommercerestapi/controller/ShoppingCartController.java index 7cac9e1..c3bdfc5 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/controller/ShoppingCartController.java +++ b/src/main/java/com/manir/springbootecommercerestapi/controller/ShoppingCartController.java @@ -1,20 +1,15 @@ package com.manir.springbootecommercerestapi.controller; -import com.manir.springbootecommercerestapi.exception.EcommerceApiException; import com.manir.springbootecommercerestapi.model.User; -import com.manir.springbootecommercerestapi.repository.UserRepository; import com.manir.springbootecommercerestapi.response.CartItemResponse; -import com.manir.springbootecommercerestapi.service.OrderService; +import com.manir.springbootecommercerestapi.service.CommonService; import com.manir.springbootecommercerestapi.service.ShoppingCartService; import com.manir.springbootecommercerestapi.utils.isAuthenticatedAsAdminOrUser; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; @@ -26,26 +21,16 @@ public class ShoppingCartController { @Resource private ShoppingCartService shoppingCartService; @Autowired - private UserRepository userRepository; - @Autowired - private OrderService orderService; + private CommonService commonService; //find by customer api @isAuthenticatedAsAdminOrUser @GetMapping("/findByCustomer") public CartItemResponse findByCustomerId(@AuthenticationPrincipal Authentication authentication){ - authentication = SecurityContextHolder.getContext().getAuthentication(); - if (!(authentication instanceof AnonymousAuthenticationToken)) { - String currentUserEmail = authentication.getName(); - //System.out.println("Name:" + currentUserEmail); - User customer = userRepository.findByEmail(currentUserEmail).orElseThrow(()-> new UsernameNotFoundException("Customer not found")); - CartItemResponse responseCartItems = shoppingCartService.findByCustomer(customer); - return responseCartItems; - - }else{ - throw new EcommerceApiException("User not authenticated", HttpStatus.BAD_REQUEST); - } + User customer = commonService.getCurrentAuthenticatedUser(authentication); + CartItemResponse responseCartItems = shoppingCartService.findByCustomer(customer); + return responseCartItems; } //add item to the cart api @@ -54,15 +39,10 @@ public CartItemResponse findByCustomerId(@AuthenticationPrincipal Authentication public ResponseEntity<CartItemResponse> addCartItem(@AuthenticationPrincipal Authentication authentication, @PathVariable Long productId, @PathVariable Integer quantity){ - authentication = SecurityContextHolder.getContext().getAuthentication(); - if (!(authentication instanceof AnonymousAuthenticationToken)){ - String currentUserEmail = authentication.getName(); - User customer = userRepository.findByEmail(currentUserEmail).orElseThrow(() -> new UsernameNotFoundException("Customer not found")); - CartItemResponse responseCartItem = shoppingCartService.addCartItem(customer, productId, quantity); - return new ResponseEntity<>(responseCartItem, HttpStatus.CREATED); - }else { - throw new EcommerceApiException("User not authenticated", HttpStatus.BAD_REQUEST); - } + + User customer = commonService.getCurrentAuthenticatedUser(authentication); + CartItemResponse responseCartItem = shoppingCartService.addCartItem(customer, productId, quantity); + return new ResponseEntity<>(responseCartItem, HttpStatus.CREATED); } //update item quantity api @@ -71,15 +51,9 @@ public ResponseEntity<CartItemResponse> addCartItem(@AuthenticationPrincipal Aut public ResponseEntity<CartItemResponse> updateItemQuantity(@AuthenticationPrincipal Authentication authentication, @PathVariable Long productId, @PathVariable Integer quantity){ - authentication = SecurityContextHolder.getContext().getAuthentication(); - if (!(authentication instanceof AnonymousAuthenticationToken)){ - String currentUserEmail = authentication.getName(); - User customer = userRepository.findByEmail(currentUserEmail).orElseThrow(() -> new UsernameNotFoundException("Customer Not found")); - CartItemResponse responseCartItem = shoppingCartService.updateItemQuantity(customer, productId, quantity); - return new ResponseEntity<>(responseCartItem, HttpStatus.OK); - }else{ - throw new EcommerceApiException("User not authenticated", HttpStatus.BAD_REQUEST); - } + User customer = commonService.getCurrentAuthenticatedUser(authentication); + CartItemResponse responseCartItem = shoppingCartService.updateItemQuantity(customer, productId, quantity); + return new ResponseEntity<>(responseCartItem, HttpStatus.OK); } //delete item product api @@ -87,15 +61,10 @@ public ResponseEntity<CartItemResponse> updateItemQuantity(@AuthenticationPrinci @DeleteMapping("/deleteItemProduct/{productId}") public ResponseEntity<String> deleteItemProduct(@AuthenticationPrincipal Authentication authentication, @PathVariable Long productId){ - authentication = SecurityContextHolder.getContext().getAuthentication(); - if (!(authentication instanceof AnonymousAuthenticationToken)){ - String currentUserEmail = authentication.getName(); - User customer = userRepository.findByEmail(currentUserEmail).orElseThrow(() -> new UsernameNotFoundException("Customer Not found")); - shoppingCartService.deleteItemProduct(customer, productId); - return ResponseEntity.ok("Product with id = " + productId +" is deleted successfully from your shopping cart"); - }else{ - throw new EcommerceApiException("User not authenticated", HttpStatus.BAD_REQUEST); - } + + User customer = commonService.getCurrentAuthenticatedUser(authentication); + shoppingCartService.deleteItemProduct(customer, productId); + return ResponseEntity.ok("Product with id = " + productId +" is deleted successfully from your shopping cart"); } diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/CommonService.java b/src/main/java/com/manir/springbootecommercerestapi/service/CommonService.java index 1dfce02..e2156a2 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/service/CommonService.java +++ b/src/main/java/com/manir/springbootecommercerestapi/service/CommonService.java @@ -1,9 +1,11 @@ package com.manir.springbootecommercerestapi.service; import com.manir.springbootecommercerestapi.dto.CartItemDto; +import com.manir.springbootecommercerestapi.model.User; import com.manir.springbootecommercerestapi.response.CartItemResponse; import com.manir.springbootecommercerestapi.response.CommonResponse; import org.springframework.data.domain.Page; +import org.springframework.security.core.Authentication; import java.util.List; @@ -14,4 +16,7 @@ public interface CommonService<T> { //cart iem response handler CartItemResponse getResponse(CartItemDto cartItemDto); + + //get current authenticated user + User getCurrentAuthenticatedUser(Authentication authentication); } diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/CommonServiceImpl.java b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/CommonServiceImpl.java index de3fec7..e8cfb9c 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/CommonServiceImpl.java +++ b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/CommonServiceImpl.java @@ -1,24 +1,39 @@ package com.manir.springbootecommercerestapi.service.Impl; import com.manir.springbootecommercerestapi.dto.CartItemDto; +import com.manir.springbootecommercerestapi.exception.EcommerceApiException; +import com.manir.springbootecommercerestapi.model.User; +import com.manir.springbootecommercerestapi.repository.UserRepository; import com.manir.springbootecommercerestapi.response.CartItemResponse; import com.manir.springbootecommercerestapi.response.CommonResponse; import com.manir.springbootecommercerestapi.service.CommonService; +import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.domain.Page; +import org.springframework.http.HttpStatus; +import org.springframework.security.authentication.AnonymousAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; + +import javax.annotation.Resource; import java.util.ArrayList; import java.util.List; @Service @Slf4j +@AllArgsConstructor public class CommonServiceImpl implements CommonService{ private static Logger logger = LoggerFactory.getLogger(CategoryServiceImpl.class); + @Resource(name = "userRepository") + private final UserRepository userRepository; + @Override public CommonResponse getResponseContent(Page page, List dtoList) { @@ -45,4 +60,19 @@ public CartItemResponse getResponse(CartItemDto cartItemDto) { cartItemResponse.setTotalCost(totalPrice); return cartItemResponse; } + + @Override + public User getCurrentAuthenticatedUser(Authentication authentication) { + authentication = SecurityContextHolder.getContext().getAuthentication(); + if (authentication == null || authentication instanceof AnonymousAuthenticationToken){ + throw new EcommerceApiException("User not authenticated", HttpStatus.BAD_REQUEST); + } + String currentUserEmail = authentication.getName(); + User currentUser = userRepository.findByEmail(currentUserEmail) + .orElseThrow( + () -> new UsernameNotFoundException("User Not found") + ); + + return currentUser; + } } diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/OrderServiceImpl.java b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/OrderServiceImpl.java index 8b58f61..40527be 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/OrderServiceImpl.java +++ b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/OrderServiceImpl.java @@ -41,12 +41,9 @@ public class OrderServiceImpl implements OrderService { @Transactional public void placeOrder(User customer) { CartItemResponse cartItemDto = shoppingCartService.findByCustomer(customer); - OrderDto orderDto = new OrderDto(); - orderDto.setTotalPrice(cartItemDto.getTotalCost()); - orderDto.setEmail(customer.getEmail()); - orderDto.setName(customer.getName()); - orderDto.setCustomer(customer); - OrderDto savedOrder = saveOrder(orderDto, customer); + OrderDto orderDto = setFields(cartItemDto, customer); + //save order to the db + OrderDto savedOrder = saveOrder(orderDto); List<CartItemDto> cartItemDtoList = cartItemDto.getContent(); for(CartItemDto cartItem : cartItemDtoList){ OrderProducts orderProducts = new OrderProducts(); @@ -62,7 +59,7 @@ public void placeOrder(User customer) { } @Override - public OrderDto saveOrder(OrderDto orderDto, User customer) { + public OrderDto saveOrder(OrderDto orderDto) { //convert to entity Order order = mapToEntity(orderDto); //save order to db @@ -70,6 +67,15 @@ public OrderDto saveOrder(OrderDto orderDto, User customer) { return mapToDto(placedOrder); } + private OrderDto setFields(CartItemResponse cartItemDto, User customer){ + OrderDto orderDto = new OrderDto(); + orderDto.setTotalPrice(cartItemDto.getTotalCost()); + orderDto.setEmail(customer.getEmail()); + orderDto.setName(customer.getName()); + orderDto.setCustomer(customer); + + return orderDto; + } @Override public List<OrderDto> listOrdersByCustomer(User customer) { List<Order> orders = orderRepository.findByCustomer(customer); diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/OrderService.java b/src/main/java/com/manir/springbootecommercerestapi/service/OrderService.java index e2d9da9..2ff968d 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/service/OrderService.java +++ b/src/main/java/com/manir/springbootecommercerestapi/service/OrderService.java @@ -8,6 +8,6 @@ public interface OrderService { void placeOrder(User customer); - OrderDto saveOrder(OrderDto orderDto, User customer); + OrderDto saveOrder(OrderDto orderDto); List<OrderDto> listOrdersByCustomer(User customer); } From 4ebd51faf7c6d9d51cb20e5906c0cd429c5aebf7 Mon Sep 17 00:00:00 2001 From: manirDev <mhtnourmhtmjr@gmail.com> Date: Wed, 16 Nov 2022 17:08:38 +0300 Subject: [PATCH 11/16] Auditing and Comment code refactors. --- ...SpringBootECommerceRestApiApplication.java | 2 + .../audit/AuditAwareImpl.java | 15 ++++++++ .../controller/CommentController.java | 27 +++++++++++-- .../model/BaseEntity.java | 38 +++++++++++++++++++ .../model/CartItem.java | 2 +- .../model/Category.java | 2 +- .../model/Comment.java | 7 +++- .../model/ImageData.java | 2 +- .../model/Order.java | 2 +- .../model/OrderProducts.java | 2 +- .../model/Product.java | 2 +- .../model/Role.java | 2 +- .../model/User.java | 8 +++- .../repository/CommentRepository.java | 2 + .../service/CommentService.java | 4 +- .../service/Impl/CommentServiceImpl.java | 25 +++++++++++- .../service/Impl/OrderServiceImpl.java | 1 + 17 files changed, 128 insertions(+), 15 deletions(-) create mode 100644 src/main/java/com/manir/springbootecommercerestapi/audit/AuditAwareImpl.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/model/BaseEntity.java diff --git a/src/main/java/com/manir/springbootecommercerestapi/SpringBootECommerceRestApiApplication.java b/src/main/java/com/manir/springbootecommercerestapi/SpringBootECommerceRestApiApplication.java index 4c07638..6b03645 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/SpringBootECommerceRestApiApplication.java +++ b/src/main/java/com/manir/springbootecommercerestapi/SpringBootECommerceRestApiApplication.java @@ -4,8 +4,10 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; @SpringBootApplication +@EnableJpaAuditing(auditorAwareRef = "auditAwareImpl") public class SpringBootECommerceRestApiApplication { public static void main(String[] args) { diff --git a/src/main/java/com/manir/springbootecommercerestapi/audit/AuditAwareImpl.java b/src/main/java/com/manir/springbootecommercerestapi/audit/AuditAwareImpl.java new file mode 100644 index 0000000..2ba6d01 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/audit/AuditAwareImpl.java @@ -0,0 +1,15 @@ +package com.manir.springbootecommercerestapi.audit; + +import org.springframework.data.domain.AuditorAware; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; + +import java.util.Optional; + +@Component("auditAwareImpl") +public class AuditAwareImpl implements AuditorAware<String> { + @Override + public Optional<String> getCurrentAuditor() { + return Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication().getName()); + } +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/controller/CommentController.java b/src/main/java/com/manir/springbootecommercerestapi/controller/CommentController.java index b10c997..b119ef8 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/controller/CommentController.java +++ b/src/main/java/com/manir/springbootecommercerestapi/controller/CommentController.java @@ -1,9 +1,15 @@ package com.manir.springbootecommercerestapi.controller; import com.manir.springbootecommercerestapi.dto.CommentDto; +import com.manir.springbootecommercerestapi.model.User; import com.manir.springbootecommercerestapi.service.CommentService; +import com.manir.springbootecommercerestapi.service.CommonService; +import com.manir.springbootecommercerestapi.utils.isAuthenticatedAsAdminOrUser; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; @@ -13,17 +19,30 @@ @RequestMapping(value = "api/v1/products") public class CommentController { - @Resource + @Autowired private CommentService commentService; + @Autowired + private CommonService commonService; //create comment api + @isAuthenticatedAsAdminOrUser @PostMapping("/{productId}/createComment") - public ResponseEntity<CommentDto> createComment(@PathVariable Long productId, + public ResponseEntity<CommentDto> createComment(@AuthenticationPrincipal Authentication authentication, + @PathVariable Long productId, @RequestBody CommentDto commentDto){ - CommentDto responseComment = commentService.createComment(productId, commentDto); + User customer = commonService.getCurrentAuthenticatedUser(authentication); + CommentDto responseComment = commentService.createComment(customer, productId, commentDto); return new ResponseEntity<>(responseComment, HttpStatus.CREATED); } + //get comment by user + @isAuthenticatedAsAdminOrUser + @GetMapping("/comment/findByUser") + public List<CommentDto> findByUser(@AuthenticationPrincipal Authentication authentication){ + User customer = commonService.getCurrentAuthenticatedUser(authentication); + return commentService.findCommentByCustomer(customer); + } + //get all comments api @GetMapping("/getAllComments") public List<CommentDto> getAllComments(){ @@ -58,4 +77,6 @@ public ResponseEntity<String> deleteComment(@PathVariable Long productId, @PathV commentService.deleteComment(productId, commentId); return ResponseEntity.ok("Comment with id: "+commentId+" is successfully:)"); } + + } diff --git a/src/main/java/com/manir/springbootecommercerestapi/model/BaseEntity.java b/src/main/java/com/manir/springbootecommercerestapi/model/BaseEntity.java new file mode 100644 index 0000000..e9e620f --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/model/BaseEntity.java @@ -0,0 +1,38 @@ +package com.manir.springbootecommercerestapi.model; + +import lombok.Data; +import org.springframework.data.annotation.CreatedBy; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedBy; +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; + +@Data +@MappedSuperclass +/** + Auditing allows us : to see who created data and who updated + then we should enable jpa auditing... + **/ +@EntityListeners(AuditingEntityListener.class) +public abstract class BaseEntity { + + @CreatedDate + @Column(name = "created_at", updatable = false) + private LocalDateTime createdAt; + @CreatedBy + @Column(updatable = false) + private String createdBy; + + @LastModifiedDate + @Column(name = "updated_at", insertable = false) + private LocalDateTime updatedAt; + @LastModifiedBy + @Column(insertable = false) + private String updatedBy; + +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/model/CartItem.java b/src/main/java/com/manir/springbootecommercerestapi/model/CartItem.java index 70155da..5a1c4ea 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/model/CartItem.java +++ b/src/main/java/com/manir/springbootecommercerestapi/model/CartItem.java @@ -11,7 +11,7 @@ @Data @Entity @Table(name = "cart_item") -public class CartItem { +public class CartItem extends BaseEntity{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; diff --git a/src/main/java/com/manir/springbootecommercerestapi/model/Category.java b/src/main/java/com/manir/springbootecommercerestapi/model/Category.java index 6d4e01c..3862154 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/model/Category.java +++ b/src/main/java/com/manir/springbootecommercerestapi/model/Category.java @@ -14,7 +14,7 @@ @Entity @Table(name = "categories") @JsonIgnoreProperties(value = {"children"}) -public class Category { +public class Category extends BaseEntity{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/src/main/java/com/manir/springbootecommercerestapi/model/Comment.java b/src/main/java/com/manir/springbootecommercerestapi/model/Comment.java index 986eaa7..cd69ca0 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/model/Comment.java +++ b/src/main/java/com/manir/springbootecommercerestapi/model/Comment.java @@ -9,7 +9,7 @@ @Getter @Entity @Table(name = "product_comments") -public class Comment { +public class Comment extends BaseEntity{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @@ -23,4 +23,9 @@ public class Comment { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "product_id") private Product product; + + //relation with user + @ManyToOne() + @JoinColumn(name = "customer_id") + private User customer; } diff --git a/src/main/java/com/manir/springbootecommercerestapi/model/ImageData.java b/src/main/java/com/manir/springbootecommercerestapi/model/ImageData.java index 2a76534..45b3d3d 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/model/ImageData.java +++ b/src/main/java/com/manir/springbootecommercerestapi/model/ImageData.java @@ -10,7 +10,7 @@ @NoArgsConstructor @Entity @Table(name = "product_image_gallery") -public class ImageData { +public class ImageData extends BaseEntity{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; diff --git a/src/main/java/com/manir/springbootecommercerestapi/model/Order.java b/src/main/java/com/manir/springbootecommercerestapi/model/Order.java index 73e9f68..189875c 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/model/Order.java +++ b/src/main/java/com/manir/springbootecommercerestapi/model/Order.java @@ -11,7 +11,7 @@ @Setter @Entity @Table(name = "orders") -public class Order { +public class Order extends BaseEntity{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; diff --git a/src/main/java/com/manir/springbootecommercerestapi/model/OrderProducts.java b/src/main/java/com/manir/springbootecommercerestapi/model/OrderProducts.java index b9362c5..084ea70 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/model/OrderProducts.java +++ b/src/main/java/com/manir/springbootecommercerestapi/model/OrderProducts.java @@ -11,7 +11,7 @@ @Data @Entity @Table(name = "order_products") -public class OrderProducts { +public class OrderProducts extends BaseEntity{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; diff --git a/src/main/java/com/manir/springbootecommercerestapi/model/Product.java b/src/main/java/com/manir/springbootecommercerestapi/model/Product.java index 78c7f3b..1333432 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/model/Product.java +++ b/src/main/java/com/manir/springbootecommercerestapi/model/Product.java @@ -12,7 +12,7 @@ @Setter @Entity @Table(name = "products") -public class Product { +public class Product extends BaseEntity{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; diff --git a/src/main/java/com/manir/springbootecommercerestapi/model/Role.java b/src/main/java/com/manir/springbootecommercerestapi/model/Role.java index 3ad1a0e..4f792f4 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/model/Role.java +++ b/src/main/java/com/manir/springbootecommercerestapi/model/Role.java @@ -7,7 +7,7 @@ @Data @Entity @Table(name = "roles") -public class Role { +public class Role extends BaseEntity{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/src/main/java/com/manir/springbootecommercerestapi/model/User.java b/src/main/java/com/manir/springbootecommercerestapi/model/User.java index edc66b9..dcda1f3 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/model/User.java +++ b/src/main/java/com/manir/springbootecommercerestapi/model/User.java @@ -13,7 +13,7 @@ @Table(name = "users", uniqueConstraints = {@UniqueConstraint(columnNames = {"userName"}), @UniqueConstraint(columnNames = {"email"}) }) -public class User { +public class User extends BaseEntity{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @@ -46,4 +46,10 @@ public class User { fetch = FetchType.LAZY, orphanRemoval = true, mappedBy = "customer") private Set<OrderProducts> orderProducts; + + //relation with comment or review + @OneToMany(cascade = CascadeType.ALL, + fetch = FetchType.LAZY, orphanRemoval = true, + mappedBy = "customer") + private Set<Comment> comments; } diff --git a/src/main/java/com/manir/springbootecommercerestapi/repository/CommentRepository.java b/src/main/java/com/manir/springbootecommercerestapi/repository/CommentRepository.java index 74fb923..8fa17c5 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/repository/CommentRepository.java +++ b/src/main/java/com/manir/springbootecommercerestapi/repository/CommentRepository.java @@ -1,10 +1,12 @@ package com.manir.springbootecommercerestapi.repository; import com.manir.springbootecommercerestapi.model.Comment; +import com.manir.springbootecommercerestapi.model.User; import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; public interface CommentRepository extends JpaRepository<Comment, Long> { List<Comment> findByProductId(Long productId); + List<Comment> findByCustomer(User customer); } diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/CommentService.java b/src/main/java/com/manir/springbootecommercerestapi/service/CommentService.java index 1741fed..575ad74 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/service/CommentService.java +++ b/src/main/java/com/manir/springbootecommercerestapi/service/CommentService.java @@ -2,13 +2,15 @@ import com.manir.springbootecommercerestapi.dto.CommentDto; +import com.manir.springbootecommercerestapi.model.User; import java.util.List; public interface CommentService { - CommentDto createComment(Long productId, CommentDto commentDto); + CommentDto createComment(User customer, Long productId, CommentDto commentDto); + List<CommentDto> findCommentByCustomer(User customer); List<CommentDto> getAllComments(); List<CommentDto> getAllCommentsByProductId(Long productId); CommentDto getCommentById(Long productId, Long commentId); diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/CommentServiceImpl.java b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/CommentServiceImpl.java index fcbb875..f3ade8d 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/CommentServiceImpl.java +++ b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/CommentServiceImpl.java @@ -3,10 +3,12 @@ import com.manir.springbootecommercerestapi.dto.CommentDto; import com.manir.springbootecommercerestapi.exception.EcommerceApiException; import com.manir.springbootecommercerestapi.exception.ResourceNotFoundException; +import com.manir.springbootecommercerestapi.model.User; import com.manir.springbootecommercerestapi.repository.CommentRepository; import com.manir.springbootecommercerestapi.repository.ProductRepository; import com.manir.springbootecommercerestapi.model.Comment; import com.manir.springbootecommercerestapi.model.Product; +import com.manir.springbootecommercerestapi.repository.UserRepository; import com.manir.springbootecommercerestapi.service.CommentService; import org.modelmapper.ModelMapper; import org.springframework.http.HttpStatus; @@ -25,15 +27,18 @@ public class CommentServiceImpl implements CommentService { private CommentRepository commentRepository; @Resource private ProductRepository productRepository; + @Resource + private UserRepository userRepository; @Override - public CommentDto createComment(Long productId, CommentDto commentDto) { - + public CommentDto createComment(User customer, Long productId, CommentDto commentDto) { + User user = findCustomerById(customer.getId()); Product product = findProductById(productId); //convert to entity Comment comment = mapToEntity(commentDto); //save to db comment.setProduct(product); + comment.setCustomer(user); Comment createdComment = commentRepository.save(comment); //convert to dto CommentDto responseComment = mapToDto(createdComment); @@ -41,6 +46,18 @@ public CommentDto createComment(Long productId, CommentDto commentDto) { return responseComment; } + @Override + public List<CommentDto> findCommentByCustomer(User customer) { + List<Comment> comments = commentRepository.findByCustomer(customer); + if (comments.size() == 0){ + throw new EcommerceApiException("User has no comment or review", HttpStatus.BAD_REQUEST); + } + List<CommentDto> commentDtoList = comments.stream() + .map(comment -> mapToDto(comment)) + .collect(Collectors.toList()); + return commentDtoList; + } + @Override public List<CommentDto> getAllComments() { List<Comment> comments = commentRepository.findAll(); @@ -120,4 +137,8 @@ private Comment findCommentById(Long commentId){ return comment; } + private User findCustomerById(Long customerId){ + User customer = userRepository.findById(customerId).orElseThrow(()->new ResourceNotFoundException("Customer", customerId)); + return customer; + } } diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/OrderServiceImpl.java b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/OrderServiceImpl.java index 40527be..72a6138 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/OrderServiceImpl.java +++ b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/OrderServiceImpl.java @@ -41,6 +41,7 @@ public class OrderServiceImpl implements OrderService { @Transactional public void placeOrder(User customer) { CartItemResponse cartItemDto = shoppingCartService.findByCustomer(customer); + //set order fields OrderDto orderDto = setFields(cartItemDto, customer); //save order to the db OrderDto savedOrder = saveOrder(orderDto); From 942ccfff6714bb964d1d1ad4aaed07bf3894ff6a Mon Sep 17 00:00:00 2001 From: manirDev <mhtnourmhtmjr@gmail.com> Date: Thu, 17 Nov 2022 16:13:26 +0300 Subject: [PATCH 12/16] Setting, Contact profile are implemented --- .../config/SecurityConfig.java | 3 +- .../controller/ContactController.java | 33 ++++++++ .../controller/ProductController.java | 6 ++ .../controller/SettingController.java | 41 ++++++++++ .../dto/ContactDto.java | 15 ++++ .../dto/FaqDto.java | 11 +++ .../dto/ProfileDto.java | 11 +++ .../dto/SettingDto.java | 27 +++++++ .../model/Contact.java | 26 +++++++ .../springbootecommercerestapi/model/Faq.java | 22 ++++++ .../model/Profile.java | 27 +++++++ .../model/Setting.java | 38 ++++++++++ .../model/User.java | 4 + .../repository/ContactRepository.java | 7 ++ .../repository/ProductRepository.java | 12 +++ .../repository/SettingRepository.java | 7 ++ .../service/ContactService.java | 11 +++ .../service/Impl/ContactServiceImpl.java | 57 ++++++++++++++ .../service/Impl/ProductServiceImpl.java | 14 ++++ .../service/Impl/SettingServiceImpl.java | 75 +++++++++++++++++++ .../service/ProductService.java | 2 + .../service/SettingService.java | 8 ++ .../utils/RequestClientIP.java | 41 ++++++++++ 23 files changed, 497 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/manir/springbootecommercerestapi/controller/ContactController.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/controller/SettingController.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/dto/ContactDto.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/dto/FaqDto.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/dto/ProfileDto.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/dto/SettingDto.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/model/Contact.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/model/Faq.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/model/Profile.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/model/Setting.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/repository/ContactRepository.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/repository/SettingRepository.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/service/ContactService.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/service/Impl/ContactServiceImpl.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/service/Impl/SettingServiceImpl.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/service/SettingService.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/utils/RequestClientIP.java diff --git a/src/main/java/com/manir/springbootecommercerestapi/config/SecurityConfig.java b/src/main/java/com/manir/springbootecommercerestapi/config/SecurityConfig.java index cb723b4..e2a691e 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/config/SecurityConfig.java +++ b/src/main/java/com/manir/springbootecommercerestapi/config/SecurityConfig.java @@ -48,7 +48,8 @@ protected void configure(HttpSecurity http) throws Exception { //to permit all get request and secure post put and delete methods .antMatchers(HttpMethod.GET, "/api/**").permitAll() //authorize singIn and signUp - .antMatchers("/api/v1/auth/**").permitAll() + .antMatchers("/api/v*/auth/**").permitAll() + .antMatchers(HttpMethod.POST, "/api/v*/contact/**").permitAll() .anyRequest() .authenticated(); diff --git a/src/main/java/com/manir/springbootecommercerestapi/controller/ContactController.java b/src/main/java/com/manir/springbootecommercerestapi/controller/ContactController.java new file mode 100644 index 0000000..d440aed --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/controller/ContactController.java @@ -0,0 +1,33 @@ +package com.manir.springbootecommercerestapi.controller; + +import com.manir.springbootecommercerestapi.dto.ContactDto; +import com.manir.springbootecommercerestapi.service.ContactService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import java.util.List; + +@RestController +@RequestMapping(value = "api/v1/contact") +public class ContactController { + @Autowired + private ContactService contactService; + + @PostMapping("/sendMessage") + public ResponseEntity<ContactDto> sendMessage(@RequestBody ContactDto contactDto, + HttpServletRequest request){ + ContactDto responseMessage = contactService.sendMessage(contactDto, request); + return new ResponseEntity<>(responseMessage, HttpStatus.CREATED); + } + + //get messages api + @PreAuthorize("hasRole('ADMIN')") + @GetMapping("/allMessages") + public List<ContactDto> getAllMessages(){ + return contactService.getMessages(); + } +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/controller/ProductController.java b/src/main/java/com/manir/springbootecommercerestapi/controller/ProductController.java index d5e2605..b34e2ed 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/controller/ProductController.java +++ b/src/main/java/com/manir/springbootecommercerestapi/controller/ProductController.java @@ -77,4 +77,10 @@ public ResponseEntity<String> deleteProduct(@PathVariable Long productId){ return new ResponseEntity<>("Product with id: "+ productId +" is deleted successfully:)", HttpStatus.OK); } + //search product api + @GetMapping("/search") + public List<ProductDto> searchProduct(@RequestParam(value = "query") String query){ + return productService.searchProduct(query); + } + } diff --git a/src/main/java/com/manir/springbootecommercerestapi/controller/SettingController.java b/src/main/java/com/manir/springbootecommercerestapi/controller/SettingController.java new file mode 100644 index 0000000..053edbd --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/controller/SettingController.java @@ -0,0 +1,41 @@ +package com.manir.springbootecommercerestapi.controller; + +import com.manir.springbootecommercerestapi.dto.SettingDto; +import com.manir.springbootecommercerestapi.model.Setting; +import com.manir.springbootecommercerestapi.repository.SettingRepository; +import com.manir.springbootecommercerestapi.service.SettingService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import java.util.Optional; + +@RestController +@RequestMapping(value = "api/v1/setting") +public class SettingController { + @Autowired + private SettingService settingService; + @Autowired + private SettingRepository settingRepository; + + //post first setting api + @PreAuthorize("hasRole('ADMIN')") + @PostMapping("/createSetting") + public ResponseEntity<SettingDto> createSetting(@RequestBody SettingDto settingDto){ + SettingDto createdSetting = settingService.addSettingFirstTime(settingDto); + return new ResponseEntity<>(createdSetting, HttpStatus.CREATED); + } + + //edit existing setting api + @PreAuthorize("hasRole('ADMIN')") + @PutMapping("/editSetting") + public ResponseEntity<SettingDto> editSetting(@RequestBody SettingDto settingDto){ + Optional<Setting> existingSetting = settingRepository.findAll().stream().findFirst(); + SettingDto editedSetting = settingService.updateSetting(settingDto, existingSetting.get().getId()); + + return ResponseEntity.ok(editedSetting); + } + +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/dto/ContactDto.java b/src/main/java/com/manir/springbootecommercerestapi/dto/ContactDto.java new file mode 100644 index 0000000..338891d --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/dto/ContactDto.java @@ -0,0 +1,15 @@ +package com.manir.springbootecommercerestapi.dto; + +import lombok.Data; + +@Data +public class ContactDto { + private Long id; + private String name; + private String email; + private String phone; + private String subject; + private String message; + private String ipAddress; + private String status; +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/dto/FaqDto.java b/src/main/java/com/manir/springbootecommercerestapi/dto/FaqDto.java new file mode 100644 index 0000000..32586c8 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/dto/FaqDto.java @@ -0,0 +1,11 @@ +package com.manir.springbootecommercerestapi.dto; + +import lombok.Data; + +@Data +public class FaqDto { + private Long id; + private String question; + private String answer; + private String status; +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/dto/ProfileDto.java b/src/main/java/com/manir/springbootecommercerestapi/dto/ProfileDto.java new file mode 100644 index 0000000..ae0c350 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/dto/ProfileDto.java @@ -0,0 +1,11 @@ +package com.manir.springbootecommercerestapi.dto; + +import lombok.Data; + +@Data +public class ProfileDto { + private Long id; + private String image; + private String address; + private String phone; +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/dto/SettingDto.java b/src/main/java/com/manir/springbootecommercerestapi/dto/SettingDto.java new file mode 100644 index 0000000..676cbc7 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/dto/SettingDto.java @@ -0,0 +1,27 @@ +package com.manir.springbootecommercerestapi.dto; + +import lombok.Data; + +@Data +public class SettingDto { + private Long id; + private String title; + private String keywords; + private String description; + private String company; + private String address; + private String phone; + private String fax; + private String email; + private String smtpServer; + private String smtpEmail; + private String smtpPassword; + private Integer smtpPort; + private String facebook; + private String instagram; + private String twitter; + private String aboutUs; + private String contact; + private String reference; + private String status; +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/model/Contact.java b/src/main/java/com/manir/springbootecommercerestapi/model/Contact.java new file mode 100644 index 0000000..e321566 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/model/Contact.java @@ -0,0 +1,26 @@ +package com.manir.springbootecommercerestapi.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.*; + +@AllArgsConstructor +@NoArgsConstructor +@Data +@Entity +@Table(name = "contact") +public class Contact extends BaseEntity{ + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + private String name; + private String email; + private String phone; + private String subject; + private String message; + private String ipAddress; + private String status; + +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/model/Faq.java b/src/main/java/com/manir/springbootecommercerestapi/model/Faq.java new file mode 100644 index 0000000..369f411 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/model/Faq.java @@ -0,0 +1,22 @@ +package com.manir.springbootecommercerestapi.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.*; + +@AllArgsConstructor +@NoArgsConstructor +@Data +@Entity +@Table(name = "faqs") +public class Faq extends BaseEntity{ + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + private String question; + private String answer; + private String status; + +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/model/Profile.java b/src/main/java/com/manir/springbootecommercerestapi/model/Profile.java new file mode 100644 index 0000000..da592e4 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/model/Profile.java @@ -0,0 +1,27 @@ +package com.manir.springbootecommercerestapi.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.*; + +@AllArgsConstructor +@NoArgsConstructor +@Data +@Entity +@Table(name = "user_profile") +public class Profile extends BaseEntity{ + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + private String image; + private String address; + private String phone; + + //relation with user + @OneToOne(cascade = CascadeType.ALL) + @JoinColumn(name = "user_id", referencedColumnName = "id") + private User user; + +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/model/Setting.java b/src/main/java/com/manir/springbootecommercerestapi/model/Setting.java new file mode 100644 index 0000000..ea839f9 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/model/Setting.java @@ -0,0 +1,38 @@ +package com.manir.springbootecommercerestapi.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.*; + +@AllArgsConstructor +@NoArgsConstructor +@Data +@Entity +@Table(name = "settings") +public class Setting extends BaseEntity{ + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + private String title; + private String keywords; + private String description; + private String company; + private String address; + private String phone; + private String fax; + private String email; + private String smtpServer; + private String smtpEmail; + private String smtpPassword; + private Integer smtpPort; + private String facebook; + private String instagram; + private String twitter; + private String aboutUs; + private String contact; + private String reference; + private String status; + +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/model/User.java b/src/main/java/com/manir/springbootecommercerestapi/model/User.java index dcda1f3..5ca2a50 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/model/User.java +++ b/src/main/java/com/manir/springbootecommercerestapi/model/User.java @@ -52,4 +52,8 @@ public class User extends BaseEntity{ fetch = FetchType.LAZY, orphanRemoval = true, mappedBy = "customer") private Set<Comment> comments; + + //relation with profile + @OneToOne(mappedBy = "user") + private Profile user_profile; } diff --git a/src/main/java/com/manir/springbootecommercerestapi/repository/ContactRepository.java b/src/main/java/com/manir/springbootecommercerestapi/repository/ContactRepository.java new file mode 100644 index 0000000..3e2911a --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/repository/ContactRepository.java @@ -0,0 +1,7 @@ +package com.manir.springbootecommercerestapi.repository; + +import com.manir.springbootecommercerestapi.model.Contact; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ContactRepository extends JpaRepository<Contact, Long> { +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/repository/ProductRepository.java b/src/main/java/com/manir/springbootecommercerestapi/repository/ProductRepository.java index 2e29f5b..419dd56 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/repository/ProductRepository.java +++ b/src/main/java/com/manir/springbootecommercerestapi/repository/ProductRepository.java @@ -2,7 +2,19 @@ import com.manir.springbootecommercerestapi.model.Product; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +import java.util.List; public interface ProductRepository extends JpaRepository<Product, Long> { + @Query( + "SELECT p FROM Product p WHERE " + + "p.title LIKE CONCAT('%', :query, '%') " + + "or p.description LIKE CONCAT('%', :query, '%')" + + "or p.keywords LIKE CONCAT('%', :query, '%')" + + "or p.detail LIKE CONCAT('%', :query, '%')" + ) + List<Product> searchProduct(String query); + } diff --git a/src/main/java/com/manir/springbootecommercerestapi/repository/SettingRepository.java b/src/main/java/com/manir/springbootecommercerestapi/repository/SettingRepository.java new file mode 100644 index 0000000..94b6cb4 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/repository/SettingRepository.java @@ -0,0 +1,7 @@ +package com.manir.springbootecommercerestapi.repository; + +import com.manir.springbootecommercerestapi.model.Setting; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface SettingRepository extends JpaRepository<Setting, Long> { +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/ContactService.java b/src/main/java/com/manir/springbootecommercerestapi/service/ContactService.java new file mode 100644 index 0000000..65223b0 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/service/ContactService.java @@ -0,0 +1,11 @@ +package com.manir.springbootecommercerestapi.service; + +import com.manir.springbootecommercerestapi.dto.ContactDto; + +import javax.servlet.http.HttpServletRequest; +import java.util.List; + +public interface ContactService { + ContactDto sendMessage(ContactDto contactDto, HttpServletRequest request); + List<ContactDto> getMessages(); +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/ContactServiceImpl.java b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/ContactServiceImpl.java new file mode 100644 index 0000000..db39d0a --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/ContactServiceImpl.java @@ -0,0 +1,57 @@ +package com.manir.springbootecommercerestapi.service.Impl; + +import com.manir.springbootecommercerestapi.dto.ContactDto; +import com.manir.springbootecommercerestapi.model.Contact; +import com.manir.springbootecommercerestapi.repository.ContactRepository; +import com.manir.springbootecommercerestapi.service.ContactService; +import com.manir.springbootecommercerestapi.utils.RequestClientIP; +import lombok.AllArgsConstructor; +import org.modelmapper.ModelMapper; +import org.springframework.stereotype.Service; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import java.util.List; +import java.util.stream.Collectors; + +@Service +@AllArgsConstructor +public class ContactServiceImpl implements ContactService { + + @Resource(name = "contactRepository") + private final ContactRepository contactRepository; + @Resource(name = "modelMapper") + private final ModelMapper modelMapper; + @Override + public ContactDto sendMessage(ContactDto contactDto, HttpServletRequest request) { + + Contact contact = mapToEntity(contactDto); + String ipAddress = RequestClientIP.getClientIpAddress(request); + contact.setIpAddress(ipAddress); + Contact createdMessage = contactRepository.save(contact); + + return mapToDto(createdMessage); + } + + @Override + public List<ContactDto> getMessages() { + List<Contact> messages = contactRepository.findAll(); + + return messages.stream() + .map(message -> mapToDto(message)) + .collect(Collectors.toList()); + } + + //map to entity + private Contact mapToEntity(ContactDto contactDto){ + Contact contact = modelMapper.map(contactDto, Contact.class); + return contact; + } + //map to dto + private ContactDto mapToDto(Contact contact){ + ContactDto contactDto = modelMapper.map(contact, ContactDto.class); + return contactDto; + } +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/ProductServiceImpl.java b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/ProductServiceImpl.java index 2f4fd98..9b3dcb6 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/ProductServiceImpl.java +++ b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/ProductServiceImpl.java @@ -1,6 +1,7 @@ package com.manir.springbootecommercerestapi.service.Impl; import com.manir.springbootecommercerestapi.dto.ProductDto; +import com.manir.springbootecommercerestapi.exception.EcommerceApiException; import com.manir.springbootecommercerestapi.exception.ResourceNotFoundException; import com.manir.springbootecommercerestapi.repository.CategoryRepository; import com.manir.springbootecommercerestapi.repository.ProductRepository; @@ -17,6 +18,7 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; +import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import org.springframework.web.multipart.MultipartFile; @@ -131,6 +133,18 @@ public ProductDto saveProductByCategoryId(Long categoryId, ProductDto productDto return responseProduct; } + @Override + public List<ProductDto> searchProduct(String query) { + List<Product> products = productRepository.searchProduct(query); + if (products.size() == 0){ + throw new EcommerceApiException("No product is found", HttpStatus.BAD_REQUEST); + } + List<ProductDto> productDtoList = products.stream() + .map(product -> mapToDto(product)) + .collect(Collectors.toList()); + return productDtoList; + } + //upload image private String uploadProductImage(MultipartFile file){ ProductDto productDto = new ProductDto(); diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/SettingServiceImpl.java b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/SettingServiceImpl.java new file mode 100644 index 0000000..b697560 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/SettingServiceImpl.java @@ -0,0 +1,75 @@ +package com.manir.springbootecommercerestapi.service.Impl; + +import com.manir.springbootecommercerestapi.dto.SettingDto; +import com.manir.springbootecommercerestapi.exception.EcommerceApiException; +import com.manir.springbootecommercerestapi.exception.ResourceNotFoundException; +import com.manir.springbootecommercerestapi.model.Setting; +import com.manir.springbootecommercerestapi.repository.SettingRepository; +import com.manir.springbootecommercerestapi.service.SettingService; +import lombok.AllArgsConstructor; +import org.modelmapper.ModelMapper; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.Optional; + +@Service +@AllArgsConstructor +public class SettingServiceImpl implements SettingService { + @Resource(name = "settingRepository") + private final SettingRepository settingRepository; + @Resource(name = "modelMapper") + private final ModelMapper modelMapper; + + @Override + public SettingDto addSettingFirstTime(SettingDto settingDto) { + + Optional<Setting> setting = settingRepository.findAll().stream().findFirst(); + if (!setting.isPresent()){ + Setting firstSetting = mapToEntity(settingDto); + Setting saveSetting = settingRepository.save(firstSetting); + return mapToDto(saveSetting); + }else { + throw new EcommerceApiException("Setting already exists, please edit it only", HttpStatus.BAD_REQUEST); + } + } + + @Override + public SettingDto updateSetting(SettingDto settingDto, Long id) { + Setting setting = settingRepository.findById(id).orElseThrow(() -> new ResourceNotFoundException("Setting", id)); + setting.setTitle(settingDto.getTitle()); + setting.setKeywords(settingDto.getKeywords()); + setting.setDescription(settingDto.getDescription()); + setting.setCompany(settingDto.getCompany()); + setting.setAddress(settingDto.getAddress()); + setting.setPhone(settingDto.getPhone()); + setting.setFax(settingDto.getFax()); + setting.setEmail(settingDto.getEmail()); + setting.setSmtpServer(settingDto.getSmtpServer()); + setting.setSmtpEmail(settingDto.getSmtpEmail()); + setting.setSmtpPassword(settingDto.getSmtpPassword()); + setting.setSmtpPort(settingDto.getSmtpPort()); + setting.setFacebook(settingDto.getFacebook()); + setting.setInstagram(settingDto.getInstagram()); + setting.setTwitter(settingDto.getTwitter()); + setting.setAboutUs(settingDto.getAboutUs()); + setting.setContact(settingDto.getContact()); + setting.setContact(settingDto.getReference()); + //save setting changes + Setting editedSetting = settingRepository.save(setting); + + return mapToDto(editedSetting); + } + + //map to dto + private SettingDto mapToDto(Setting setting){ + SettingDto settingDto = modelMapper.map(setting, SettingDto.class); + return settingDto; + } + //map to entity + private Setting mapToEntity(SettingDto settingDto){ + Setting setting = modelMapper.map(settingDto, Setting.class); + return setting; + } +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/ProductService.java b/src/main/java/com/manir/springbootecommercerestapi/service/ProductService.java index 9853f05..803e650 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/service/ProductService.java +++ b/src/main/java/com/manir/springbootecommercerestapi/service/ProductService.java @@ -15,4 +15,6 @@ public interface ProductService { void deleteProduct(Long productId); ProductDto saveProductByCategoryId(Long categoryId, ProductDto productDto); + + List<ProductDto> searchProduct(String query); } diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/SettingService.java b/src/main/java/com/manir/springbootecommercerestapi/service/SettingService.java new file mode 100644 index 0000000..05c010e --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/service/SettingService.java @@ -0,0 +1,8 @@ +package com.manir.springbootecommercerestapi.service; + +import com.manir.springbootecommercerestapi.dto.SettingDto; + +public interface SettingService { + SettingDto addSettingFirstTime(SettingDto settingDto); + SettingDto updateSetting(SettingDto settingDto, Long id); +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/utils/RequestClientIP.java b/src/main/java/com/manir/springbootecommercerestapi/utils/RequestClientIP.java new file mode 100644 index 0000000..5920839 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/utils/RequestClientIP.java @@ -0,0 +1,41 @@ +package com.manir.springbootecommercerestapi.utils; + +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; + +public class RequestClientIP { + + private static final String[] IP_HEADER_CANDIDATES = { + "X-Forwarded-For", + "Proxy-Client-IP", + "WL-Proxy-Client-IP", + "HTTP_X_FORWARDED_FOR", + "HTTP_X_FORWARDED", + "HTTP_X_CLUSTER_CLIENT_IP", + "HTTP_CLIENT_IP", + "HTTP_FORWARDED_FOR", + "HTTP_FORWARDED", + "HTTP_VIA", + "REMOTE_ADDR" + }; + + public static String getClientIpAddress(HttpServletRequest request) { + + if (RequestContextHolder.getRequestAttributes() == null) { + return "0.0.0.0"; + } + + request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + for (String header: IP_HEADER_CANDIDATES) { + String ipList = request.getHeader(header); + if (ipList != null && ipList.length() != 0 && !"unknown".equalsIgnoreCase(ipList)) { + String ip = ipList.split(",")[0]; + return ip; + } + } + + return request.getRemoteAddr(); + } +} From 36847a17309793b5e99a9c2306f86047000268f6 Mon Sep 17 00:00:00 2001 From: manirDev <mhtnourmhtmjr@gmail.com> Date: Thu, 17 Nov 2022 16:56:56 +0300 Subject: [PATCH 13/16] Faq CRUD is done. --- .../controller/FaqController.java | 57 ++++++++++++++++ .../repository/FaqRepository.java | 7 ++ .../service/FaqService.java | 13 ++++ .../service/Impl/FaqServiceImpl.java | 68 +++++++++++++++++++ 4 files changed, 145 insertions(+) create mode 100644 src/main/java/com/manir/springbootecommercerestapi/controller/FaqController.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/repository/FaqRepository.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/service/FaqService.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/service/Impl/FaqServiceImpl.java diff --git a/src/main/java/com/manir/springbootecommercerestapi/controller/FaqController.java b/src/main/java/com/manir/springbootecommercerestapi/controller/FaqController.java new file mode 100644 index 0000000..4c3ea0a --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/controller/FaqController.java @@ -0,0 +1,57 @@ +package com.manir.springbootecommercerestapi.controller; + +import com.manir.springbootecommercerestapi.dto.FaqDto; +import com.manir.springbootecommercerestapi.service.FaqService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("api/v1/faq") +public class FaqController { + @Autowired + private FaqService faqService; + + //add faq api + @PreAuthorize("hasRole('ADMIN')") + @PostMapping("/addFaq") + public ResponseEntity<FaqDto> addFaq(@RequestBody FaqDto faqDto){ + FaqDto addedFaq = faqService.addFaq(faqDto); + return new ResponseEntity<>(addedFaq, HttpStatus.CREATED); + } + //list all faqs api + @PreAuthorize("hasRole('ADMIN')") + @GetMapping("/getAllFaqs") + public List<FaqDto> listAllFaqs(){ + List<FaqDto> faqs = faqService.listAllFaqs(); + return faqs; + } + + //get faq by id api + @PreAuthorize("hasRole('ADMIN')") + @GetMapping("/{id}") + public ResponseEntity<FaqDto> getFaqById(@PathVariable Long id){ + FaqDto faq = faqService.getFaqById(id); + return new ResponseEntity<>(faq, HttpStatus.OK); + } + + //update faq api + @PreAuthorize("hasRole('ADMIN')") + @PutMapping("/updateFaq/{id}") + public ResponseEntity<FaqDto> updateFaq(@RequestBody FaqDto faqDto, @PathVariable Long id){ + FaqDto updatedFaq = faqService.updateFaq(faqDto, id); + return new ResponseEntity<>(updatedFaq, HttpStatus.OK); + } + + //delete faq api + @PreAuthorize("hasRole('ADMIN')") + @DeleteMapping("/deleteFaq/{id}") + public ResponseEntity<String> deleteFaq(@PathVariable Long id){ + faqService.deleteFaq(id); + return new ResponseEntity<>("Faq with id: "+id+ " is deleted successfully", HttpStatus.OK); + } +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/repository/FaqRepository.java b/src/main/java/com/manir/springbootecommercerestapi/repository/FaqRepository.java new file mode 100644 index 0000000..3fc9ed1 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/repository/FaqRepository.java @@ -0,0 +1,7 @@ +package com.manir.springbootecommercerestapi.repository; + +import com.manir.springbootecommercerestapi.model.Faq; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface FaqRepository extends JpaRepository<Faq, Long> { +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/FaqService.java b/src/main/java/com/manir/springbootecommercerestapi/service/FaqService.java new file mode 100644 index 0000000..acfe24e --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/service/FaqService.java @@ -0,0 +1,13 @@ +package com.manir.springbootecommercerestapi.service; + +import com.manir.springbootecommercerestapi.dto.FaqDto; + +import java.util.List; + +public interface FaqService { + FaqDto addFaq(FaqDto faqDto); + List<FaqDto> listAllFaqs(); + FaqDto getFaqById(Long id); + FaqDto updateFaq(FaqDto faqDto, Long id); + void deleteFaq(Long id); +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/FaqServiceImpl.java b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/FaqServiceImpl.java new file mode 100644 index 0000000..d8fba99 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/FaqServiceImpl.java @@ -0,0 +1,68 @@ +package com.manir.springbootecommercerestapi.service.Impl; + +import com.manir.springbootecommercerestapi.dto.FaqDto; +import com.manir.springbootecommercerestapi.exception.ResourceNotFoundException; +import com.manir.springbootecommercerestapi.model.Faq; +import com.manir.springbootecommercerestapi.repository.FaqRepository; +import com.manir.springbootecommercerestapi.service.FaqService; +import lombok.AllArgsConstructor; +import org.modelmapper.ModelMapper; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; +import java.util.stream.Collectors; + +@Service +@AllArgsConstructor +public class FaqServiceImpl implements FaqService { + @Resource(name = "faqRepository") + private final FaqRepository faqRepository; + @Resource(name = "modelMapper") + private final ModelMapper modelMapper; + + @Override + public FaqDto addFaq(FaqDto faqDto) { + Faq faq = mapToEntity(faqDto); + Faq addedFaq = faqRepository.save(faq); + + return mapToDto(addedFaq); + } + + @Override + public List<FaqDto> listAllFaqs() { + List<Faq> faqs = faqRepository.findAll(); + return faqs.stream().map(faq -> mapToDto(faq)).collect(Collectors.toList()); + } + + @Override + public FaqDto getFaqById(Long id) { + Faq faq = faqRepository.findById(id).orElseThrow(()->new ResourceNotFoundException("Faq", id)); + return mapToDto(faq); + } + + @Override + public FaqDto updateFaq(FaqDto faqDto, Long id) { + Faq faq = faqRepository.findById(id).orElseThrow(()->new ResourceNotFoundException("Faq", id)); + faq.setQuestion(faqDto.getQuestion()); + faq.setAnswer(faqDto.getAnswer()); + Faq updatedFaq = faqRepository.save(faq); + return mapToDto(updatedFaq); + } + + @Override + public void deleteFaq(Long id) { + Faq faq = faqRepository.findById(id).orElseThrow(()->new ResourceNotFoundException("Faq", id)); + faqRepository.delete(faq); + } + + private FaqDto mapToDto(Faq faq){ + FaqDto faqDto = modelMapper.map(faq, FaqDto.class); + return faqDto; + } + //map to entity + private Faq mapToEntity(FaqDto faqDto){ + Faq faq = modelMapper.map(faqDto, Faq.class); + return faq; + } +} From 57849c8a4d0080d2e3eef6dd1e7bb0d56ceab884 Mon Sep 17 00:00:00 2001 From: manirDev <mhtnourmhtmjr@gmail.com> Date: Fri, 18 Nov 2022 15:16:57 +0300 Subject: [PATCH 14/16] Code Refactor --- .../springbootecommercerestapi/dto/FaqDto.java | 3 ++- .../service/CommonService.java | 6 ++++++ .../service/Impl/CommonServiceImpl.java | 17 +++++++++++++++++ .../service/Impl/FaqServiceImpl.java | 3 +++ 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/manir/springbootecommercerestapi/dto/FaqDto.java b/src/main/java/com/manir/springbootecommercerestapi/dto/FaqDto.java index 32586c8..a476603 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/dto/FaqDto.java +++ b/src/main/java/com/manir/springbootecommercerestapi/dto/FaqDto.java @@ -1,9 +1,10 @@ package com.manir.springbootecommercerestapi.dto; +import com.manir.springbootecommercerestapi.model.BaseEntity; import lombok.Data; @Data -public class FaqDto { +public class FaqDto extends BaseEntity { private Long id; private String question; private String answer; diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/CommonService.java b/src/main/java/com/manir/springbootecommercerestapi/service/CommonService.java index e2156a2..f973fb0 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/service/CommonService.java +++ b/src/main/java/com/manir/springbootecommercerestapi/service/CommonService.java @@ -19,4 +19,10 @@ public interface CommonService<T> { //get current authenticated user User getCurrentAuthenticatedUser(Authentication authentication); + + //entity mapper + T mapToEntity(T type); + + //dto mapper + T mapToDto(T type); } diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/CommonServiceImpl.java b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/CommonServiceImpl.java index e8cfb9c..bc633ab 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/CommonServiceImpl.java +++ b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/CommonServiceImpl.java @@ -9,6 +9,7 @@ import com.manir.springbootecommercerestapi.service.CommonService; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.modelmapper.ModelMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.domain.Page; @@ -17,6 +18,7 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; @@ -27,12 +29,15 @@ @Service @Slf4j @AllArgsConstructor +@Component("commonService") public class CommonServiceImpl implements CommonService{ private static Logger logger = LoggerFactory.getLogger(CategoryServiceImpl.class); @Resource(name = "userRepository") private final UserRepository userRepository; + @Resource(name = "modelMapper") + private final ModelMapper modelMapper; @Override public CommonResponse getResponseContent(Page page, List dtoList) { @@ -75,4 +80,16 @@ public User getCurrentAuthenticatedUser(Authentication authentication) { return currentUser; } + + @Override + public Object mapToEntity(Object type) { + Object entityObject = modelMapper.map(type, Object.class); + return entityObject; + } + + @Override + public Object mapToDto(Object type) { + Object dtoObject = modelMapper.map(type, Object.class); + return dtoObject; + } } diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/FaqServiceImpl.java b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/FaqServiceImpl.java index d8fba99..6ea6cb8 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/FaqServiceImpl.java +++ b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/FaqServiceImpl.java @@ -4,6 +4,7 @@ import com.manir.springbootecommercerestapi.exception.ResourceNotFoundException; import com.manir.springbootecommercerestapi.model.Faq; import com.manir.springbootecommercerestapi.repository.FaqRepository; +import com.manir.springbootecommercerestapi.service.CommonService; import com.manir.springbootecommercerestapi.service.FaqService; import lombok.AllArgsConstructor; import org.modelmapper.ModelMapper; @@ -20,6 +21,8 @@ public class FaqServiceImpl implements FaqService { private final FaqRepository faqRepository; @Resource(name = "modelMapper") private final ModelMapper modelMapper; + @Resource(name = "commonService") + private final CommonService commonService; @Override public FaqDto addFaq(FaqDto faqDto) { From e7907878183fff1336bc089ae45f9abd8d64e9e2 Mon Sep 17 00:00:00 2001 From: manirDev <mhtnourmhtmjr@gmail.com> Date: Fri, 18 Nov 2022 17:30:20 +0300 Subject: [PATCH 15/16] ModelMapper code refactor using java generic --- .../service/Impl/FaqServiceImpl.java | 9 ++--- .../service/MapperService.java | 9 +++++ .../service/MapperServiceImpl.java | 36 +++++++++++++++++++ 3 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/manir/springbootecommercerestapi/service/MapperService.java create mode 100644 src/main/java/com/manir/springbootecommercerestapi/service/MapperServiceImpl.java diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/FaqServiceImpl.java b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/FaqServiceImpl.java index 6ea6cb8..567dc11 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/FaqServiceImpl.java +++ b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/FaqServiceImpl.java @@ -6,6 +6,7 @@ import com.manir.springbootecommercerestapi.repository.FaqRepository; import com.manir.springbootecommercerestapi.service.CommonService; import com.manir.springbootecommercerestapi.service.FaqService; +import com.manir.springbootecommercerestapi.service.MapperService; import lombok.AllArgsConstructor; import org.modelmapper.ModelMapper; import org.springframework.stereotype.Service; @@ -21,15 +22,15 @@ public class FaqServiceImpl implements FaqService { private final FaqRepository faqRepository; @Resource(name = "modelMapper") private final ModelMapper modelMapper; - @Resource(name = "commonService") - private final CommonService commonService; + @Resource(name = "mapperService") + private final MapperService<Faq, FaqDto> mapperService; @Override public FaqDto addFaq(FaqDto faqDto) { - Faq faq = mapToEntity(faqDto); + Faq faq = mapperService.mapToEntity(faqDto); Faq addedFaq = faqRepository.save(faq); - return mapToDto(addedFaq); + return mapperService.mapToDto(addedFaq); } @Override diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/MapperService.java b/src/main/java/com/manir/springbootecommercerestapi/service/MapperService.java new file mode 100644 index 0000000..33a4150 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/service/MapperService.java @@ -0,0 +1,9 @@ +package com.manir.springbootecommercerestapi.service; + +public interface MapperService<E, D>{ + //entity mapper + E mapToEntity(D type); + + //dto mapper + D mapToDto(E type); +} diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/MapperServiceImpl.java b/src/main/java/com/manir/springbootecommercerestapi/service/MapperServiceImpl.java new file mode 100644 index 0000000..2eb67f5 --- /dev/null +++ b/src/main/java/com/manir/springbootecommercerestapi/service/MapperServiceImpl.java @@ -0,0 +1,36 @@ +package com.manir.springbootecommercerestapi.service; + +import lombok.AllArgsConstructor; +import org.modelmapper.ModelMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; + +@AllArgsConstructor +@Service +@Component("mapperService") +public class MapperServiceImpl<E, D> implements MapperService<E, D> { + + + @Resource(name = "modelMapper") + private final ModelMapper modelMapper; + @Resource + private final Class<E> entityClass; + @Resource + private final Class<D> dtoClass; + + + @Override + public E mapToEntity(D type) { + E model = modelMapper.map(type, entityClass); + return model; + } + + @Override + public D mapToDto(E type) { + D dto = modelMapper.map(type, dtoClass); + return dto; + } +} From 3b990a9004305917bb42b2b6d378357ffe87079c Mon Sep 17 00:00:00 2001 From: manirDev <mhtnourmhtmjr@gmail.com> Date: Mon, 21 Nov 2022 14:06:53 +0300 Subject: [PATCH 16/16] model mapper refactor --- .../service/Impl/FaqServiceImpl.java | 2 +- .../service/MapperServiceImpl.java | 22 +++++++++++-------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/FaqServiceImpl.java b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/FaqServiceImpl.java index 567dc11..1732722 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/service/Impl/FaqServiceImpl.java +++ b/src/main/java/com/manir/springbootecommercerestapi/service/Impl/FaqServiceImpl.java @@ -36,7 +36,7 @@ public FaqDto addFaq(FaqDto faqDto) { @Override public List<FaqDto> listAllFaqs() { List<Faq> faqs = faqRepository.findAll(); - return faqs.stream().map(faq -> mapToDto(faq)).collect(Collectors.toList()); + return faqs.stream().map(faq -> mapperService.mapToDto(faq)).collect(Collectors.toList()); } @Override diff --git a/src/main/java/com/manir/springbootecommercerestapi/service/MapperServiceImpl.java b/src/main/java/com/manir/springbootecommercerestapi/service/MapperServiceImpl.java index 2eb67f5..9857292 100644 --- a/src/main/java/com/manir/springbootecommercerestapi/service/MapperServiceImpl.java +++ b/src/main/java/com/manir/springbootecommercerestapi/service/MapperServiceImpl.java @@ -1,36 +1,40 @@ package com.manir.springbootecommercerestapi.service; -import lombok.AllArgsConstructor; + +import lombok.Data; import org.modelmapper.ModelMapper; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; import javax.annotation.Resource; -@AllArgsConstructor + @Service @Component("mapperService") +@Data public class MapperServiceImpl<E, D> implements MapperService<E, D> { @Resource(name = "modelMapper") private final ModelMapper modelMapper; - @Resource - private final Class<E> entityClass; - @Resource - private final Class<D> dtoClass; + private Class<E> entityClass; + + private Class<D> dtoClass; + + public MapperServiceImpl(ModelMapper modelMapper) { + this.modelMapper = modelMapper; + } @Override public E mapToEntity(D type) { - E model = modelMapper.map(type, entityClass); + E model = modelMapper.map(type, getEntityClass()); return model; } @Override public D mapToDto(E type) { - D dto = modelMapper.map(type, dtoClass); + D dto = modelMapper.map(type, getDtoClass()); return dto; } }