This is an automated email from the ASF dual-hosted git repository.

taskain pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git


The following commit(s) were added to refs/heads/develop by this push:
     new 8090c614e FINERACT-1724 Loan COB Api Filter external id fix - [x] UUID 
az external id to test non-numeric id - [x] Unit test
8090c614e is described below

commit 8090c614ed2e5b599528ef1461e2a744676adf88
Author: Janos Haber <[email protected]>
AuthorDate: Wed Mar 1 12:08:56 2023 +0100

    FINERACT-1724 Loan COB Api Filter external id fix
    - [x] UUID az external id to test non-numeric id
    - [x] Unit test
---
 .../jobs/filter/LoanCOBApiFilter.java              | 38 +++++++++++++++----
 .../jobs/filter/LoanCOBApiFilterTest.java          | 44 ++++++++++++++++++----
 2 files changed, 68 insertions(+), 14 deletions(-)

diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/filter/LoanCOBApiFilter.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/filter/LoanCOBApiFilter.java
index 571fb3a25..9812f6f55 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/filter/LoanCOBApiFilter.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/filter/LoanCOBApiFilter.java
@@ -39,6 +39,7 @@ import 
org.apache.fineract.cob.service.InlineLoanCOBExecutorServiceImpl;
 import org.apache.fineract.cob.service.LoanAccountLockService;
 import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
 import org.apache.fineract.infrastructure.core.data.ApiGlobalErrorResponse;
+import org.apache.fineract.infrastructure.core.domain.ExternalId;
 import org.apache.fineract.infrastructure.core.filters.BatchFilter;
 import org.apache.fineract.infrastructure.core.filters.BatchFilterChain;
 import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
@@ -65,7 +66,7 @@ public class LoanCOBApiFilter extends OncePerRequestFilter 
implements BatchFilte
 
     private static final List<HttpMethod> HTTP_METHODS = 
List.of(HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE);
 
-    public static final Pattern LOAN_PATH_PATTERN = 
Pattern.compile("\\/?loans\\/(?:external-id\\/)?(\\d+).*");
+    public static final Pattern LOAN_PATH_PATTERN = 
Pattern.compile("\\/?loans\\/(?:external-id\\/)?([^\\/\\?]+).*");
 
     public static final Pattern LOAN_GLIMACCOUNT_PATH_PATTERN = 
Pattern.compile("\\/?loans\\/glimAccount\\/(\\d+).*");
     private static final Predicate<String> URL_FUNCTION = s -> 
LOAN_PATH_PATTERN.matcher(s).find()
@@ -142,16 +143,27 @@ public class LoanCOBApiFilter extends 
OncePerRequestFilter implements BatchFilte
 
     private List<Long> calculateRelevantLoanIds(String pathInfo) {
 
-        boolean isGlim = isGlim(pathInfo);
-        Long loanIdFromRequest = getLoanId(isGlim, pathInfo);
-        List<Long> loanIds = isGlim ? getGlimChildLoanIds(loanIdFromRequest) : 
Collections.singletonList(loanIdFromRequest);
+        List<Long> loanIds = getLoanIdList(pathInfo);
         if (isLoanHardLocked(loanIds)) {
-            throw new LoanIdsHardLockedException(loanIdFromRequest);
+            throw new LoanIdsHardLockedException(loanIds.get(0));
         } else {
             return loanIds;
         }
     }
 
+    private List<Long> getLoanIdList(String pathInfo) {
+        boolean isGlim = isGlim(pathInfo);
+        Long loanIdFromRequest = getLoanId(isGlim, pathInfo);
+        if (loanIdFromRequest == null) {
+            return Collections.emptyList();
+        }
+        if (isGlim) {
+            return getGlimChildLoanIds(loanIdFromRequest);
+        } else {
+            return Collections.singletonList(loanIdFromRequest);
+        }
+    }
+
     private void executeInlineCob(List<Long> loanIds) {
         inlineLoanCOBExecutorService.execute(loanIds, JOB_NAME);
     }
