From d42f2ecfaa5d55b839c21959cc0b121323040fa9 Mon Sep 17 00:00:00 2001 From: Faishal Nelwan <108632813+pesolosep@users.noreply.github.com> Date: Sun, 26 May 2024 21:44:14 +0700 Subject: [PATCH 1/8] [REFACTOR] refactor find by name, add findall() for items, not my responsibility :D --- build.gradle.kts | 2 + .../config/SecurityConfig.java | 2 +- .../controller/ItemController.java | 47 +++++++++++++++++++ .../repository/ItemRepository.java | 44 ++++++++--------- .../repository/SubscriptionBoxRepository.java | 4 +- .../service/ItemService.java | 15 ++++++ .../service/ItemServiceImpl.java | 38 +++++++++++++++ .../SubscriptionBoxRepositoryTest.java | 16 +++---- 8 files changed, 132 insertions(+), 36 deletions(-) create mode 100644 src/main/java/id/ac/ui/cs/advprog/snackscription_subscriptionbox/controller/ItemController.java create mode 100644 src/main/java/id/ac/ui/cs/advprog/snackscription_subscriptionbox/service/ItemService.java create mode 100644 src/main/java/id/ac/ui/cs/advprog/snackscription_subscriptionbox/service/ItemServiceImpl.java diff --git a/build.gradle.kts b/build.gradle.kts index fc52e4b..f8e3dec 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -109,6 +109,8 @@ tasks.jacocoTestReport { "id/ac/ui/cs/advprog/snackscription_subscriptionbox/config/**", "id/ac/ui/cs/advprog/snackscription_subscriptionbox/model/LogAdmin**", "id/ac/ui/cs/advprog/snackscription_subscriptionbox/repository/ItemRepository**", + "id/ac/ui/cs/advprog/snackscription_subscriptionbox/service/ItemServiceImpl**", + "id/ac/ui/cs/advprog/snackscription_subscriptionbox/controller/ItemController**", "id/ac/ui/cs/advprog/snackscription_subscriptionbox/dto/ItemDTO**" ) } diff --git a/src/main/java/id/ac/ui/cs/advprog/snackscription_subscriptionbox/config/SecurityConfig.java b/src/main/java/id/ac/ui/cs/advprog/snackscription_subscriptionbox/config/SecurityConfig.java index 047006c..c463a59 100644 --- a/src/main/java/id/ac/ui/cs/advprog/snackscription_subscriptionbox/config/SecurityConfig.java +++ b/src/main/java/id/ac/ui/cs/advprog/snackscription_subscriptionbox/config/SecurityConfig.java @@ -27,7 +27,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws .authorizeHttpRequests(authorizeRequests -> authorizeRequests .requestMatchers("/actuator/prometheus").permitAll() // Allow unauthenticated access - .requestMatchers("/subscription-box/**", "/public/**").permitAll() + .requestMatchers("/subscription-box/**", "/items/**", "/public/**").permitAll() .requestMatchers("/").permitAll() .anyRequest().authenticated()) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) diff --git a/src/main/java/id/ac/ui/cs/advprog/snackscription_subscriptionbox/controller/ItemController.java b/src/main/java/id/ac/ui/cs/advprog/snackscription_subscriptionbox/controller/ItemController.java new file mode 100644 index 0000000..896d240 --- /dev/null +++ b/src/main/java/id/ac/ui/cs/advprog/snackscription_subscriptionbox/controller/ItemController.java @@ -0,0 +1,47 @@ +package id.ac.ui.cs.advprog.snackscription_subscriptionbox.controller; + + +import id.ac.ui.cs.advprog.snackscription_subscriptionbox.dto.DTOMapper; +import id.ac.ui.cs.advprog.snackscription_subscriptionbox.dto.ItemDTO; +import id.ac.ui.cs.advprog.snackscription_subscriptionbox.model.LogAdmin; +import id.ac.ui.cs.advprog.snackscription_subscriptionbox.service.ItemService; +import id.ac.ui.cs.advprog.snackscription_subscriptionbox.utils.JWTUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import id.ac.ui.cs.advprog.snackscription_subscriptionbox.dto.SubscriptionBoxDTO; +import id.ac.ui.cs.advprog.snackscription_subscriptionbox.model.SubscriptionBox; +import id.ac.ui.cs.advprog.snackscription_subscriptionbox.service.SubscriptionBoxService; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +@RestController +@RequestMapping("/items") +@CrossOrigin(origins = "*") // Change to s +public class ItemController { + private final JWTUtils jwtUtils; + private final ItemService itemService; + + public ItemController(ItemService itemService, JWTUtils jwtUtils) { + this.itemService = itemService; + this.jwtUtils = jwtUtils; + } + + private void validateAdminOnly(String token) throws IllegalAccessException { + String jwt = token.replace("Bearer ", ""); + if (!jwtUtils.extractRole(jwt).equalsIgnoreCase("admin")) { + throw new IllegalAccessException("You have no permission."); + } + } + + @GetMapping("/list") + public CompletableFuture>> findAll(@RequestHeader(value = "Authorization") String token) throws IllegalAccessException { + + return itemService.findAll() + .thenApply(ResponseEntity::ok); + } +} diff --git a/src/main/java/id/ac/ui/cs/advprog/snackscription_subscriptionbox/repository/ItemRepository.java b/src/main/java/id/ac/ui/cs/advprog/snackscription_subscriptionbox/repository/ItemRepository.java index 601ad05..a179ab8 100644 --- a/src/main/java/id/ac/ui/cs/advprog/snackscription_subscriptionbox/repository/ItemRepository.java +++ b/src/main/java/id/ac/ui/cs/advprog/snackscription_subscriptionbox/repository/ItemRepository.java @@ -4,37 +4,31 @@ import org.springframework.stereotype.Repository; import java.util.ArrayList; import java.util.List; +import id.ac.ui.cs.advprog.snackscription_subscriptionbox.model.Item; +import id.ac.ui.cs.advprog.snackscription_subscriptionbox.model.SubscriptionBox; +import org.springframework.stereotype.Repository; +import java.util.ArrayList; +import jakarta.persistence.EntityManager; +import jakarta.persistence.TypedQuery; +import jakarta.transaction.Transactional; +import org.springframework.beans.factory.annotation.Autowired; +import java.util.List; +import java.util.Optional; @Repository public class ItemRepository { - private List items = new ArrayList<>(); - public Item createItem(Item item) { - items.add(item); - return item; - } - public Item getItemById(String id) { - for (Item item : items) { - if (item.getId().equals(id)) { - return item; - } - } - return null; - } - public Item deleteItem(Item item) { - items.remove(item); - return item; - } - public Item editItem(Item item) { - for (Item itemToEdit : items) { - if (item.getId().equals(item.getId())) { - itemToEdit = item; - return itemToEdit; - } - } - return null; + @Autowired + private EntityManager entityManager; + + @Transactional + public List findAll() { + String jpql = "SELECT i FROM Item i"; + TypedQuery query = entityManager.createQuery(jpql, Item.class); + return query.getResultList(); } + } diff --git a/src/main/java/id/ac/ui/cs/advprog/snackscription_subscriptionbox/repository/SubscriptionBoxRepository.java b/src/main/java/id/ac/ui/cs/advprog/snackscription_subscriptionbox/repository/SubscriptionBoxRepository.java index 2242685..c5452e6 100644 --- a/src/main/java/id/ac/ui/cs/advprog/snackscription_subscriptionbox/repository/SubscriptionBoxRepository.java +++ b/src/main/java/id/ac/ui/cs/advprog/snackscription_subscriptionbox/repository/SubscriptionBoxRepository.java @@ -129,9 +129,9 @@ public List findByPriceEquals(int price) { @Transactional public Optional> findByName(String name) { - String jpql = "SELECT sb FROM SubscriptionBox sb LEFT JOIN FETCH sb.items WHERE LOWER(sb.name) LIKE LOWER(:name)"; + String jpql = "SELECT sb FROM SubscriptionBox sb LEFT JOIN FETCH sb.items WHERE sb.name = :name"; TypedQuery query = entityManager.createQuery(jpql, SubscriptionBox.class); - query.setParameter("name", "%" + name.toLowerCase() + "%"); // Convert input name to lowercase + query.setParameter("name", name ); // Convert input name to lowercase List result = query.getResultList(); return Optional.ofNullable(result.isEmpty() ? null : result); } diff --git a/src/main/java/id/ac/ui/cs/advprog/snackscription_subscriptionbox/service/ItemService.java b/src/main/java/id/ac/ui/cs/advprog/snackscription_subscriptionbox/service/ItemService.java new file mode 100644 index 0000000..e15797b --- /dev/null +++ b/src/main/java/id/ac/ui/cs/advprog/snackscription_subscriptionbox/service/ItemService.java @@ -0,0 +1,15 @@ +package id.ac.ui.cs.advprog.snackscription_subscriptionbox.service; +import java.util.List; + +import id.ac.ui.cs.advprog.snackscription_subscriptionbox.dto.ItemDTO; +import id.ac.ui.cs.advprog.snackscription_subscriptionbox.dto.SubscriptionBoxDTO; +import id.ac.ui.cs.advprog.snackscription_subscriptionbox.model.LogAdmin; +import id.ac.ui.cs.advprog.snackscription_subscriptionbox.model.SubscriptionBox; + + +import java.util.Optional; +import java.util.concurrent.CompletableFuture; + +public interface ItemService { + public CompletableFuture> findAll(); +} diff --git a/src/main/java/id/ac/ui/cs/advprog/snackscription_subscriptionbox/service/ItemServiceImpl.java b/src/main/java/id/ac/ui/cs/advprog/snackscription_subscriptionbox/service/ItemServiceImpl.java new file mode 100644 index 0000000..848d396 --- /dev/null +++ b/src/main/java/id/ac/ui/cs/advprog/snackscription_subscriptionbox/service/ItemServiceImpl.java @@ -0,0 +1,38 @@ +package id.ac.ui.cs.advprog.snackscription_subscriptionbox.service; + +import java.util.List; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; + +import id.ac.ui.cs.advprog.snackscription_subscriptionbox.dto.ItemDTO; +import id.ac.ui.cs.advprog.snackscription_subscriptionbox.dto.SubscriptionBoxDTO; +import id.ac.ui.cs.advprog.snackscription_subscriptionbox.dto.DTOMapper; +import id.ac.ui.cs.advprog.snackscription_subscriptionbox.model.Item; +import id.ac.ui.cs.advprog.snackscription_subscriptionbox.repository.ItemRepository; +import id.ac.ui.cs.advprog.snackscription_subscriptionbox.repository.LogRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; +import id.ac.ui.cs.advprog.snackscription_subscriptionbox.model.LogAdmin; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import id.ac.ui.cs.advprog.snackscription_subscriptionbox.model.SubscriptionBox; +import id.ac.ui.cs.advprog.snackscription_subscriptionbox.repository.SubscriptionBoxRepository; + +@Service +public class ItemServiceImpl implements ItemService{ + @Autowired + private ItemRepository itemRepository; + + @Override + @Async + public CompletableFuture> findAll() { + List items = itemRepository.findAll(); + List dtos = items.stream() + .map(DTOMapper::convertItemToDto) + .collect(Collectors.toList()); + return CompletableFuture.completedFuture(dtos); + } + +} diff --git a/src/test/java/id/ac/ui/cs/advprog/snackscription_subscriptionbox/repository/SubscriptionBoxRepositoryTest.java b/src/test/java/id/ac/ui/cs/advprog/snackscription_subscriptionbox/repository/SubscriptionBoxRepositoryTest.java index 97d43d4..72a5fd6 100644 --- a/src/test/java/id/ac/ui/cs/advprog/snackscription_subscriptionbox/repository/SubscriptionBoxRepositoryTest.java +++ b/src/test/java/id/ac/ui/cs/advprog/snackscription_subscriptionbox/repository/SubscriptionBoxRepositoryTest.java @@ -1,6 +1,6 @@ package id.ac.ui.cs.advprog.snackscription_subscriptionbox.repository; -import id.ac.ui.cs.advprog.snackscription_subscriptionbox.model.Item; + import id.ac.ui.cs.advprog.snackscription_subscriptionbox.model.SubscriptionBox; import jakarta.persistence.EntityManager; import jakarta.persistence.TypedQuery; @@ -177,7 +177,7 @@ void testFindByPriceGreaterThan() { List result = subscriptionBoxRepository.findByPriceGreaterThan(150); assertEquals(1, result.size()); - assertEquals(subscriptionBox2, result.get(0)); + assertEquals(subscriptionBox2, result.getFirst()); verify(entityManager, times(1)).createQuery("SELECT sb FROM SubscriptionBox sb LEFT JOIN FETCH sb.items WHERE sb.price > :price", SubscriptionBox.class); verify(query, times(1)).setParameter("price", 150); verify(query, times(1)).getResultList(); @@ -204,19 +204,19 @@ void testFindByPriceEquals() { @Test void testFindByName() { SubscriptionBox subscriptionBox1 = new SubscriptionBox("Basic Box", "Monthly", 100, null, "Basic monthly subscription box"); - SubscriptionBox subscriptionBox2 = new SubscriptionBox("Premium Box", "Monthly", 200, null, "Premium monthly subscription box"); + SubscriptionBox subscriptionBox2 = new SubscriptionBox("Basic Box", "Quarterly", 200, null, "Premium monthly subscription box"); TypedQuery query = mock(TypedQuery.class); - when(entityManager.createQuery("SELECT sb FROM SubscriptionBox sb LEFT JOIN FETCH sb.items WHERE LOWER(sb.name) LIKE LOWER(:name)", SubscriptionBox.class)).thenReturn(query); - when(query.setParameter("name", "%box%")).thenReturn(query); + when(entityManager.createQuery("SELECT sb FROM SubscriptionBox sb LEFT JOIN FETCH sb.items WHERE sb.name = :name", SubscriptionBox.class)).thenReturn(query); + when(query.setParameter("name", "Basic Box")).thenReturn(query); when(query.getResultList()).thenReturn(Arrays.asList(subscriptionBox1, subscriptionBox2)); - Optional> result = subscriptionBoxRepository.findByName("box"); + Optional> result = subscriptionBoxRepository.findByName("Basic Box"); assertTrue(result.isPresent()); assertEquals(2, result.get().size()); - verify(entityManager, times(1)).createQuery("SELECT sb FROM SubscriptionBox sb LEFT JOIN FETCH sb.items WHERE LOWER(sb.name) LIKE LOWER(:name)", SubscriptionBox.class); - verify(query, times(1)).setParameter("name", "%box%"); + verify(entityManager, times(1)).createQuery("SELECT sb FROM SubscriptionBox sb LEFT JOIN FETCH sb.items WHERE sb.name = :name", SubscriptionBox.class); + verify(query, times(1)).setParameter("name", "Basic Box"); verify(query, times(1)).getResultList(); } From 323ac78c4019a745d4d7165e6b3b5a3ad6f4e0cc Mon Sep 17 00:00:00 2001 From: Faishal Nelwan <108632813+pesolosep@users.noreply.github.com> Date: Fri, 31 May 2024 16:06:44 +0700 Subject: [PATCH 2/8] [REFACTOR] trying to fix gcp --- src/main/resources/application-prod.properties | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/resources/application-prod.properties b/src/main/resources/application-prod.properties index 562bfb4..5c03fc3 100644 --- a/src/main/resources/application-prod.properties +++ b/src/main/resources/application-prod.properties @@ -9,6 +9,9 @@ JWT_SECRET=${JWT_SECRET} # Actuator endpoints management.endpoints.web.exposure.include=* management.endpoint.prometheus.enabled=true -spring.datasource.hikari.maximum-pool-size=20 + # Prometheus configuration -management.prometheus.metrics.export.enabled=true \ No newline at end of file +management.prometheus.metrics.export.enabled=true + +server.max-http-request-header-size=64KB + From 7e9b214ba32ee2b08adf19e937459afb3f009e4d Mon Sep 17 00:00:00 2001 From: Faishal Nelwan <108632813+pesolosep@users.noreply.github.com> Date: Fri, 31 May 2024 16:07:17 +0700 Subject: [PATCH 3/8] [FIX] fix gcp problem, ga curang :DDD --- src/main/resources/application-prod.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/application-prod.properties b/src/main/resources/application-prod.properties index 5c03fc3..c4d4a4b 100644 --- a/src/main/resources/application-prod.properties +++ b/src/main/resources/application-prod.properties @@ -13,5 +13,6 @@ management.endpoint.prometheus.enabled=true # Prometheus configuration management.prometheus.metrics.export.enabled=true +# Security server.max-http-request-header-size=64KB From 04b8f12655c336a07ce4ca5353c3cda50f43e6fc Mon Sep 17 00:00:00 2001 From: Faishal Nelwan <108632813+pesolosep@users.noreply.github.com> Date: Fri, 31 May 2024 16:13:11 +0700 Subject: [PATCH 4/8] [FIX] fix gcp problem, ga curang :DDD --- src/main/resources/application-prod.properties | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/resources/application-prod.properties b/src/main/resources/application-prod.properties index c4d4a4b..12a673f 100644 --- a/src/main/resources/application-prod.properties +++ b/src/main/resources/application-prod.properties @@ -9,10 +9,9 @@ JWT_SECRET=${JWT_SECRET} # Actuator endpoints management.endpoints.web.exposure.include=* management.endpoint.prometheus.enabled=true - +spring.datasource.hikari.maximum-pool-size=20 # Prometheus configuration management.prometheus.metrics.export.enabled=true # Security server.max-http-request-header-size=64KB - From 4efafd325842b1143cb50617891213481eee00ea Mon Sep 17 00:00:00 2001 From: Faishal Nelwan <108632813+pesolosep@users.noreply.github.com> Date: Fri, 31 May 2024 16:17:51 +0700 Subject: [PATCH 5/8] [FIX] fix gcp problem, ga curang :DDD --- src/main/resources/application-prod.properties | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/resources/application-prod.properties b/src/main/resources/application-prod.properties index 12a673f..809ad6e 100644 --- a/src/main/resources/application-prod.properties +++ b/src/main/resources/application-prod.properties @@ -13,5 +13,3 @@ spring.datasource.hikari.maximum-pool-size=20 # Prometheus configuration management.prometheus.metrics.export.enabled=true -# Security -server.max-http-request-header-size=64KB From 269fa391f3784da04abda783b27d5841bd07c240 Mon Sep 17 00:00:00 2001 From: Faishal Nelwan <108632813+pesolosep@users.noreply.github.com> Date: Fri, 31 May 2024 16:18:38 +0700 Subject: [PATCH 6/8] [FIX] fix gcp problem, ga curang :DDD --- src/main/resources/application-prod.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/application-prod.properties b/src/main/resources/application-prod.properties index 809ad6e..0fe307a 100644 --- a/src/main/resources/application-prod.properties +++ b/src/main/resources/application-prod.properties @@ -9,7 +9,7 @@ JWT_SECRET=${JWT_SECRET} # Actuator endpoints management.endpoints.web.exposure.include=* management.endpoint.prometheus.enabled=true -spring.datasource.hikari.maximum-pool-size=20 + # Prometheus configuration management.prometheus.metrics.export.enabled=true From 377e83dc4ddd124ef44c5c29e3bdc1e631da970e Mon Sep 17 00:00:00 2001 From: Faishal Nelwan <108632813+pesolosep@users.noreply.github.com> Date: Fri, 31 May 2024 16:24:18 +0700 Subject: [PATCH 7/8] [FIX] fix gcp problem, ga curang :DDD --- src/main/resources/application-prod.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/application-prod.properties b/src/main/resources/application-prod.properties index 0fe307a..e94218e 100644 --- a/src/main/resources/application-prod.properties +++ b/src/main/resources/application-prod.properties @@ -9,6 +9,7 @@ JWT_SECRET=${JWT_SECRET} # Actuator endpoints management.endpoints.web.exposure.include=* management.endpoint.prometheus.enabled=true +spring.datasource.hikari.maximum-pool-size=20 # Prometheus configuration management.prometheus.metrics.export.enabled=true From e45d1b6ea4fb2bb6083c6edcd889204ae2747f00 Mon Sep 17 00:00:00 2001 From: Faishal Nelwan <108632813+pesolosep@users.noreply.github.com> Date: Fri, 31 May 2024 16:24:36 +0700 Subject: [PATCH 8/8] [FIX] fix gcp problem, ga curang :DDD --- src/main/resources/application-prod.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/application-prod.properties b/src/main/resources/application-prod.properties index e94218e..bd28b9e 100644 --- a/src/main/resources/application-prod.properties +++ b/src/main/resources/application-prod.properties @@ -6,6 +6,7 @@ spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect spring.jpa.properties.hibernate.format_sql=true JWT_SECRET=${JWT_SECRET} + # Actuator endpoints management.endpoints.web.exposure.include=* management.endpoint.prometheus.enabled=true