From 6ccca720898bd0be74fb08787dafeaeacb1e11fe Mon Sep 17 00:00:00 2001 From: Fabien Date: Thu, 7 Mar 2024 18:02:45 +0100 Subject: [PATCH 1/7] fix: take account preferredName for visale guarantee --- ...aranteeProviderRulesValidationService.java | 6 ++--- ...teeProviderRulesValidationServiceTest.java | 22 ++++++++++++++++--- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/documentrules/GuaranteeProviderRulesValidationService.java b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/documentrules/GuaranteeProviderRulesValidationService.java index 053de9f58..6cfae1732 100644 --- a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/documentrules/GuaranteeProviderRulesValidationService.java +++ b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/documentrules/GuaranteeProviderRulesValidationService.java @@ -3,7 +3,6 @@ import fr.dossierfacile.common.entity.*; import fr.dossierfacile.common.entity.ocr.GuaranteeProviderFile; import fr.dossierfacile.common.enums.DocumentCategory; -import fr.dossierfacile.common.enums.DocumentSubCategory; import fr.dossierfacile.common.enums.ParsedStatus; import fr.dossierfacile.process.file.util.PersonNameComparator; import lombok.RequiredArgsConstructor; @@ -36,7 +35,8 @@ private boolean checkNamesRule(Document document, GuaranteeProviderFile parsedFi Tenant tenant = document.getGuarantor().getTenant(); return parsedFile.getNames().stream().anyMatch( (fullname) -> PersonNameComparator.bearlyEqualsTo(fullname.firstName(), tenant.getFirstName()) - && PersonNameComparator.bearlyEqualsTo(fullname.lastName(), tenant.getLastName())); + && (PersonNameComparator.bearlyEqualsTo(fullname.lastName(), tenant.getLastName()) + || PersonNameComparator.bearlyEqualsTo(fullname.lastName(), tenant.getPreferredName()))); } private boolean checkValidityRule(GuaranteeProviderFile parsedFile) { @@ -78,7 +78,7 @@ public DocumentAnalysisReport process(Document document, DocumentAnalysisReport } } catch (Exception e) { - log.error("Error during the rules validation execution pocess",e); + log.error("Error during the rules validation execution pocess", e); report.setAnalysisStatus(DocumentAnalysisStatus.UNDEFINED); } return report; diff --git a/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/documentrules/GuaranteeProviderRulesValidationServiceTest.java b/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/documentrules/GuaranteeProviderRulesValidationServiceTest.java index 0824df29d..ee1c246c7 100644 --- a/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/documentrules/GuaranteeProviderRulesValidationServiceTest.java +++ b/dossierfacile-process-file/src/test/java/fr/dossierfacile/process/file/service/documentrules/GuaranteeProviderRulesValidationServiceTest.java @@ -13,12 +13,12 @@ import java.time.LocalDate; import java.time.format.DateTimeFormatter; -import java.util.Arrays; +import java.util.Collections; import java.util.LinkedList; class GuaranteeProviderRulesValidationServiceTest { - private GuaranteeProviderRulesValidationService guaranteeProviderRulesValidationService = new GuaranteeProviderRulesValidationService(); + private final GuaranteeProviderRulesValidationService guaranteeProviderRulesValidationService = new GuaranteeProviderRulesValidationService(); Document buildGuaranteeProviderFile() throws JsonProcessingException { Tenant tenant = Tenant.builder() @@ -59,7 +59,7 @@ Document buildGuaranteeProviderFile() throws JsonProcessingException { .guarantor(Guarantor.builder().tenant(tenant).build()) .documentCategory(DocumentCategory.IDENTIFICATION) .documentSubCategory(DocumentSubCategory.OTHER_GUARANTEE) - .files(Arrays.asList(dfFile)) + .files(Collections.singletonList(dfFile)) .build(); } @@ -94,6 +94,22 @@ void document_expired() throws Exception { Assertions.assertThat(report.getBrokenRules().get(0)).matches(docRule -> docRule.getRule() == DocumentRule.R_GUARANTEE_EXPIRED); } + @Test + void document_valid_preferredname() throws Exception { + Document document = buildGuaranteeProviderFile(); + document.getGuarantor().getTenant().setLastName("NAKAMURA"); + document.getGuarantor().getTenant().setPreferredName("KALOUF"); + ((GuaranteeProviderFile) document.getFiles().get(0).getParsedFileAnalysis().getParsedFile()) + .setValidityDate(LocalDate.now().plusDays(15).format(DateTimeFormatter.ofPattern("dd/MM/yyyy"))); + DocumentAnalysisReport report = DocumentAnalysisReport.builder() + .document(document) + .brokenRules(new LinkedList<>()) + .build(); + guaranteeProviderRulesValidationService.process(document, report); + + Assertions.assertThat(report.getAnalysisStatus()).isEqualTo(DocumentAnalysisStatus.CHECKED); + } + @Test void document_wrong_firstname() throws Exception { Document document = buildGuaranteeProviderFile(); From 9bb3a0ffbb9b6c8e9217db214d96f9c3d4358fac Mon Sep 17 00:00:00 2001 From: Fabien Date: Fri, 8 Mar 2024 18:12:58 +0100 Subject: [PATCH 2/7] fix: mdc injection error and add response status as key --- .../DossierfacileApiOwnerApplication.java | 4 -- .../config/ConnectionContextFilter.java | 3 +- .../config/GeneralConfig.java | 37 ------------------- .../config/ResourceServerConfig.java | 5 ++- .../config/WebhookFilter.java | 6 ++- .../filter/ConnectionContextFilter.java | 3 +- .../AbstractConnectionContextFilter.java | 12 +++++- 7 files changed, 20 insertions(+), 50 deletions(-) diff --git a/dossierfacile-api-owner/src/main/java/fr/dossierfacile/api/dossierfacileapiowner/DossierfacileApiOwnerApplication.java b/dossierfacile-api-owner/src/main/java/fr/dossierfacile/api/dossierfacileapiowner/DossierfacileApiOwnerApplication.java index 5005e4a80..a527e825b 100644 --- a/dossierfacile-api-owner/src/main/java/fr/dossierfacile/api/dossierfacileapiowner/DossierfacileApiOwnerApplication.java +++ b/dossierfacile-api-owner/src/main/java/fr/dossierfacile/api/dossierfacileapiowner/DossierfacileApiOwnerApplication.java @@ -4,17 +4,13 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.domain.EntityScan; -import org.springframework.context.annotation.ComponentScan; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; -@EnableWebMvc @SpringBootApplication(scanBasePackages = "fr.dossierfacile") @EntityScan(basePackages = "fr.dossierfacile") @EnableJpaRepositories(basePackages = "fr.dossierfacile") -@ComponentScan(basePackages = "fr.dossierfacile") @EnableAsync @EnableScheduling @Slf4j diff --git a/dossierfacile-api-owner/src/main/java/fr/dossierfacile/api/dossierfacileapiowner/config/ConnectionContextFilter.java b/dossierfacile-api-owner/src/main/java/fr/dossierfacile/api/dossierfacileapiowner/config/ConnectionContextFilter.java index c5d0c97e4..8a436b299 100644 --- a/dossierfacile-api-owner/src/main/java/fr/dossierfacile/api/dossierfacileapiowner/config/ConnectionContextFilter.java +++ b/dossierfacile-api-owner/src/main/java/fr/dossierfacile/api/dossierfacileapiowner/config/ConnectionContextFilter.java @@ -21,10 +21,9 @@ public boolean isRequestIgnored(HttpServletRequest request) { @Override public Map getAdditionalContextElements() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - if (authentication == null || authentication.getPrincipal() == null) { + if (authentication == null || authentication.getPrincipal() == null || !(authentication.getPrincipal() instanceof Jwt principal)) { return Map.of(); } - Jwt principal = (Jwt) authentication.getPrincipal(); Map map = new TreeMap<>(); map.put(EMAIL, principal.getClaimAsString("email")); return map; diff --git a/dossierfacile-api-owner/src/main/java/fr/dossierfacile/api/dossierfacileapiowner/config/GeneralConfig.java b/dossierfacile-api-owner/src/main/java/fr/dossierfacile/api/dossierfacileapiowner/config/GeneralConfig.java index 53e081c19..b4e552d5c 100644 --- a/dossierfacile-api-owner/src/main/java/fr/dossierfacile/api/dossierfacileapiowner/config/GeneralConfig.java +++ b/dossierfacile-api-owner/src/main/java/fr/dossierfacile/api/dossierfacileapiowner/config/GeneralConfig.java @@ -1,50 +1,13 @@ package fr.dossierfacile.api.dossierfacileapiowner.config; -import org.apache.commons.lang3.StringUtils; -import org.springframework.boot.actuate.autoconfigure.endpoint.web.CorsEndpointProperties; -import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties; -import org.springframework.boot.actuate.autoconfigure.web.server.ManagementPortType; -import org.springframework.boot.actuate.endpoint.ExposableEndpoint; -import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver; -import org.springframework.boot.actuate.endpoint.web.EndpointMapping; -import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes; -import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint; -import org.springframework.boot.actuate.endpoint.web.WebEndpointsSupplier; -import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointsSupplier; -import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointsSupplier; -import org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.core.env.Environment; import org.springframework.web.client.RestTemplate; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - @Configuration public class GeneralConfig { @Bean public RestTemplate restTemplate() { return new RestTemplate(); } - - - @Bean - public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(WebEndpointsSupplier webEndpointsSupplier, ServletEndpointsSupplier servletEndpointsSupplier, ControllerEndpointsSupplier controllerEndpointsSupplier, EndpointMediaTypes endpointMediaTypes, CorsEndpointProperties corsProperties, WebEndpointProperties webEndpointProperties, Environment environment) { - List> allEndpoints = new ArrayList(); - Collection webEndpoints = webEndpointsSupplier.getEndpoints(); - allEndpoints.addAll(webEndpoints); - allEndpoints.addAll(servletEndpointsSupplier.getEndpoints()); - allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints()); - String basePath = webEndpointProperties.getBasePath(); - EndpointMapping endpointMapping = new EndpointMapping(basePath); - boolean shouldRegisterLinksMapping = this.shouldRegisterLinksMapping(webEndpointProperties, environment, basePath); - return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes, corsProperties.toCorsConfiguration(), new EndpointLinksResolver(allEndpoints, basePath), shouldRegisterLinksMapping, null); - } - - - private boolean shouldRegisterLinksMapping(WebEndpointProperties webEndpointProperties, Environment environment, String basePath) { - return webEndpointProperties.getDiscovery().isEnabled() && (StringUtils.isNotBlank(basePath) || ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT)); - } } diff --git a/dossierfacile-api-owner/src/main/java/fr/dossierfacile/api/dossierfacileapiowner/config/ResourceServerConfig.java b/dossierfacile-api-owner/src/main/java/fr/dossierfacile/api/dossierfacileapiowner/config/ResourceServerConfig.java index 97ea0487e..7d7a325fc 100644 --- a/dossierfacile-api-owner/src/main/java/fr/dossierfacile/api/dossierfacileapiowner/config/ResourceServerConfig.java +++ b/dossierfacile-api-owner/src/main/java/fr/dossierfacile/api/dossierfacileapiowner/config/ResourceServerConfig.java @@ -36,6 +36,7 @@ public class ResourceServerConfig { SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .addFilterBefore(new ConnectionContextFilter(), FilterSecurityInterceptor.class) + .formLogin(AbstractHttpConfigurer::disable) .httpBasic(AbstractHttpConfigurer::disable) .csrf(AbstractHttpConfigurer::disable) .addFilterBefore(new WebhookFilter(token, headerName), BasicAuthenticationFilter.class) @@ -56,12 +57,12 @@ SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { @Bean CorsConfigurationSource corsConfigurationSource() { - var configuration = new CorsConfiguration(); + CorsConfiguration configuration = new CorsConfiguration(); configuration.setAllowedOriginPatterns(Collections.singletonList("*")); configuration.setAllowCredentials(true); configuration.setAllowedHeaders(Arrays.asList("Access-Control-Allow-Headers", "Access-Control-Allow-Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers", "Origin", "Cache-Control", "Content-Type", "Authorization", "Baggage", "Sentry-trace")); configuration.setAllowedMethods(Arrays.asList("DELETE", "GET", "POST", "PATCH", "PUT")); - var source = new UrlBasedCorsConfigurationSource(); + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; } diff --git a/dossierfacile-api-owner/src/main/java/fr/dossierfacile/api/dossierfacileapiowner/config/WebhookFilter.java b/dossierfacile-api-owner/src/main/java/fr/dossierfacile/api/dossierfacileapiowner/config/WebhookFilter.java index c5a48149e..926d1969d 100644 --- a/dossierfacile-api-owner/src/main/java/fr/dossierfacile/api/dossierfacileapiowner/config/WebhookFilter.java +++ b/dossierfacile-api-owner/src/main/java/fr/dossierfacile/api/dossierfacileapiowner/config/WebhookFilter.java @@ -13,6 +13,10 @@ import javax.servlet.http.HttpServletResponse; import java.io.IOException; +/** + * DossierFacile will send callback request at change on tenant status. + * This filter check if callback request contain a valid x-api-key. + */ public class WebhookFilter extends OncePerRequestFilter { private final String token; private final String headerName; @@ -49,6 +53,4 @@ protected boolean shouldNotFilter(@NotNull HttpServletRequest request) { RequestMatcher matcher = new NegatedRequestMatcher(uriMatcher); return matcher.matches(request); } - - } \ No newline at end of file diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/config/filter/ConnectionContextFilter.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/config/filter/ConnectionContextFilter.java index 17ef88cb1..a9c22a28e 100644 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/config/filter/ConnectionContextFilter.java +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/config/filter/ConnectionContextFilter.java @@ -23,10 +23,9 @@ public boolean isRequestIgnored(HttpServletRequest request) { @Override public Map getAdditionalContextElements() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - if (authentication == null || authentication.getPrincipal() == null) { + if (authentication == null || authentication.getPrincipal() == null || !(authentication.getPrincipal() instanceof Jwt principal)) { return Map.of(); } - Jwt principal = (Jwt) authentication.getPrincipal(); Map map = new TreeMap<>(); map.put(CLIENT_ID, principal.getClaimAsString("azp")); map.put(KC_ID, principal.getClaimAsString("sub")); diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/config/AbstractConnectionContextFilter.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/config/AbstractConnectionContextFilter.java index acbf5cce2..1c7c03810 100644 --- a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/config/AbstractConnectionContextFilter.java +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/config/AbstractConnectionContextFilter.java @@ -17,6 +17,7 @@ public abstract class AbstractConnectionContextFilter extends HttpFilter { private static final String URI = "uri"; private static final String REQUEST_ID = "request_id"; + private static final String RESPONSE_STATUS = "response_status"; @Override protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { @@ -40,7 +41,16 @@ protected void doFilter(HttpServletRequest request, HttpServletResponse response try { chain.doFilter(request, response); } finally { - log.info("Response: status={}, method={}, path={}", response.getStatus(), request.getMethod(), request.getRequestURI()); + if (response.getStatus() != 200) { + MDC.put(RESPONSE_STATUS, String.valueOf(response.getStatus())); + if (response.getStatus() < 400) { + log.info("Response: status={}, method={}, path={}", response.getStatus(), request.getMethod(), request.getRequestURI()); + } else if (response.getStatus() < 500) { + log.warn("Response: status={}, method={}, path={}", response.getStatus(), request.getMethod(), request.getRequestURI()); + } else { + log.error("Response: status={}, method={}, path={}", response.getStatus(), request.getMethod(), request.getRequestURI()); + } + } MDC.clear(); } } From a6d0f8d493c385c7c0a6b892f0316f8a10f6f8ed Mon Sep 17 00:00:00 2001 From: Fabien Date: Mon, 11 Mar 2024 11:37:15 +0100 Subject: [PATCH 3/7] hotfix: issue on do not archive(confirmAccount) / updateLastLogin behaviour --- .../front/config/ResourceServerConfig.java | 2 +- .../front/controller/RegisterController.java | 8 ---- .../front/controller/TenantController.java | 5 +++ .../api/front/service/TenantServiceImpl.java | 43 +++++++++++-------- .../api/front/service/UserServiceImpl.java | 38 ++-------------- .../service/interfaces/TenantService.java | 2 + .../front/service/interfaces/UserService.java | 2 - .../dossierfacile/common/enums/LogType.java | 1 + .../repository/TenantCommonRepository.java | 4 -- .../service/ConfirmationTokenServiceImpl.java | 6 +++ .../interfaces/ConfirmationTokenService.java | 2 + 11 files changed, 45 insertions(+), 68 deletions(-) diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/config/ResourceServerConfig.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/config/ResourceServerConfig.java index e45e7f088..8ea7ec838 100644 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/config/ResourceServerConfig.java +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/config/ResourceServerConfig.java @@ -51,7 +51,7 @@ SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { .cors(withDefaults()) .authorizeHttpRequests(auth -> auth .requestMatchers("/swagger-ui.html", "/swagger-ui/**", "/v3/api-docs/**", - "/api/register/account", "/api/register/confirmAccount/**", + "/api/register/account", "/api/tenant/doNotArchive/**", "/api/auth/**", "/api/user/forgotPassword", "/api/user/createPassword/**", "/api/document/**", "/api/application/full/**", "/api/application/light/**", "/api/application/fullPdf/**", "/api/tenant/property/**", diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/controller/RegisterController.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/controller/RegisterController.java index b4a794628..cecd0e408 100644 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/controller/RegisterController.java +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/controller/RegisterController.java @@ -41,7 +41,6 @@ public class RegisterController { private final TenantMapper tenantMapper; private final TenantService tenantService; - private final UserService userService; private final AuthenticationFacade authenticationFacade; private final LogService logService; @@ -52,13 +51,6 @@ public ResponseEntity account(@Validated(Dossier.class) @RequestBod return ok(tenantModel); } - @GetMapping("/confirmAccount/{token}") - public ResponseEntity confirmAccount(@PathVariable String token) { - long tenantId = userService.confirmAccount(token); - logService.saveLog(LogType.EMAIL_ACCOUNT_VALIDATED, tenantId); - return ok().build(); - } - @PreAuthorize("hasPermissionOnTenant(#namesForm.tenantId)") @PostMapping(value = "/names", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity names(@Validated(Dossier.class) @RequestBody NamesForm namesForm) { diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/controller/TenantController.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/controller/TenantController.java index 17231d094..da4adc514 100644 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/controller/TenantController.java +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/controller/TenantController.java @@ -84,4 +84,9 @@ public ResponseEntity sendFileByMail(@RequestBody ShareFileByMailForm sh } return ok(""); } + @GetMapping("/doNotArchive/{token}") + public ResponseEntity doNotArchive(@PathVariable String token) { + tenantService.doNotArchive(token); + return ok().build(); + } } diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/service/TenantServiceImpl.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/service/TenantServiceImpl.java index d31b46838..7684a06f3 100644 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/service/TenantServiceImpl.java +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/service/TenantServiceImpl.java @@ -12,15 +12,8 @@ import fr.dossierfacile.api.front.service.interfaces.TenantService; import fr.dossierfacile.api.front.service.interfaces.UserApiService; import fr.dossierfacile.api.front.util.Obfuscator; -import fr.dossierfacile.common.entity.ApartmentSharing; -import fr.dossierfacile.common.entity.ApartmentSharingLink; -import fr.dossierfacile.common.entity.Tenant; -import fr.dossierfacile.common.entity.UserApi; -import fr.dossierfacile.common.enums.ApartmentSharingLinkType; -import fr.dossierfacile.common.enums.LogType; -import fr.dossierfacile.common.enums.PartnerCallBackType; -import fr.dossierfacile.common.enums.TenantFileStatus; -import fr.dossierfacile.common.enums.TenantType; +import fr.dossierfacile.common.entity.*; +import fr.dossierfacile.common.enums.*; import fr.dossierfacile.common.model.TenantUpdate; import fr.dossierfacile.common.repository.ApartmentSharingLinkRepository; import fr.dossierfacile.common.repository.ApartmentSharingRepository; @@ -30,6 +23,7 @@ import fr.dossierfacile.common.service.interfaces.PartnerCallBackService; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -61,17 +55,30 @@ public TenantModel saveStepRegister(Tenant tenant, T formStep, StepRegister } @Override - public void updateLastLoginDateAndResetWarnings(Tenant tenant) { - tenant.setLastLoginDate(LocalDateTime.now()); - tenant.setWarnings(0); - if (tenant.getStatus() == TenantFileStatus.ARCHIVED) { - tenant.setStatus(TenantFileStatus.INCOMPLETE); - partnerCallBackService.sendCallBack(tenant, PartnerCallBackType.RETURNED_ACCOUNT); + public void updateLastLoginDateAndResetWarnings(Tenant tenantToUpdate) { + LocalDateTime currentTime = LocalDateTime.now(); + for (Tenant tenant : tenantToUpdate.getApartmentSharing().getTenants()) { + if (tenant.getId() == tenantToUpdate.getId() || StringUtils.isBlank(tenant.getEmail())) { + tenant.setLastLoginDate(currentTime); + tenant.setWarnings(0); + if (tenant.getStatus() == TenantFileStatus.ARCHIVED) { + tenant.setStatus(TenantFileStatus.INCOMPLETE); + partnerCallBackService.sendCallBack(tenant, PartnerCallBackType.RETURNED_ACCOUNT); + } + log.info("Updating last_login_date of tenant with ID [" + tenant.getId() + "]"); + tenantRepository.save(tenant); + } } - log.info("Updating last_login_date of tenant with ID [" + tenant.getId() + "]"); - tenantRepository.save(tenant); } - + @Override + @Transactional + public void doNotArchive(String token) { + ConfirmationToken confirmationToken = confirmationTokenService.findByToken(token); + Tenant tenant = tenantRepository.getReferenceById(confirmationToken.getUser().getId()); + tenant.setConfirmationToken(null); + updateLastLoginDateAndResetWarnings(tenant); + logService.saveLog(LogType.DO_NOT_ARCHIVE, tenant.getId()); + } @Override @Transactional public Tenant create(Tenant tenant) { diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/service/UserServiceImpl.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/service/UserServiceImpl.java index b76d0042e..2075ffcf1 100644 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/service/UserServiceImpl.java +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/service/UserServiceImpl.java @@ -6,25 +6,13 @@ import fr.dossierfacile.api.front.model.tenant.TenantModel; import fr.dossierfacile.api.front.repository.PasswordRecoveryTokenRepository; import fr.dossierfacile.api.front.repository.UserRepository; -import fr.dossierfacile.api.front.service.interfaces.ApartmentSharingService; -import fr.dossierfacile.api.front.service.interfaces.KeycloakService; -import fr.dossierfacile.api.front.service.interfaces.MailService; -import fr.dossierfacile.api.front.service.interfaces.PasswordRecoveryTokenService; -import fr.dossierfacile.api.front.service.interfaces.UserApiService; -import fr.dossierfacile.api.front.service.interfaces.UserService; -import fr.dossierfacile.common.entity.ApartmentSharing; -import fr.dossierfacile.common.entity.ConfirmationToken; -import fr.dossierfacile.common.entity.PasswordRecoveryToken; -import fr.dossierfacile.common.entity.Tenant; -import fr.dossierfacile.common.entity.User; -import fr.dossierfacile.common.entity.UserApi; +import fr.dossierfacile.api.front.service.interfaces.*; +import fr.dossierfacile.common.entity.*; import fr.dossierfacile.common.enums.ApplicationType; import fr.dossierfacile.common.enums.LogType; import fr.dossierfacile.common.enums.PartnerCallBackType; import fr.dossierfacile.common.enums.TenantType; -import fr.dossierfacile.common.exceptions.ConfirmationTokenNotFoundException; import fr.dossierfacile.common.model.WebhookDTO; -import fr.dossierfacile.common.repository.ConfirmationTokenRepository; import fr.dossierfacile.common.repository.TenantCommonRepository; import fr.dossierfacile.common.service.interfaces.LogService; import fr.dossierfacile.common.service.interfaces.PartnerCallBackService; @@ -35,7 +23,6 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -44,7 +31,6 @@ @RequiredArgsConstructor @Slf4j public class UserServiceImpl implements UserService { - private final ConfirmationTokenRepository confirmationTokenRepository; private final UserRepository userRepository; private final PasswordRecoveryTokenRepository passwordRecoveryTokenRepository; private final MailService mailService; @@ -58,24 +44,6 @@ public class UserServiceImpl implements UserService { private final ApartmentSharingService apartmentSharingService; private final TenantCommonService tenantCommonService; - @Override - @Transactional - public long confirmAccount(String token) { - ConfirmationToken confirmationToken = confirmationTokenRepository.findByToken(token).orElseThrow(() -> new ConfirmationTokenNotFoundException(token)); - User user = confirmationToken.getUser(); - user.setEnabled(true); - user.setConfirmationToken(null); - user.setLastLoginDate(LocalDateTime.now()); - userRepository.save(user); - confirmationTokenRepository.delete(confirmationToken); - if (user.getKeycloakId() != null) { - keycloakService.confirmKeycloakUser(user.getKeycloakId()); - // else we assume it's a partner account - } - tenantRepository.resetWarnings(user.getId()); - return user.getId(); - } - @Override public TenantModel createPassword(User user, String password) { keycloakService.createKeyCloakPassword(user.getKeycloakId(), password); @@ -90,7 +58,7 @@ public TenantModel createPassword(String token, String password) { // check if keycloak is correctly synchronised User user = passwordRecoveryToken.getUser(); var keycloakId = keycloakService.getKeycloakId(user.getEmail()); - if (!StringUtils.equals(keycloakId, user.getKeycloakId())){ + if (!StringUtils.equals(keycloakId, user.getKeycloakId())) { log.warn("Tenant keycloakId has been synchronized - user_id: " + user.getId()); user.setKeycloakId(keycloakId); userRepository.save(user); diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/service/interfaces/TenantService.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/service/interfaces/TenantService.java index da6a64f3f..3d53a2899 100644 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/service/interfaces/TenantService.java +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/service/interfaces/TenantService.java @@ -32,4 +32,6 @@ public interface TenantService { List findTenantUpdateByLastUpdateAndPartner(LocalDateTime from, UserApi userApi, Long limit, boolean includeDeleted, boolean includeRevoked); void sendFileByMail(Tenant tenant, String email, String shareType); + + void doNotArchive(String token); } diff --git a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/service/interfaces/UserService.java b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/service/interfaces/UserService.java index 8cda507b7..a449628b0 100644 --- a/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/service/interfaces/UserService.java +++ b/dossierfacile-api-tenant/src/main/java/fr/dossierfacile/api/front/service/interfaces/UserService.java @@ -5,8 +5,6 @@ import fr.dossierfacile.common.entity.User; public interface UserService { - long confirmAccount(String token); - TenantModel createPassword(User user, String password); TenantModel createPassword(String token, String password); diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/enums/LogType.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/enums/LogType.java index 424a16a93..68a44512e 100644 --- a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/enums/LogType.java +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/enums/LogType.java @@ -18,6 +18,7 @@ public enum LogType { FIRST_ACCOUNT_WARNING_FOR_DOCUMENT_DELETION, SECOND_ACCOUNT_WARNING_FOR_DOCUMENT_DELETION, DOCUMENT_DELETION_AFTER_2_ACCOUNT_WARNINGS, + DO_NOT_ARCHIVE, FC_ACCOUNT_CREATION, FC_ACCOUNT_LINK, PARTNER_ACCESS_REVOKED, diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/repository/TenantCommonRepository.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/repository/TenantCommonRepository.java index 53a6900d4..a47f88ba8 100644 --- a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/repository/TenantCommonRepository.java +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/repository/TenantCommonRepository.java @@ -199,10 +199,6 @@ SELECT COUNT(t.id) ) List findAllTenantsValidatedSinceXDaysAgo(@Param("startDate") LocalDateTime startDate, @Param("endDate") LocalDateTime endDate); - @Modifying - @Query("UPDATE Tenant t SET t.warnings = 0 where t.id = :tenantId") - void resetWarnings(@Param("tenantId") Long tenantId); - List findAllByApartmentSharing(ApartmentSharing apartmentSharing); List findByEmailInAndApartmentSharingNot(List coTenantEmail, ApartmentSharing apartmentSharing); diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/ConfirmationTokenServiceImpl.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/ConfirmationTokenServiceImpl.java index 69ff8ae45..749b51a96 100644 --- a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/ConfirmationTokenServiceImpl.java +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/ConfirmationTokenServiceImpl.java @@ -2,6 +2,7 @@ import fr.dossierfacile.common.entity.ConfirmationToken; import fr.dossierfacile.common.entity.User; +import fr.dossierfacile.common.exceptions.ConfirmationTokenNotFoundException; import fr.dossierfacile.common.repository.ConfirmationTokenRepository; import fr.dossierfacile.common.service.interfaces.ConfirmationTokenService; import lombok.AllArgsConstructor; @@ -19,4 +20,9 @@ public ConfirmationToken createToken(User user) { confirmationToken.refreshToken(); return confirmationTokenRepository.save(confirmationToken); } + + @Override + public ConfirmationToken findByToken(String token) { + return confirmationTokenRepository.findByToken(token).orElseThrow(() -> new ConfirmationTokenNotFoundException(token)); + } } diff --git a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/interfaces/ConfirmationTokenService.java b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/interfaces/ConfirmationTokenService.java index f1ffd39ac..be9eb8939 100644 --- a/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/interfaces/ConfirmationTokenService.java +++ b/dossierfacile-common-library/src/main/java/fr/dossierfacile/common/service/interfaces/ConfirmationTokenService.java @@ -5,4 +5,6 @@ public interface ConfirmationTokenService { ConfirmationToken createToken(User user); + + ConfirmationToken findByToken(String token); } From c61fe4c0cc9c78c7cde11b60ab0434efd4791328 Mon Sep 17 00:00:00 2001 From: Fabien Date: Mon, 11 Mar 2024 12:40:33 +0100 Subject: [PATCH 4/7] chore: add MDC keys in appender --- .../src/main/resources/logback-spring-delayed.xml | 2 ++ .../src/main/resources/logback-spring-delayed.xml | 1 + 2 files changed, 3 insertions(+) diff --git a/dossierfacile-api-owner/src/main/resources/logback-spring-delayed.xml b/dossierfacile-api-owner/src/main/resources/logback-spring-delayed.xml index 1934f8fdf..b547204ef 100644 --- a/dossierfacile-api-owner/src/main/resources/logback-spring-delayed.xml +++ b/dossierfacile-api-owner/src/main/resources/logback-spring-delayed.xml @@ -49,6 +49,8 @@ client user request_id + response_status + email diff --git a/dossierfacile-api-tenant/src/main/resources/logback-spring-delayed.xml b/dossierfacile-api-tenant/src/main/resources/logback-spring-delayed.xml index 07246a58a..e235c4b1b 100644 --- a/dossierfacile-api-tenant/src/main/resources/logback-spring-delayed.xml +++ b/dossierfacile-api-tenant/src/main/resources/logback-spring-delayed.xml @@ -51,6 +51,7 @@ user email request_id + response_status From c9f658cc9d2dc9e4dcdf029cb9681377f25d7499 Mon Sep 17 00:00:00 2001 From: Fabien Date: Mon, 11 Mar 2024 14:52:50 +0100 Subject: [PATCH 5/7] chore: increase dpi resolution for image parser --- .../process/file/service/parsers/AbstractPDFImageParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/AbstractPDFImageParser.java b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/AbstractPDFImageParser.java index 1a7e8f974..f48028a82 100644 --- a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/AbstractPDFImageParser.java +++ b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/parsers/AbstractPDFImageParser.java @@ -27,7 +27,7 @@ void init() { this.tesseract = new Tesseract(); this.tesseract.setLanguage("fra+eng"); this.tesseract.setOcrEngineMode(ITessAPI.TessOcrEngineMode.OEM_LSTM_ONLY); - this.tesseract.setVariable("user_defined_dpi", "128"); + this.tesseract.setVariable("user_defined_dpi", "300"); } } From 0648cac9fef5d6bc3e01b5af5deaee921f2ff4c8 Mon Sep 17 00:00:00 2001 From: Fabien Date: Mon, 11 Mar 2024 15:10:39 +0100 Subject: [PATCH 6/7] chore: update fullname on rental document rules --- .../documentrules/RentalReceiptRulesValidationService.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/documentrules/RentalReceiptRulesValidationService.java b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/documentrules/RentalReceiptRulesValidationService.java index 515e0ab4b..d8a0f98e0 100644 --- a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/documentrules/RentalReceiptRulesValidationService.java +++ b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/documentrules/RentalReceiptRulesValidationService.java @@ -42,8 +42,10 @@ private boolean checkNamesRule(Document document) { ParsedFileAnalysis analysis = dfFile.getParsedFileAnalysis(); RentalReceiptFile parsedFile = (RentalReceiptFile) analysis.getParsedFile(); - if (users.stream().noneMatch((user) -> PersonNameComparator.bearlyEqualsTo(parsedFile.getTenantFullName(), user.getLastName(), user.getFirstName()) - || PersonNameComparator.bearlyEqualsTo(parsedFile.getTenantFullName(), user.getPreferredName(), user.getFirstName()))) { + String fullName = parsedFile.getTenantFullName().toUpperCase().replaceFirst("^(M. |MR |MME |MLLE |MONSIEUR |MADAME |MADEMOISELLE )", ""); + + if (users.stream().noneMatch((user) -> PersonNameComparator.bearlyEqualsTo(fullName, user.getLastName(), user.getFirstName()) + || PersonNameComparator.bearlyEqualsTo(fullName, user.getPreferredName(), user.getFirstName()))) { return false; } } From c945023b9a34fccd111a9b2771aeb28a9e15ed54 Mon Sep 17 00:00:00 2001 From: Fabien Date: Mon, 11 Mar 2024 15:54:30 +0100 Subject: [PATCH 7/7] fix: update rental rules for guarantor to 1 month receipt --- .../RentalReceiptRulesValidationService.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/documentrules/RentalReceiptRulesValidationService.java b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/documentrules/RentalReceiptRulesValidationService.java index d8a0f98e0..9542abaf0 100644 --- a/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/documentrules/RentalReceiptRulesValidationService.java +++ b/dossierfacile-process-file/src/main/java/fr/dossierfacile/process/file/service/documentrules/RentalReceiptRulesValidationService.java @@ -65,8 +65,21 @@ private List> getExpectedMonthsLists() { List.of(yearMonth.minusMonths(2), yearMonth.minusMonths(3), yearMonth.minusMonths(4))); } + private List> getGuarantorExpectedMonthsLists() { + LocalDate localDate = LocalDate.now(); + YearMonth yearMonth = YearMonth.now(); + return (localDate.getDayOfMonth() <= 15) ? + List.of( + List.of(yearMonth.minusMonths(1)), + List.of(yearMonth.minusMonths(2)), + List.of(yearMonth.minusMonths(3))) : + List.of( + List.of(yearMonth.minusMonths(1)), + List.of(yearMonth.minusMonths(2))); + } + private boolean checkMonthsValidityRule(Document document) { - List> expectedMonthsList = getExpectedMonthsLists(); + List> expectedMonthsList = (document.getTenant() != null) ? getExpectedMonthsLists() : getGuarantorExpectedMonthsLists(); List presentMonths = document.getFiles().stream() .map(file -> ((RentalReceiptFile) file.getParsedFileAnalysis().getParsedFile()).getPeriod())