@@ -190,12 +202,24 @@ public class LoanCOBApiFilter extends 
OncePerRequestFilter implements BatchFilte
 
     private Long getLoanId(boolean isGlim, String pathInfo) {
         if (!isGlim) {
-            return 
Long.valueOf(LOAN_PATH_PATTERN.matcher(pathInfo).replaceAll("$1"));
+            String id = LOAN_PATH_PATTERN.matcher(pathInfo).replaceAll("$1");
+            if (isExternal(pathInfo)) {
+                String externalId = id;
+                return loanRepository.findIdByExternalId(new 
ExternalId(externalId));
+            } else if (StringUtils.isNumeric(id)) {
+                return Long.valueOf(id);
+            } else {
+                return null;
+            }
         } else {
             return 
Long.valueOf(LOAN_GLIMACCOUNT_PATH_PATTERN.matcher(pathInfo).replaceAll("$1"));
         }
     }
 
+    private boolean isExternal(String pathInfo) {
+        return LOAN_PATH_PATTERN.matcher(pathInfo).matches() && 
pathInfo.contains("external-id");
+    }
+
     private boolean isOnApiList(String pathInfo, String method) {
         if (StringUtils.isBlank(pathInfo)) {
             return false;
@@ -219,7 +243,7 @@ public class LoanCOBApiFilter extends OncePerRequestFilter 
implements BatchFilte
                 } else {
                     try {
                         List<Long> result = calculateRelevantLoanIds("/" + 
batchRequest.getRelativeUrl());
-                        if (isLoanSoftLocked(result)) {
+                        if (isLoanSoftLocked(result) || isLoanBehind(result)) {
                             executeInlineCob(result);
                         }
                         return chain.serviceCall(batchRequest, uriInfo);
diff --git 
a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/jobs/filter/LoanCOBApiFilterTest.java
 
b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/jobs/filter/LoanCOBApiFilterTest.java
index 0ccf932f3..e31e89647 100644
--- 
a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/jobs/filter/LoanCOBApiFilterTest.java
+++ 
b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/jobs/filter/LoanCOBApiFilterTest.java
@@ -18,6 +18,7 @@
  */
 package org.apache.fineract.infrastructure.jobs.filter;
 
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyList;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.BDDMockito.given;
@@ -33,6 +34,7 @@ import java.time.LocalDate;
 import java.time.ZoneId;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.UUID;
 import javax.servlet.FilterChain;
 import javax.servlet.ServletException;
 import org.apache.fineract.cob.service.InlineLoanCOBExecutorServiceImpl;
@@ -77,15 +79,18 @@ class LoanCOBApiFilterTest {
 
     @Test
     void shouldLoanAndExternalMatchToo() {
+        String externalId = UUID.randomUUID().toString();
         
Assertions.assertTrue(LoanCOBApiFilter.LOAN_PATH_PATTERN.matcher("/loans/12").matches());
         
Assertions.assertTrue(LoanCOBApiFilter.LOAN_PATH_PATTERN.matcher("/loans/12?correct=parameter").matches());
-        
Assertions.assertTrue(LoanCOBApiFilter.LOAN_PATH_PATTERN.matcher("/loans/external-id/12").matches());
-        
Assertions.assertTrue(LoanCOBApiFilter.LOAN_PATH_PATTERN.matcher("/loans/external-id/12?additional=parameter").matches());
+        
Assertions.assertTrue(LoanCOBApiFilter.LOAN_PATH_PATTERN.matcher("/loans/external-id/"
 + externalId).matches());
+        Assertions.assertTrue(
+                
LoanCOBApiFilter.LOAN_PATH_PATTERN.matcher("/loans/external-id/" + externalId + 
"?additional=parameter").matches());
         Assertions.assertEquals("12", 
LoanCOBApiFilter.LOAN_PATH_PATTERN.matcher("/loans/12").replaceAll("$1"));
         Assertions.assertEquals("12", 
LoanCOBApiFilter.LOAN_PATH_PATTERN.matcher("/loans/12?correct=parameter").replaceAll("$1"));
-        Assertions.assertEquals("12", 
LoanCOBApiFilter.LOAN_PATH_PATTERN.matcher("/loans/external-id/12").replaceAll("$1"));
-        Assertions.assertEquals("12",
-                
LoanCOBApiFilter.LOAN_PATH_PATTERN.matcher("/loans/external-id/12?additional=parameter").replaceAll("$1"));
+        Assertions.assertEquals(externalId,
+                
LoanCOBApiFilter.LOAN_PATH_PATTERN.matcher("/loans/external-id/" + 
externalId).replaceAll("$1"));
+        Assertions.assertEquals(externalId,
+                
LoanCOBApiFilter.LOAN_PATH_PATTERN.matcher("/loans/external-id/" + externalId + 
"?additional=parameter").replaceAll("$1"));
     }
 
     @Test
@@ -111,6 +116,30 @@ class LoanCOBApiFilterTest {
         verify(filterChain, times(1)).doFilter(request, response);
     }
 
+    @Test
+    void shouldProceedWhenUrlDoesNotMatchWithInvalidLoanId() throws 
ServletException, IOException {
+        MockHttpServletRequest request = mock(MockHttpServletRequest.class);
+        MockHttpServletResponse response = mock(MockHttpServletResponse.class);
+        FilterChain filterChain = mock(FilterChain.class);
+        AppUser appUser = mock(AppUser.class);
+        ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L, 
"default", "Default", "Asia/Kolkata", null));
+        HashMap<BusinessDateType, LocalDate> businessDates = new HashMap<>();
+        LocalDate businessDate = LocalDate.now(ZoneId.systemDefault());
+        businessDates.put(BusinessDateType.BUSINESS_DATE, businessDate);
+        businessDates.put(BusinessDateType.COB_DATE, 
businessDate.minusDays(1));
+        ThreadLocalContextUtil.setBusinessDates(businessDates);
+
+        
given(request.getPathInfo()).willReturn("/loans/invalid2LoanId/charges");
+        given(request.getMethod()).willReturn(HTTPMethods.POST.value());
+        given(context.authenticatedUser()).willReturn(appUser);
+        given(loanRepository.findAllNonClosedLoansBehindByLoanIds(
+                
eq(ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE)), 
anyList()))
+                        .willReturn(Collections.emptyList());
+
+        testObj.doFilterInternal(request, response, filterChain);
+        verify(filterChain, times(1)).doFilter(request, response);
+    }
+
     @Test
     void shouldProceedWhenUserHasBypassPermission() throws ServletException, 
IOException {
         MockHttpServletRequest request = mock(MockHttpServletRequest.class);
@@ -165,12 +194,13 @@ class LoanCOBApiFilterTest {
         businessDates.put(BusinessDateType.BUSINESS_DATE, businessDate);
         businessDates.put(BusinessDateType.COB_DATE, 
businessDate.minusDays(1));
         ThreadLocalContextUtil.setBusinessDates(businessDates);
-
-        
given(request.getPathInfo()).willReturn("/loans/external-id/2/charges");
+        String uuid = UUID.randomUUID().toString();
+        given(request.getPathInfo()).willReturn("/loans/external-id/" + uuid + 
"/charges");
         given(request.getMethod()).willReturn(HTTPMethods.POST.value());
         given(loanAccountLockService.isLoanHardLocked(2L)).willReturn(false);
         given(loanAccountLockService.isLoanSoftLocked(2L)).willReturn(false);
         given(context.authenticatedUser()).willReturn(appUser);
+        given(loanRepository.findIdByExternalId(any())).willReturn(2L);
         given(loanRepository.findAllNonClosedLoansBehindByLoanIds(
                 
eq(ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE)), 
anyList()))
                         .willReturn(Collections.emptyList());

Reply via email to