From 43cc11ba0208d512a66ac326131494f0c3e23958 Mon Sep 17 00:00:00 2001 From: harish Date: Fri, 20 Sep 2024 16:25:57 +0530 Subject: [PATCH 01/58] Updated Logic for Retrieving Previous Form --- .../tendermanagement/dao/FlowFormDao.java | 106 +++++++++++------- .../repositories/FormRepository.java | 2 + 2 files changed, 68 insertions(+), 40 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java b/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java index 0df71aa8..f46e61f5 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java @@ -1,10 +1,12 @@ package net.gepafin.tendermanagement.dao; +import java.util.Comparator; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; +import net.gepafin.tendermanagement.repositories.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -18,10 +20,6 @@ import net.gepafin.tendermanagement.entities.FlowEdgesEntity; import net.gepafin.tendermanagement.entities.FormEntity; import net.gepafin.tendermanagement.enums.FormActionEnum; import net.gepafin.tendermanagement.model.response.NextOrPreviousFormResponse; -import net.gepafin.tendermanagement.repositories.ApplicationFormFieldRepository; -import net.gepafin.tendermanagement.repositories.ApplicationFormRepository; -import net.gepafin.tendermanagement.repositories.FlowDataRepository; -import net.gepafin.tendermanagement.repositories.FlowEdgesRepository; import net.gepafin.tendermanagement.service.FormService; import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException; @@ -47,7 +45,8 @@ public class FlowFormDao { @Autowired private FormService formService; - + @Autowired + private FormRepository formRepository; // Long getNextForm(FormEntity currentFormEntity, ApplicationEntity applicationEntity) { // // vlaidation if next form findout and cuuent from is not fill the give error @@ -177,52 +176,79 @@ public class FlowFormDao { .orElse(null); } - public Long getPreviousForm(FormEntity currentFormEntity, ApplicationEntity applicationEntity) { - // Retrieve the flow edges for the previous forms - List flowEdgesList = flowEdgesRepository.findByTargetIdAndCallId( - currentFormEntity.getId(), applicationEntity.getCall().getId()); +// public Long getPreviousForm(FormEntity currentFormEntity, ApplicationEntity applicationEntity) { +// // Retrieve the flow edges for the previous forms +// List flowEdgesList = flowEdgesRepository.findByTargetIdAndCallId( +// currentFormEntity.getId(), applicationEntity.getCall().getId()); +// +// if (flowEdgesList.isEmpty()) { +// return null; +//// throw new ResourceNotFoundException(Status.NOT_FOUND, +//// Translator.toLocale(GepafinConstant.PREVIOUS_FORM_NOT_FOUND)); +// } +// +// // If only one edge exists, return the source form ID +// if (flowEdgesList.size() == 1) { +// return flowEdgesList.get(0).getSourceId(); +// } +// +// // For multiple edges, find the previous form based on the chosen value +// List previousFormIds = flowEdgesList.stream() +// .map(FlowEdgesEntity::getSourceId) +// .toList(); +// +// // Fetch the flow data based on previous form IDs +// List flowDataList = flowDataRepository.findByFormIdInAndCallId( +// previousFormIds, applicationEntity.getCall().getId()); +// +// List chosenValues = flowDataList.stream() +// .map(FlowDataEntity::getChoosenValue) +// .toList(); +// +// // Fetch the previous forms based on the chosen field values +// Set formList = applicationFormFieldRepository +// .findByFieldValueInAndApplicationFormApplicationId(chosenValues, applicationEntity.getId()).stream() +// .map(fieldEntity -> fieldEntity.getApplicationForm().getForm()) +// .collect(Collectors.toSet()); +// +// // Find next form IDs recursively for all forms in the formList +// List fieldIds = formList.stream() +// .map(formEntity -> getNextForm(formEntity, applicationEntity)) +// .toList(); +// +// // Return the first matching previous form ID that corresponds to a next form +// return previousFormIds.stream() +// .filter(fieldIds::contains) +// .findFirst().orElse(null); +// } - if (flowEdgesList.isEmpty()) { - return null; + public Long getPreviousForm(FormEntity currentFormEntity, ApplicationEntity applicationEntity) { + + List flowEdgesList = flowEdgesRepository.findByTargetIdAndCallId( + currentFormEntity.getId(), applicationEntity.getCall().getId()); + + if (flowEdgesList.isEmpty()) { + return null; // throw new ResourceNotFoundException(Status.NOT_FOUND, // Translator.toLocale(GepafinConstant.PREVIOUS_FORM_NOT_FOUND)); } - // If only one edge exists, return the source form ID - if (flowEdgesList.size() == 1) { - return flowEdgesList.get(0).getSourceId(); - } + // // If only one edge exists, return the source form ID + // if (flowEdgesList.size() == 1) { + // return flowEdgesList.get(0).getSourceId(); + // } // For multiple edges, find the previous form based on the chosen value - List previousFormIds = flowEdgesList.stream() - .map(FlowEdgesEntity::getSourceId) - .toList(); + List previousFormIds = flowEdgesList.stream() + .map(FlowEdgesEntity::getSourceId) + .toList(); - // Fetch the flow data based on previous form IDs - List flowDataList = flowDataRepository.findByFormIdInAndCallId( - previousFormIds, applicationEntity.getCall().getId()); + List previousForms = formRepository.findByIdIn(previousFormIds); - List chosenValues = flowDataList.stream() - .map(FlowDataEntity::getChoosenValue) - .toList(); + previousForms.sort(Comparator.comparing(FormEntity::getCreatedDate).reversed()); - // Fetch the previous forms based on the chosen field values - Set formList = applicationFormFieldRepository - .findByFieldValueInAndApplicationFormApplicationId(chosenValues, applicationEntity.getId()).stream() - .map(fieldEntity -> fieldEntity.getApplicationForm().getForm()) - .collect(Collectors.toSet()); - - // Find next form IDs recursively for all forms in the formList - List fieldIds = formList.stream() - .map(formEntity -> getNextForm(formEntity, applicationEntity)) - .toList(); - - // Return the first matching previous form ID that corresponds to a next form - return previousFormIds.stream() - .filter(fieldIds::contains) - .findFirst().orElse(null); + return previousForms.isEmpty() ? null : previousForms.get(0).getId(); } - public NextOrPreviousFormResponse getnextOrPreviousForm(ApplicationEntity applicationEntity, Long formId, FormActionEnum action) { Long calculatedFormId = null; diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/FormRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/FormRepository.java index 6250b21b..db35477f 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/FormRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/FormRepository.java @@ -10,4 +10,6 @@ import java.util.List; public interface FormRepository extends JpaRepository { List findByCallId(Long callId); + + List findByIdIn(List formId); } From 398fb7cc43a7aee1ffe4d67185d879549aebfbec Mon Sep 17 00:00:00 2001 From: rajesh Date: Sun, 22 Sep 2024 13:23:32 +0530 Subject: [PATCH 02/58] created an api to get metadata --- pom.xml | 36 ++++++++++++++++--- .../web/rest/api/SamlApi.java | 30 ++++++++++++++++ .../web/rest/api/impl/SamlApiController.java | 33 +++++++++++++++++ src/main/resources/application-dev.properties | 3 +- .../resources/application-local.properties | 3 +- .../resources/application-testing.properties | 3 +- 6 files changed, 100 insertions(+), 8 deletions(-) create mode 100644 src/main/java/net/gepafin/tendermanagement/web/rest/api/SamlApi.java create mode 100644 src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/SamlApiController.java diff --git a/pom.xml b/pom.xml index 713de99a..ad01e409 100644 --- a/pom.xml +++ b/pom.xml @@ -116,10 +116,6 @@ jjwt-jackson 0.11.5 - - org.springframework.boot - spring-boot-starter-web - jakarta.validation jakarta.validation-api @@ -139,6 +135,37 @@ problem-spring-web 0.23.0 + + + + org.springframework.security + spring-security-saml2-service-provider + + + + + org.opensaml + opensaml-core + 4.0.1 + + + + + + org.opensaml + opensaml-saml-api + 4.0.1 + + + + + + org.opensaml + opensaml-saml-impl + 4.0.1 + + + @@ -152,7 +179,6 @@ org.liquibase liquibase-maven-plugin - 4.20.0 src/main/resources/application.properties diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/SamlApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/SamlApi.java new file mode 100644 index 00000000..54ac52dd --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/SamlApi.java @@ -0,0 +1,30 @@ +package net.gepafin.tendermanagement.web.rest.api; + +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants; + +public interface SamlApi { + + + @Operation(summary = "Api to get SP metadata", + responses = { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @GetMapping(value = "/gw/metadata", + produces = { "application/json" }) + ResponseEntity getMetadata(HttpServletRequest request); + +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/SamlApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/SamlApiController.java new file mode 100644 index 00000000..b9a35be8 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/SamlApiController.java @@ -0,0 +1,33 @@ +package net.gepafin.tendermanagement.web.rest.api.impl; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.saml2.provider.service.metadata.OpenSamlMetadataResolver; +import org.springframework.security.saml2.provider.service.metadata.Saml2MetadataResolver; +import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration; +import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.web.rest.api.SamlApi; + +@RestController +@RequestMapping("${openapi.gepafin.base-path:/v1/saml}") +public class SamlApiController implements SamlApi{ + + @Autowired + private RelyingPartyRegistrationRepository relyingPartyRegistrationRepository; + + @Override + public ResponseEntity getMetadata(HttpServletRequest request) { + Saml2MetadataResolver metadataResolver = new OpenSamlMetadataResolver(); + RelyingPartyRegistration registration = relyingPartyRegistrationRepository.findByRegistrationId("loginumbria"); + return ResponseEntity.status(HttpStatus.OK).header("Content-Type", MediaType.APPLICATION_XML_VALUE) + .body(metadataResolver.resolve(registration)); + + } + +} diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties index 72135766..c160287a 100644 --- a/src/main/resources/application-dev.properties +++ b/src/main/resources/application-dev.properties @@ -5,4 +5,5 @@ spring.datasource.password=vs1pAc9vu07mMcdx93j6WiBS spring.datasource.driver-class-name=org.postgresql.Driver # JPA Configuration -spring.h2.console.enabled=true \ No newline at end of file +spring.h2.console.enabled=true +base-url=https://api-dev-gepafin.memento.credit \ No newline at end of file diff --git a/src/main/resources/application-local.properties b/src/main/resources/application-local.properties index 7ed5944b..6b925e03 100644 --- a/src/main/resources/application-local.properties +++ b/src/main/resources/application-local.properties @@ -5,4 +5,5 @@ spring.datasource.password=root spring.datasource.driver-class-name=org.postgresql.Driver # JPA Configuration -spring.jpa.show-sql=true \ No newline at end of file +spring.jpa.show-sql=true +base-url=http://localhost:8080 \ No newline at end of file diff --git a/src/main/resources/application-testing.properties b/src/main/resources/application-testing.properties index ea3a5732..12b95acb 100644 --- a/src/main/resources/application-testing.properties +++ b/src/main/resources/application-testing.properties @@ -4,4 +4,5 @@ spring.datasource.username=sa spring.datasource.password=sa # JPA Configuration -spring.h2.console.enabled=true \ No newline at end of file +spring.h2.console.enabled=true +base-url=http://localhost:8080 \ No newline at end of file From d2df445edf5afc136e1123ce07b9d7c436111fd2 Mon Sep 17 00:00:00 2001 From: rajesh Date: Mon, 23 Sep 2024 13:31:02 +0530 Subject: [PATCH 03/58] updated code --- .../config/SecurityConfig.java | 186 +++++++++++++++--- .../entities/SamlResponseLogEntity.java | 26 +++ .../SamlResponseLogRepository.java | 11 ++ .../web/rest/api/impl/SamlApiController.java | 6 + src/main/resources/application.properties | 1 + .../db/changelog/db.changelog-1.0.0.xml | 26 +++ 6 files changed, 232 insertions(+), 24 deletions(-) create mode 100644 src/main/java/net/gepafin/tendermanagement/entities/SamlResponseLogEntity.java create mode 100644 src/main/java/net/gepafin/tendermanagement/repositories/SamlResponseLogRepository.java diff --git a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java index e06c3e4b..22ac7dff 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java @@ -1,6 +1,18 @@ package net.gepafin.tendermanagement.config; - +import java.io.File; +import java.io.FileInputStream; +import java.io.FileReader; +import java.io.InputStream; +import java.security.KeyFactory; +import java.security.PrivateKey; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.security.spec.PKCS8EncodedKeySpec; +import org.bouncycastle.util.io.pem.PemReader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; @@ -14,6 +26,11 @@ import org.springframework.security.config.annotation.web.configurers.AbstractHt 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.saml2.core.Saml2X509Credential; +import org.springframework.security.saml2.provider.service.registration.InMemoryRelyingPartyRegistrationRepository; +import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration; +import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository; +import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher; @@ -23,6 +40,8 @@ import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; import org.springframework.web.servlet.handler.HandlerMappingIntrospector; +import com.fasterxml.jackson.databind.ObjectMapper; + import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.security.SecurityRequirement; @@ -30,24 +49,29 @@ import io.swagger.v3.oas.models.security.SecurityScheme; import io.swagger.v3.oas.models.servers.Server; import net.gepafin.tendermanagement.config.jwt.JWTFilter; import net.gepafin.tendermanagement.config.jwt.TokenProvider; - +import net.gepafin.tendermanagement.entities.SamlResponseLogEntity; +import net.gepafin.tendermanagement.repositories.SamlResponseLogRepository; @Configuration @EnableWebSecurity @EnableMethodSecurity(prePostEnabled = true) public class SecurityConfig { - + private final Logger logger = LoggerFactory.getLogger(SecurityConfig.class); private final TokenProvider tokenProvider; - + + @Value("${base-url}") + String baseUrl; + + @Autowired + private SamlResponseLogRepository samlResponseLogRepository; + @Autowired public SecurityConfig(TokenProvider tokenProvider) { this.tokenProvider = tokenProvider; } - @Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception { return config.getAuthenticationManager(); } - @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); @@ -75,8 +99,8 @@ public class SecurityConfig { CorsConfiguration config = new CorsConfiguration(); config.addAllowedOrigin("*"); - config.addAllowedMethod("*"); - config.addAllowedHeader("*"); + config.addAllowedMethod("*"); + config.addAllowedHeader("*"); config.setMaxAge(3600l); if (config.getAllowedOrigins() != null && !config.getAllowedOrigins().isEmpty()) { @@ -86,24 +110,91 @@ public class SecurityConfig { } return new CorsFilter(source); } - - @Bean - public SecurityFilterChain securityFilterChain(HttpSecurity http, MvcRequestMatcher.Builder mvc) throws Exception { - http - .csrf(AbstractHttpConfigurer::disable) - .authorizeHttpRequests(auth -> auth - .requestMatchers(mvc.pattern(HttpMethod.POST, "/v1/user/login")).permitAll() - .requestMatchers("/swagger-ui/**").permitAll() - .requestMatchers("/v1/api-docs/**").permitAll() - .anyRequest().authenticated() - ) - .sessionManagement(session -> session - .sessionCreationPolicy(SessionCreationPolicy.STATELESS) - ) + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http.csrf(AbstractHttpConfigurer::disable).authorizeHttpRequests(auth -> auth + // Allow public access to the login endpoints + .requestMatchers("/v1/user/login").permitAll() // JWT-based login + .requestMatchers("/v1/saml/**").permitAll() // JWT-based login + .requestMatchers("/saml2/**").permitAll() // SAML login initiation + .requestMatchers("/swagger-ui/**").permitAll() // Swagger docs + .requestMatchers("/v1/api-docs/**").permitAll() // API docs + .anyRequest().authenticated()) + .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .addFilterBefore(corsFilter(), UsernamePasswordAuthenticationFilter.class) - .addFilterBefore(new JWTFilter(tokenProvider), UsernamePasswordAuthenticationFilter.class); + .addFilterBefore(new JWTFilter(tokenProvider), UsernamePasswordAuthenticationFilter.class) + // Add SAML2 login configuration (for BENEFICIARI) + /* + * .saml2Login(saml -> saml.loginPage("/saml/login") // Entry point for SAML + * login .defaultSuccessUrl("/") // Redirect after successful SAML login ); + */ + .saml2Login(saml -> + saml.defaultSuccessUrl("/") + .successHandler((request, response, authentication) -> { + logger.error("SAML success login"); + SamlResponseLogEntity samlResponseLogEntity = new SamlResponseLogEntity(); + samlResponseLogEntity.setRequest(request.toString()); + samlResponseLogEntity.setResponse(response.toString()); + samlResponseLogEntity.setAuthenticationObject(authentication.toString()); + samlResponseLogRepository.save(samlResponseLogEntity); + try { + ObjectMapper objectMapper = new ObjectMapper(); + // Create a new SAML log entity + SamlResponseLogEntity samlResponseLogEntity1 = new SamlResponseLogEntity(); + // Convert request, response, and authentication to JSON format + String requestJson = objectMapper.writeValueAsString(request.getParameterMap()); // Assuming request params to JSON + String responseJson = objectMapper.writeValueAsString(response); // This may need to be adapted based on your response object + String authenticationJson = objectMapper.writeValueAsString(authentication); // Authentication object to JSON + + // Set the JSON strings in the entity + samlResponseLogEntity1.setRequest(requestJson); + samlResponseLogEntity1.setResponse(responseJson); + samlResponseLogEntity1.setAuthenticationObject(authenticationJson); + samlResponseLogRepository.save(samlResponseLogEntity1); + + logger.info("SAML Request: " + requestJson); + logger.info("SAML Response: " + responseJson); + logger.info("Authentication Details: " + authenticationJson); + }catch(Exception e) { + logger.info("Exception object" + e); + } +// samlResponseLogRepository + logger.info("SAML login successful for user: " + authentication.getName()); + response.sendRedirect("http://gepafin-staging-fe.s3-website.eu-central-1.amazonaws.com/"); + }).failureHandler((request, response, exception) -> { + logger.error("SAML login failed: " + exception.getMessage()); + + SamlResponseLogEntity samlResponseLogEntity = new SamlResponseLogEntity(); + samlResponseLogEntity.setRequest(request.toString()); + samlResponseLogEntity.setResponse(response.toString()); + samlResponseLogEntity.setExceptionObject(exception.toString()); + samlResponseLogRepository.save(samlResponseLogEntity); + try { + ObjectMapper objectMapper = new ObjectMapper(); + + // Create a new SAML log entity + SamlResponseLogEntity samlResponseLogEntity1 = new SamlResponseLogEntity(); + + // Convert request, response, and authentication to JSON format + String requestJson = objectMapper.writeValueAsString(request.getParameterMap()); // Assuming request params to JSON + String responseJson = objectMapper.writeValueAsString(response); // This may need to be adapted based on your response object + String exceptionJson = objectMapper.writeValueAsString(exception); // Authentication object to JSON + + // Set the JSON strings in the entity + samlResponseLogEntity1.setRequest(requestJson); + samlResponseLogEntity1.setResponse(responseJson); + samlResponseLogEntity1.setAuthenticationObject(exceptionJson); + samlResponseLogRepository.save(samlResponseLogEntity1); + + logger.info("SAML Request: " + requestJson); + logger.info("SAML Response: " + responseJson); + logger.info("exception Details: " + exceptionJson); + }catch(Exception e) { + logger.info("Exception object" + e); + } + response.sendRedirect("http://gepafin-staging-fe.s3-website.eu-central-1.amazonaws.com/login"); + })); return http.build(); } @@ -116,4 +207,51 @@ public class SecurityConfig { new SecurityScheme().type(SecurityScheme.Type.HTTP) .scheme("bearer").bearerFormat("JWT"))); } -} + + @Bean + public RelyingPartyRegistrationRepository relyingPartyRegistrationRepository() { + + String entityId = baseUrl + "/v1/saml/gw/metadata"; + String acsUrl = baseUrl + "/login/saml2/sso/loginumbria"; + RelyingPartyRegistration registration = RelyingPartyRegistration.withRegistrationId("loginumbria") + .entityId(entityId) + .signingX509Credentials(credentials -> { + try { + credentials.add(Saml2X509Credential.signing(readPrivateKey(), readCertificate())); + } catch (Exception e) { + e.printStackTrace(); + } + }) + .assertionConsumerServiceLocation(acsUrl) + .assertingPartyDetails(details -> details.entityId("https://federatest.umbriadigitale.it/gw/metadata") + .singleSignOnServiceLocation("https://federatest.umbriadigitale.it/gw/SSOProxy/SAML2") + .singleSignOnServiceBinding(Saml2MessageBinding.POST).wantAuthnRequestsSigned(false) + ) + .build(); + return new InMemoryRelyingPartyRegistrationRepository(registration); + } + + + + public PrivateKey readPrivateKey() throws Exception { + // Path to your private key PEM file + File privateKeyFile = new File("src/main/resources/dev/saml/private-key.pem"); + try (PemReader pemReader = new PemReader(new FileReader(privateKeyFile))) { + // Read the PEM content + byte[] pemContent = pemReader.readPemObject().getContent(); + // Decode the PEM content + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pemContent); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); // Use RSA algorithm + // Generate and return the PrivateKey + return keyFactory.generatePrivate(keySpec); + } + } + public X509Certificate readCertificate() throws Exception { + // Path to your certificate PEM fileFile + File certFile = new File("src/main/resources/dev/saml/public-cert.pem"); + try (InputStream inStream = new FileInputStream(certFile)) { + CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); + return (X509Certificate) certFactory.generateCertificate(inStream); + } + } +} \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/entities/SamlResponseLogEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/SamlResponseLogEntity.java new file mode 100644 index 00000000..53e262e9 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/entities/SamlResponseLogEntity.java @@ -0,0 +1,26 @@ +package net.gepafin.tendermanagement.entities; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; +import lombok.Data; + +@Entity +@Table(name = "SAML_RESPONSE_LOG") +@Data +public class SamlResponseLogEntity extends BaseEntity{ + + @Column(name = "REQUEST") + private String request; + + @Column(name = "RESPONSE") + private String response; + + @Column(name = "AUTHENTICATION_OBJECT") + private String authenticationObject; + + @Column(name = "EXCEPTION_OBJECT") + private String exceptionObject; + + +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/SamlResponseLogRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/SamlResponseLogRepository.java new file mode 100644 index 00000000..3f98e083 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/repositories/SamlResponseLogRepository.java @@ -0,0 +1,11 @@ +package net.gepafin.tendermanagement.repositories; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import net.gepafin.tendermanagement.entities.SamlResponseLogEntity; + +@Repository +public interface SamlResponseLogRepository extends JpaRepository { + +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/SamlApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/SamlApiController.java index b9a35be8..f49b9fa5 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/SamlApiController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/SamlApiController.java @@ -1,5 +1,7 @@ package net.gepafin.tendermanagement.web.rest.api.impl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -12,17 +14,21 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.config.SecurityConfig; import net.gepafin.tendermanagement.web.rest.api.SamlApi; @RestController @RequestMapping("${openapi.gepafin.base-path:/v1/saml}") public class SamlApiController implements SamlApi{ + private final Logger logger = LoggerFactory.getLogger(SecurityConfig.class); + @Autowired private RelyingPartyRegistrationRepository relyingPartyRegistrationRepository; @Override public ResponseEntity getMetadata(HttpServletRequest request) { + logger.info("get SP metadata"); Saml2MetadataResolver metadataResolver = new OpenSamlMetadataResolver(); RelyingPartyRegistration registration = relyingPartyRegistrationRepository.findByRegistrationId("loginumbria"); return ResponseEntity.status(HttpStatus.OK).header("Content-Type", MediaType.APPLICATION_XML_VALUE) diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 07fcf32f..1b6634c5 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -35,6 +35,7 @@ aws.s3.url.folder=gepafin # Ensure these values match your expectations security.authentication.jwt.secret=my-secret-token-to-change-in-prod-environment-your-super-secure-randomly-generated-key security.authentication.jwt.token-validity-in-seconds=86400 +base-url=https://api-dev-gepafin.memento.credit spring.main.allow-circular-references=true diff --git a/src/main/resources/db/changelog/db.changelog-1.0.0.xml b/src/main/resources/db/changelog/db.changelog-1.0.0.xml index f4a78969..d7377f5c 100644 --- a/src/main/resources/db/changelog/db.changelog-1.0.0.xml +++ b/src/main/resources/db/changelog/db.changelog-1.0.0.xml @@ -710,4 +710,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + From 29b94c7bd7ed8b25e7717bc921e14131a85e53be Mon Sep 17 00:00:00 2001 From: rajesh Date: Mon, 23 Sep 2024 15:01:43 +0530 Subject: [PATCH 04/58] updated private and public key --- src/main/resources/dev/saml/private-key.pem | 28 +++++++++++++++++++++ src/main/resources/dev/saml/public-cert.pem | 24 ++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 src/main/resources/dev/saml/private-key.pem create mode 100644 src/main/resources/dev/saml/public-cert.pem diff --git a/src/main/resources/dev/saml/private-key.pem b/src/main/resources/dev/saml/private-key.pem new file mode 100644 index 00000000..9302e091 --- /dev/null +++ b/src/main/resources/dev/saml/private-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCsCrXQyDN5nURj +2LB1wJKRIOzO8tgIXxPHVL65dYv7cOql01b5LpmUGQaGfUKALlvEdPs0NwCSdiyz +MGAMTD81KHLqa+Wdm5ySl82ONRGl15pmHQFJlUDFpOr5+r1AZvQdh9MfdcbWW57m +4qaDEF3kvihIZg9PMbqlQjHOrcG1iUPzpHnzcnmevpP32MH2FSYZhy+b0Ie2Fsho +3Aj7CvmJYlBWfCaFLQ/wi8FsDEhjsOlUUkcr7/giO3ygK57oPzcld74g4x79A/UH +VbUe2+CUxzFqP9+VtDWGqJ7lp0bHA/lfGvmDvIJAY6UDyYfum1Vn/ag2NmvW5wLH +Z8vdLP75AgMBAAECggEABJ5u/jF5zFCQFvwo1Kh8ZuAS64Vyjlr7HXVlf3Yr8W65 +JgWUBrGdFvBLEA5J3EYiWZZobiDx53y7u33Xfk0Hv2YcG7YU3pPgcsEXmDNNi33L +2+T4dWDH8eZ5FogIT7PT5v0QCn6vfW7NR9aa8NbeJneCflsbGx2zLJ+n1awtkLGY +6vFSwl/xzRCClWCccT64+8/b2btLEDFa4IK5KdMoiP/t1fM51vu3DmPBgWt2ZWH1 +cPcd2GSXPaEyHECUAYV7/HpY5I+2xD8W3YJLaGmSeavsuW726ygUaYDsX3L3EPP8 +/AIPwhI0uLRLT2zRfH9BzPqJL+A1gnFR/BysVWnKQQKBgQDm6myujHrpe1A92j8v +E3nTmaigCAdIhJSkoOjcvHxcHacJtK/QN4zmQvOtHwn9NAOz0jvMgJUM2Pd6t4MV +1vWSFZam9P6EkNkmhg94V2FnQlas329XIfLWdVqfVsTxbyhIICRLBmBgn3Z22ugw +FU5rYoZw7mjP/Gqhv3hYNH2dcQKBgQC+uw01Jh51JclSkT2lh5M2xwovnA74HuWT +d/w9smXS3hi1TJn0ECVJKagZXhwAIgVntxzV93Vz3++VvX3LeM81eOD2vTpTR+MP +mZ8lwsCxKDABZfoFV79lrO+8I61e4pSgcRSK0uqsvFmlN1agL+hn6esBrZe4IV37 +Hvk1OobWCQKBgFtJ8B9tcCYf1xAs2O/Ofko2JCDoK6DysSUIbCbf6TYtjtzabusd +GvnpHBaj/7n3N0N+6J8nckV6/ROpuwwGSF0xZbapgnl8Hi0JsNH9kYdWBZggWQ8U +X8GC8YmurvtX24/wDQkQA0gPorDISCTCN5digw3gYtVez/UUEgqk7cgxAoGADA3q +YceM+T5wIOXJDaMp7LZbsHKeh5P8Unus14Fk6hTbXun+eOxkTuFxHFlUT7XWvZ1X +FzbSl4Y5sC8PukJiZjDDlxSSkRzj/uJoqoxKfWfa0NvPF3NaR2TMqglfNbYASrua +3sNBzbUBvW1n7ivY9mhUUADWq+5/8BUfDvwp9XECgYEAxfclKcPbns4Hm5N0/tGV +aTCvlwXIWIYa5krewof1bfW/APS917MZEfIMvVUJOtLU+iD9OJnZOMtA3qFDcWN6 +gnkQui8RpmJKteLf2eemfP6owWhMG5AZZjcinLTjHbiWFnjs8HLsj8931pGxSSUD +aR7D9CcLcEUqi8EaeNukmbA= +-----END PRIVATE KEY----- diff --git a/src/main/resources/dev/saml/public-cert.pem b/src/main/resources/dev/saml/public-cert.pem new file mode 100644 index 00000000..b88d60cb --- /dev/null +++ b/src/main/resources/dev/saml/public-cert.pem @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIID+zCCAuOgAwIBAgIUBKj5WxwQRn0Ro0lChsMb+NZOnTMwDQYJKoZIhvcNAQEL +BQAwgYwxCzAJBgNVBAYTAklUMQ8wDQYDVQQIDAZVbWJyaWExEDAOBgNVBAcMB1Bl +cnVnaWExEDAOBgNVBAoMB0dlcGFmaW4xCzAJBgNVBAsMAklUMRAwDgYDVQQDDAdH +ZXBhZmluMSkwJwYJKoZIhvcNAQkBFhpyaW5hbGRvLmJvbmF6em9AYmZsb3dzLm5l +dDAeFw0yNDA5MjMwODUxMTlaFw0yNTA5MjMwODUxMTlaMIGMMQswCQYDVQQGEwJJ +VDEPMA0GA1UECAwGVW1icmlhMRAwDgYDVQQHDAdQZXJ1Z2lhMRAwDgYDVQQKDAdH +ZXBhZmluMQswCQYDVQQLDAJJVDEQMA4GA1UEAwwHR2VwYWZpbjEpMCcGCSqGSIb3 +DQEJARYacmluYWxkby5ib25henpvQGJmbG93cy5uZXQwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQCsCrXQyDN5nURj2LB1wJKRIOzO8tgIXxPHVL65dYv7 +cOql01b5LpmUGQaGfUKALlvEdPs0NwCSdiyzMGAMTD81KHLqa+Wdm5ySl82ONRGl +15pmHQFJlUDFpOr5+r1AZvQdh9MfdcbWW57m4qaDEF3kvihIZg9PMbqlQjHOrcG1 +iUPzpHnzcnmevpP32MH2FSYZhy+b0Ie2Fsho3Aj7CvmJYlBWfCaFLQ/wi8FsDEhj +sOlUUkcr7/giO3ygK57oPzcld74g4x79A/UHVbUe2+CUxzFqP9+VtDWGqJ7lp0bH +A/lfGvmDvIJAY6UDyYfum1Vn/ag2NmvW5wLHZ8vdLP75AgMBAAGjUzBRMB0GA1Ud +DgQWBBTSz8YB9ACNsuoGwrhtGt4ct+Bm3DAfBgNVHSMEGDAWgBTSz8YB9ACNsuoG +wrhtGt4ct+Bm3DAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAB +3xJ2OQBI4VgICN4ohZ+Bfq4pHkJgZUV202mC8XLiCx1oihpi1ew25zu5BdNUgDn8 +dlMzx8MeMa4aRCKg5Xdio956ea1iPx4n0UafbnU13p2oLGTSDKRuYOidDcFF/fl4 +77nVAa8THc9GKaIQ1jvOnZ5+Sq0dKA2ZjT4sXciuEgrdsPM5CSjHNSSN9dwceGVZ +OWyta0NViqQh1DFfLv1Tqkt3vaEcKRGqWlXryHmRSlmTrAiTFF4LE4eYMiUrlIbq +P4R1R0w7fVXRufJkpiTAzrmQa5xTr5/9w8zTDuFxVHAQ23vMn9uB+P4ZUDu6ZoDP +khKe3VzuKIBSKiSfiuFY +-----END CERTIFICATE----- From 6f2bb714e10476d0cf45169a7fa4380d91974281 Mon Sep 17 00:00:00 2001 From: rajesh Date: Mon, 23 Sep 2024 15:15:46 +0530 Subject: [PATCH 05/58] removed flow smells --- .../java/net/gepafin/tendermanagement/web/rest/api/FlowApi.java | 2 -- .../tendermanagement/web/rest/api/impl/FlowApiController.java | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/FlowApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/FlowApi.java index 61115f63..218ed5ff 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/FlowApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/FlowApi.java @@ -9,7 +9,6 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.Valid; import net.gepafin.tendermanagement.model.request.FlowRequestBean; import net.gepafin.tendermanagement.model.response.FlowResponseBean; -import net.gepafin.tendermanagement.model.response.FormResponseBean; import net.gepafin.tendermanagement.model.util.Response; import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants; import org.springframework.http.MediaType; @@ -18,7 +17,6 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import java.util.List; @Validated public interface FlowApi { diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/FlowApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/FlowApiController.java index 6245a420..68cb183b 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/FlowApiController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/FlowApiController.java @@ -12,11 +12,9 @@ import net.gepafin.tendermanagement.web.rest.api.errors.Status; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import java.util.List; @RestController @RequestMapping("${openapi.gepafin.base-path:/v1/flow}") From 59d895108966cabc34397f0d0ca1c7a84aa30442 Mon Sep 17 00:00:00 2001 From: rbonazzo-KZ <66477605+rbonazzo-KZ@users.noreply.github.com> Date: Mon, 23 Sep 2024 12:48:57 +0200 Subject: [PATCH 06/58] Update Dockerfile --- Dockerfile | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 22070bd1..d1f3b45a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,9 @@ FROM amazoncorretto:17.0.8-alpine3.17 EXPOSE 8080 +# Create the folder in the docker image +RUN mkdir -pv /foldername/keys + +ADD /src/main/resources/dev/saml/public-cert.pem foldername/keys/public-cert.pem +ADD /src/main/resources/dev/saml/private-key.pem /foldername/keys/private-key.pem ADD /target/tendermanagement-0.0.1-SNAPSHOT.jar tendermanagement-0.0.1-SNAPSHOT.jar -ENTRYPOINT ["java", "-jar","tendermanagement-0.0.1-SNAPSHOT.jar"] \ No newline at end of file +ENTRYPOINT ["java", "-jar","tendermanagement-0.0.1-SNAPSHOT.jar"] From f92c4fb7b94be60c7288e0bcb5e67f690660dc6a Mon Sep 17 00:00:00 2001 From: rajesh Date: Mon, 23 Sep 2024 17:47:51 +0530 Subject: [PATCH 07/58] updated code for keys --- Dockerfile | 5 ----- .../config/SecurityConfig.java | 22 +++++++++++++------ 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/Dockerfile b/Dockerfile index d1f3b45a..ceacf16e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,4 @@ FROM amazoncorretto:17.0.8-alpine3.17 EXPOSE 8080 -# Create the folder in the docker image -RUN mkdir -pv /foldername/keys - -ADD /src/main/resources/dev/saml/public-cert.pem foldername/keys/public-cert.pem -ADD /src/main/resources/dev/saml/private-key.pem /foldername/keys/private-key.pem ADD /target/tendermanagement-0.0.1-SNAPSHOT.jar tendermanagement-0.0.1-SNAPSHOT.jar ENTRYPOINT ["java", "-jar","tendermanagement-0.0.1-SNAPSHOT.jar"] diff --git a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java index 22ac7dff..ae30d29e 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java @@ -1,8 +1,8 @@ package net.gepafin.tendermanagement.config; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileReader; +import java.io.FileNotFoundException; +import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.cert.CertificateFactory; @@ -235,8 +235,7 @@ public class SecurityConfig { public PrivateKey readPrivateKey() throws Exception { // Path to your private key PEM file - File privateKeyFile = new File("src/main/resources/dev/saml/private-key.pem"); - try (PemReader pemReader = new PemReader(new FileReader(privateKeyFile))) { + try (PemReader pemReader = new PemReader(new InputStreamReader(readKey("dev/saml/private-key.pem")))) { // Read the PEM content byte[] pemContent = pemReader.readPemObject().getContent(); // Decode the PEM content @@ -248,10 +247,19 @@ public class SecurityConfig { } public X509Certificate readCertificate() throws Exception { // Path to your certificate PEM fileFile - File certFile = new File("src/main/resources/dev/saml/public-cert.pem"); - try (InputStream inStream = new FileInputStream(certFile)) { + try (InputStream inStream = readKey("dev/saml/public-cert.pem")) { CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); return (X509Certificate) certFactory.generateCertificate(inStream); } } + + public InputStream readKey(String path) throws IOException { + ClassLoader classLoader = getClass().getClassLoader(); + InputStream inputStream = classLoader.getResourceAsStream(path); + + if (inputStream == null) { + throw new FileNotFoundException("file not found : "+path); + } + return inputStream; + } } \ No newline at end of file From afbdd70f6bbc25e1fe9f6763381e0ee335311959 Mon Sep 17 00:00:00 2001 From: rajesh Date: Mon, 23 Sep 2024 18:33:45 +0530 Subject: [PATCH 08/58] Updated code --- .../java/net/gepafin/tendermanagement/dao/FlowFormDao.java | 6 +++--- src/main/java/net/gepafin/tendermanagement/dao/FormDao.java | 4 +++- .../repositories/ApplicationFormRepository.java | 1 + 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java b/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java index f46e61f5..a6f6a867 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java @@ -243,11 +243,11 @@ public class FlowFormDao { .map(FlowEdgesEntity::getSourceId) .toList(); - List previousForms = formRepository.findByIdIn(previousFormIds); + List applicationFormEntities=applicationFormRepository.findByFormIdInAndApplicationId(previousFormIds,applicationEntity.getId()); - previousForms.sort(Comparator.comparing(FormEntity::getCreatedDate).reversed()); + applicationFormEntities.sort(Comparator.comparing(ApplicationFormEntity::getCreatedDate).reversed()); - return previousForms.isEmpty() ? null : previousForms.get(0).getId(); + return applicationFormEntities.isEmpty() ? null : applicationFormEntities.get(0).getForm().getId(); } public NextOrPreviousFormResponse getnextOrPreviousForm(ApplicationEntity applicationEntity, Long formId, FormActionEnum action) { diff --git a/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java b/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java index 11a27915..57568468 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java @@ -221,7 +221,9 @@ public class FormDao { .validateCustom(value, fieldValidatorBean.getCustom(), fieldId); // Add the custom validation here if (fieldValidatorBean.getCustom() != null && fieldValidatorBean.getCustom().equals(GepafinConstant.IS_PIVA)) { String error = validateVatNumber(value, fieldValidatorBean.getCustom(), fieldId); - validator.addError(error); + if(error != null) { + validator.addError(error); + } } }); validator.validate(); diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationFormRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationFormRepository.java index 992eece3..1037402a 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationFormRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationFormRepository.java @@ -17,4 +17,5 @@ public interface ApplicationFormRepository extends JpaRepository findByApplicationIdOrderByCreatedDateAsc(Long applicationId); + public List findByFormIdInAndApplicationId(List formIds,Long applicationId); } From dc0640e21125d694657200da3be797dc124089a5 Mon Sep 17 00:00:00 2001 From: rajesh Date: Mon, 23 Sep 2024 20:21:24 -0700 Subject: [PATCH 09/58] Updated config --- .../net/gepafin/tendermanagement/config/SecurityConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java index ae30d29e..d5ad81e6 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java @@ -225,7 +225,7 @@ public class SecurityConfig { .assertionConsumerServiceLocation(acsUrl) .assertingPartyDetails(details -> details.entityId("https://federatest.umbriadigitale.it/gw/metadata") .singleSignOnServiceLocation("https://federatest.umbriadigitale.it/gw/SSOProxy/SAML2") - .singleSignOnServiceBinding(Saml2MessageBinding.POST).wantAuthnRequestsSigned(false) + .singleSignOnServiceBinding(Saml2MessageBinding.POST).wantAuthnRequestsSigned(true) ) .build(); return new InMemoryRelyingPartyRegistrationRepository(registration); From 18b1cff9f0317fd4ef9ca5fdd8fdad17694da6c7 Mon Sep 17 00:00:00 2001 From: rajesh Date: Mon, 23 Sep 2024 21:16:58 -0700 Subject: [PATCH 10/58] Updated config --- .../config/SecurityConfig.java | 56 ++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java index d5ad81e6..73213a77 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java @@ -8,7 +8,14 @@ import java.security.PrivateKey; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.spec.PKCS8EncodedKeySpec; + import org.bouncycastle.util.io.pem.PemReader; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.saml2.core.AuthnContextClassRef; +import org.opensaml.saml.saml2.core.AuthnContextComparisonTypeEnumeration; +import org.opensaml.saml.saml2.core.RequestedAuthnContext; +import org.opensaml.saml.saml2.core.impl.AuthnContextClassRefBuilder; +import org.opensaml.saml.saml2.core.impl.RequestedAuthnContextBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -31,6 +38,10 @@ import org.springframework.security.saml2.provider.service.registration.InMemory import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration; import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository; import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding; +import org.springframework.security.saml2.provider.service.web.DefaultRelyingPartyRegistrationResolver; +import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver; +import org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver; +import org.springframework.security.saml2.provider.service.web.authentication.Saml2AuthenticationRequestResolver; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher; @@ -51,6 +62,9 @@ import net.gepafin.tendermanagement.config.jwt.JWTFilter; import net.gepafin.tendermanagement.config.jwt.TokenProvider; import net.gepafin.tendermanagement.entities.SamlResponseLogEntity; import net.gepafin.tendermanagement.repositories.SamlResponseLogRepository; +//import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationRequestContext; +//import org.springframework.security.saml2.core.Saml2AuthenticationRequest; + @Configuration @EnableWebSecurity @EnableMethodSecurity(prePostEnabled = true) @@ -68,6 +82,17 @@ public class SecurityConfig { public SecurityConfig(TokenProvider tokenProvider) { this.tokenProvider = tokenProvider; } +// +// @Bean +// public Saml2AuthenticationRequestResolver authenticationRequestResolver() { +// return (Saml2AuthenticationRequestContext context) -> { +// Saml2AuthenticationRequest request = Saml2AuthenticationRequest.withAuthenticationRequestContext(context) +// .authenticationContextClassRef("urn:oasis:names:tc:SAML:2.0:ac:classes:SecureRemotePassword") // Add context here +// .build(); +// return request; +// }; +// } + @Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception { return config.getAuthenticationManager(); @@ -225,12 +250,41 @@ public class SecurityConfig { .assertionConsumerServiceLocation(acsUrl) .assertingPartyDetails(details -> details.entityId("https://federatest.umbriadigitale.it/gw/metadata") .singleSignOnServiceLocation("https://federatest.umbriadigitale.it/gw/SSOProxy/SAML2") - .singleSignOnServiceBinding(Saml2MessageBinding.POST).wantAuthnRequestsSigned(true) + .singleSignOnServiceBinding(Saml2MessageBinding.POST).wantAuthnRequestsSigned(true).build() ) .build(); return new InMemoryRelyingPartyRegistrationRepository(registration); } + @Bean + public Saml2AuthenticationRequestResolver authenticationRequestResolver(RelyingPartyRegistrationRepository registrations) { + RelyingPartyRegistrationResolver registrationResolver = new DefaultRelyingPartyRegistrationResolver(registrations); + OpenSaml4AuthenticationRequestResolver authenticationRequestResolver = new OpenSaml4AuthenticationRequestResolver(registrationResolver); + + // Customize the AuthnRequest with the authentication context + authenticationRequestResolver.setAuthnRequestCustomizer((context) -> { + context.getAuthnRequest().setRequestedAuthnContext(buildRequestedAuthnContext()); + }); + + return authenticationRequestResolver; + } + + private RequestedAuthnContext buildRequestedAuthnContext() { + AuthnContextClassRefBuilder authnContextClassRefBuilder = new AuthnContextClassRefBuilder(); + AuthnContextClassRef authnContextClassRef = authnContextClassRefBuilder.buildObject( + SAMLConstants.SAML20_NS, AuthnContextClassRef.DEFAULT_ELEMENT_LOCAL_NAME, SAMLConstants.SAML20_PREFIX + ); + + // Set the SPID Level 2 authentication context + authnContextClassRef.setURI("urn:oasis:names:tc:SAML:2.0:ac:classes:SecureRemotePassword"); + + RequestedAuthnContextBuilder requestedAuthnContextBuilder = new RequestedAuthnContextBuilder(); + RequestedAuthnContext requestedAuthnContext = requestedAuthnContextBuilder.buildObject(); + requestedAuthnContext.setComparison(AuthnContextComparisonTypeEnumeration.EXACT); + requestedAuthnContext.getAuthnContextClassRefs().add(authnContextClassRef); + + return requestedAuthnContext; + } public PrivateKey readPrivateKey() throws Exception { From c018757df831d7de6c910827fe20928bc5579321 Mon Sep 17 00:00:00 2001 From: rajesh Date: Mon, 23 Sep 2024 21:28:41 -0700 Subject: [PATCH 11/58] Updated config --- .../gepafin/tendermanagement/config/SecurityConfig.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java index 73213a77..409a4bb8 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java @@ -261,14 +261,19 @@ public class SecurityConfig { RelyingPartyRegistrationResolver registrationResolver = new DefaultRelyingPartyRegistrationResolver(registrations); OpenSaml4AuthenticationRequestResolver authenticationRequestResolver = new OpenSaml4AuthenticationRequestResolver(registrationResolver); - // Customize the AuthnRequest with the authentication context + // Customize and log the AuthnRequest after setting the context authenticationRequestResolver.setAuthnRequestCustomizer((context) -> { context.getAuthnRequest().setRequestedAuthnContext(buildRequestedAuthnContext()); + + // Log the SAML AuthnRequest after setting the authentication context + String samlRequest = context.getAuthnRequest().toString(); // Get the updated AuthnRequest + logger.info("SAML AuthnRequest after setting context: " + samlRequest); // Log the updated SAML request }); return authenticationRequestResolver; } + private RequestedAuthnContext buildRequestedAuthnContext() { AuthnContextClassRefBuilder authnContextClassRefBuilder = new AuthnContextClassRefBuilder(); AuthnContextClassRef authnContextClassRef = authnContextClassRefBuilder.buildObject( From d9c428262add4a251ede02333f444a6c8f1696b6 Mon Sep 17 00:00:00 2001 From: rajesh Date: Mon, 23 Sep 2024 21:37:03 -0700 Subject: [PATCH 12/58] Updated config --- .../config/SamlRequestLogger.java | 22 +++++++++++++++++++ .../config/SecurityConfig.java | 4 ++-- 2 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 src/main/java/net/gepafin/tendermanagement/config/SamlRequestLogger.java diff --git a/src/main/java/net/gepafin/tendermanagement/config/SamlRequestLogger.java b/src/main/java/net/gepafin/tendermanagement/config/SamlRequestLogger.java new file mode 100644 index 00000000..fd4d6561 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/config/SamlRequestLogger.java @@ -0,0 +1,22 @@ +package net.gepafin.tendermanagement.config; + +import org.opensaml.core.xml.io.MarshallingException; +import org.opensaml.core.xml.util.XMLObjectSupport; +import org.opensaml.saml.saml2.core.AuthnRequest; +import org.w3c.dom.Element; + +import net.shibboleth.utilities.java.support.xml.SerializeSupport; + +public class SamlRequestLogger { + + public static String convertSAMLObjectToString(AuthnRequest authnRequest) { + try { + Element element = XMLObjectSupport.marshall(authnRequest); + return SerializeSupport.prettyPrintXML(element); // Pretty print XML using SerializeSupport + } catch (MarshallingException e) { + e.printStackTrace(); + return "Error converting SAML object to XML"; + } + } +} + diff --git a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java index 409a4bb8..d9285b8d 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java @@ -266,8 +266,8 @@ public class SecurityConfig { context.getAuthnRequest().setRequestedAuthnContext(buildRequestedAuthnContext()); // Log the SAML AuthnRequest after setting the authentication context - String samlRequest = context.getAuthnRequest().toString(); // Get the updated AuthnRequest - logger.info("SAML AuthnRequest after setting context: " + samlRequest); // Log the updated SAML request + String samlRequest = SamlRequestLogger.convertSAMLObjectToString(context.getAuthnRequest()); + logger.info("SAML AuthnRequest after setting context: " + samlRequest); }); return authenticationRequestResolver; From ab52e844d16bd872ea0c6d2c1d6e6701a36597dd Mon Sep 17 00:00:00 2001 From: rajesh Date: Mon, 23 Sep 2024 21:49:11 -0700 Subject: [PATCH 13/58] Updated config --- .../config/SecurityConfig.java | 65 ++++++++++--------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java index d9285b8d..ac2ade2c 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java @@ -8,11 +8,14 @@ import java.security.PrivateKey; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.spec.PKCS8EncodedKeySpec; +import java.util.UUID; import org.bouncycastle.util.io.pem.PemReader; +import org.opensaml.saml.common.SAMLVersion; import org.opensaml.saml.common.xml.SAMLConstants; import org.opensaml.saml.saml2.core.AuthnContextClassRef; import org.opensaml.saml.saml2.core.AuthnContextComparisonTypeEnumeration; +import org.opensaml.saml.saml2.core.AuthnRequest; import org.opensaml.saml.saml2.core.RequestedAuthnContext; import org.opensaml.saml.saml2.core.impl.AuthnContextClassRefBuilder; import org.opensaml.saml.saml2.core.impl.RequestedAuthnContextBuilder; @@ -256,41 +259,45 @@ public class SecurityConfig { return new InMemoryRelyingPartyRegistrationRepository(registration); } - @Bean - public Saml2AuthenticationRequestResolver authenticationRequestResolver(RelyingPartyRegistrationRepository registrations) { - RelyingPartyRegistrationResolver registrationResolver = new DefaultRelyingPartyRegistrationResolver(registrations); - OpenSaml4AuthenticationRequestResolver authenticationRequestResolver = new OpenSaml4AuthenticationRequestResolver(registrationResolver); - // Customize and log the AuthnRequest after setting the context - authenticationRequestResolver.setAuthnRequestCustomizer((context) -> { - context.getAuthnRequest().setRequestedAuthnContext(buildRequestedAuthnContext()); - - // Log the SAML AuthnRequest after setting the authentication context - String samlRequest = SamlRequestLogger.convertSAMLObjectToString(context.getAuthnRequest()); - logger.info("SAML AuthnRequest after setting context: " + samlRequest); - }); +@Bean +public Saml2AuthenticationRequestResolver authenticationRequestResolver(RelyingPartyRegistrationRepository registrations) { + RelyingPartyRegistrationResolver registrationResolver = new DefaultRelyingPartyRegistrationResolver(registrations); + OpenSaml4AuthenticationRequestResolver authenticationRequestResolver = new OpenSaml4AuthenticationRequestResolver(registrationResolver); - return authenticationRequestResolver; - } + authenticationRequestResolver.setAuthnRequestCustomizer((context) -> { + // Set the required attributes + AuthnRequest authnRequest = context.getAuthnRequest(); + authnRequest.setID("_" + UUID.randomUUID().toString()); // Add a unique ID + authnRequest.setVersion(SAMLVersion.VERSION_20); // Ensure version is 2.0 + authnRequest.setProtocolBinding(SAMLConstants.SAML2_POST_BINDING_URI); // HTTP-POST + // Set Authentication Context + authnRequest.setRequestedAuthnContext(buildRequestedAuthnContext()); - private RequestedAuthnContext buildRequestedAuthnContext() { - AuthnContextClassRefBuilder authnContextClassRefBuilder = new AuthnContextClassRefBuilder(); - AuthnContextClassRef authnContextClassRef = authnContextClassRefBuilder.buildObject( - SAMLConstants.SAML20_NS, AuthnContextClassRef.DEFAULT_ELEMENT_LOCAL_NAME, SAMLConstants.SAML20_PREFIX - ); - - // Set the SPID Level 2 authentication context - authnContextClassRef.setURI("urn:oasis:names:tc:SAML:2.0:ac:classes:SecureRemotePassword"); + // Log the SAML AuthnRequest after setting context + String samlRequest = SamlRequestLogger.convertSAMLObjectToString(authnRequest); + logger.info("SAML AuthnRequest after setting context: " + samlRequest); + }); - RequestedAuthnContextBuilder requestedAuthnContextBuilder = new RequestedAuthnContextBuilder(); - RequestedAuthnContext requestedAuthnContext = requestedAuthnContextBuilder.buildObject(); - requestedAuthnContext.setComparison(AuthnContextComparisonTypeEnumeration.EXACT); - requestedAuthnContext.getAuthnContextClassRefs().add(authnContextClassRef); + return authenticationRequestResolver; +} - return requestedAuthnContext; - } - +private RequestedAuthnContext buildRequestedAuthnContext() { + AuthnContextClassRefBuilder authnContextClassRefBuilder = new AuthnContextClassRefBuilder(); + AuthnContextClassRef authnContextClassRef = authnContextClassRefBuilder.buildObject( + SAMLConstants.SAML20_NS, AuthnContextClassRef.DEFAULT_ELEMENT_LOCAL_NAME, SAMLConstants.SAML20_PREFIX + ); + // Set the SPID Level 2 authentication context + authnContextClassRef.setURI("urn:oasis:names:tc:SAML:2.0:ac:classes:SecureRemotePassword"); + + RequestedAuthnContextBuilder requestedAuthnContextBuilder = new RequestedAuthnContextBuilder(); + RequestedAuthnContext requestedAuthnContext = requestedAuthnContextBuilder.buildObject(); + requestedAuthnContext.setComparison(AuthnContextComparisonTypeEnumeration.EXACT); + requestedAuthnContext.getAuthnContextClassRefs().add(authnContextClassRef); + + return requestedAuthnContext; +} public PrivateKey readPrivateKey() throws Exception { // Path to your private key PEM file From 4cd6b9a606d473f7d26491524a2a1d9b00fca078 Mon Sep 17 00:00:00 2001 From: rajesh Date: Tue, 24 Sep 2024 11:52:07 -0700 Subject: [PATCH 14/58] Updated conifg --- .../config/SecurityConfig.java | 50 ++++++++++++++++--- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java index ac2ade2c..365f2fb7 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java @@ -8,9 +8,11 @@ import java.security.PrivateKey; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.spec.PKCS8EncodedKeySpec; +import java.time.Instant; import java.util.UUID; import org.bouncycastle.util.io.pem.PemReader; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; import org.opensaml.saml.common.SAMLVersion; import org.opensaml.saml.common.xml.SAMLConstants; import org.opensaml.saml.saml2.core.AuthnContextClassRef; @@ -19,6 +21,11 @@ import org.opensaml.saml.saml2.core.AuthnRequest; import org.opensaml.saml.saml2.core.RequestedAuthnContext; import org.opensaml.saml.saml2.core.impl.AuthnContextClassRefBuilder; import org.opensaml.saml.saml2.core.impl.RequestedAuthnContextBuilder; +import org.opensaml.security.x509.BasicX509Credential; +import org.opensaml.xmlsec.config.impl.DefaultSecurityConfigurationBootstrap; +import org.opensaml.xmlsec.signature.Signature; +import org.opensaml.xmlsec.signature.support.SignatureConstants; +import org.opensaml.xmlsec.signature.support.Signer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -36,7 +43,6 @@ import org.springframework.security.config.annotation.web.configurers.AbstractHt 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.saml2.core.Saml2X509Credential; import org.springframework.security.saml2.provider.service.registration.InMemoryRelyingPartyRegistrationRepository; import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration; import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository; @@ -244,11 +250,12 @@ public class SecurityConfig { RelyingPartyRegistration registration = RelyingPartyRegistration.withRegistrationId("loginumbria") .entityId(entityId) .signingX509Credentials(credentials -> { - try { - credentials.add(Saml2X509Credential.signing(readPrivateKey(), readCertificate())); - } catch (Exception e) { - e.printStackTrace(); - } + try { + AuthnRequest signedAuthnRequest = createSignedAuthnRequest(readPrivateKey(), readCertificate()); + logger.info("Signed SAML AuthnRequest: " + SamlRequestLogger.convertSAMLObjectToString(signedAuthnRequest)); + } catch (Exception e) { + e.printStackTrace(); + } }) .assertionConsumerServiceLocation(acsUrl) .assertingPartyDetails(details -> details.entityId("https://federatest.umbriadigitale.it/gw/metadata") @@ -259,6 +266,37 @@ public class SecurityConfig { return new InMemoryRelyingPartyRegistrationRepository(registration); } + public AuthnRequest createSignedAuthnRequest(PrivateKey privateKey, X509Certificate certificate) throws Exception { + AuthnRequest authnRequest = (AuthnRequest) XMLObjectProviderRegistrySupport.getBuilderFactory() + .getBuilder(AuthnRequest.DEFAULT_ELEMENT_NAME) + .buildObject(AuthnRequest.DEFAULT_ELEMENT_NAME); + + authnRequest.setID("_" + UUID.randomUUID().toString()); + authnRequest.setVersion(SAMLVersion.VERSION_20); + // authnRequest.setIssueInstant(new DateTime()); + authnRequest.setIssueInstant(Instant.now()); + + + // Sign the AuthnRequest + // BasicCredential signingCredential = new BasicCredential(certificate, privateKey); + BasicX509Credential signingCredential = new BasicX509Credential(certificate, privateKey); + + Signature signature = (Signature) XMLObjectProviderRegistrySupport.getBuilderFactory() + .getBuilder(Signature.DEFAULT_ELEMENT_NAME) + .buildObject(Signature.DEFAULT_ELEMENT_NAME); + + signature.setSigningCredential(signingCredential); + signature.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1); // Set RSA-SHA1 + + authnRequest.setSignature(signature); + DefaultSecurityConfigurationBootstrap.buildDefaultSignatureSigningConfiguration(); + + // Marshall and sign the object + XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(authnRequest).marshall(authnRequest); + Signer.signObject(signature); + + return authnRequest; + } @Bean public Saml2AuthenticationRequestResolver authenticationRequestResolver(RelyingPartyRegistrationRepository registrations) { From b765d53d6652b66226a1985066228249cdc37c05 Mon Sep 17 00:00:00 2001 From: rajesh Date: Tue, 24 Sep 2024 11:58:53 +0530 Subject: [PATCH 15/58] Revert "Updated conifg" This reverts commit 4cd6b9a606d473f7d26491524a2a1d9b00fca078. --- .../config/SecurityConfig.java | 50 +++---------------- 1 file changed, 6 insertions(+), 44 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java index 365f2fb7..ac2ade2c 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java @@ -8,11 +8,9 @@ import java.security.PrivateKey; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.spec.PKCS8EncodedKeySpec; -import java.time.Instant; import java.util.UUID; import org.bouncycastle.util.io.pem.PemReader; -import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; import org.opensaml.saml.common.SAMLVersion; import org.opensaml.saml.common.xml.SAMLConstants; import org.opensaml.saml.saml2.core.AuthnContextClassRef; @@ -21,11 +19,6 @@ import org.opensaml.saml.saml2.core.AuthnRequest; import org.opensaml.saml.saml2.core.RequestedAuthnContext; import org.opensaml.saml.saml2.core.impl.AuthnContextClassRefBuilder; import org.opensaml.saml.saml2.core.impl.RequestedAuthnContextBuilder; -import org.opensaml.security.x509.BasicX509Credential; -import org.opensaml.xmlsec.config.impl.DefaultSecurityConfigurationBootstrap; -import org.opensaml.xmlsec.signature.Signature; -import org.opensaml.xmlsec.signature.support.SignatureConstants; -import org.opensaml.xmlsec.signature.support.Signer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -43,6 +36,7 @@ import org.springframework.security.config.annotation.web.configurers.AbstractHt 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.saml2.core.Saml2X509Credential; import org.springframework.security.saml2.provider.service.registration.InMemoryRelyingPartyRegistrationRepository; import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration; import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository; @@ -250,12 +244,11 @@ public class SecurityConfig { RelyingPartyRegistration registration = RelyingPartyRegistration.withRegistrationId("loginumbria") .entityId(entityId) .signingX509Credentials(credentials -> { - try { - AuthnRequest signedAuthnRequest = createSignedAuthnRequest(readPrivateKey(), readCertificate()); - logger.info("Signed SAML AuthnRequest: " + SamlRequestLogger.convertSAMLObjectToString(signedAuthnRequest)); - } catch (Exception e) { - e.printStackTrace(); - } + try { + credentials.add(Saml2X509Credential.signing(readPrivateKey(), readCertificate())); + } catch (Exception e) { + e.printStackTrace(); + } }) .assertionConsumerServiceLocation(acsUrl) .assertingPartyDetails(details -> details.entityId("https://federatest.umbriadigitale.it/gw/metadata") @@ -266,37 +259,6 @@ public class SecurityConfig { return new InMemoryRelyingPartyRegistrationRepository(registration); } - public AuthnRequest createSignedAuthnRequest(PrivateKey privateKey, X509Certificate certificate) throws Exception { - AuthnRequest authnRequest = (AuthnRequest) XMLObjectProviderRegistrySupport.getBuilderFactory() - .getBuilder(AuthnRequest.DEFAULT_ELEMENT_NAME) - .buildObject(AuthnRequest.DEFAULT_ELEMENT_NAME); - - authnRequest.setID("_" + UUID.randomUUID().toString()); - authnRequest.setVersion(SAMLVersion.VERSION_20); - // authnRequest.setIssueInstant(new DateTime()); - authnRequest.setIssueInstant(Instant.now()); - - - // Sign the AuthnRequest - // BasicCredential signingCredential = new BasicCredential(certificate, privateKey); - BasicX509Credential signingCredential = new BasicX509Credential(certificate, privateKey); - - Signature signature = (Signature) XMLObjectProviderRegistrySupport.getBuilderFactory() - .getBuilder(Signature.DEFAULT_ELEMENT_NAME) - .buildObject(Signature.DEFAULT_ELEMENT_NAME); - - signature.setSigningCredential(signingCredential); - signature.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1); // Set RSA-SHA1 - - authnRequest.setSignature(signature); - DefaultSecurityConfigurationBootstrap.buildDefaultSignatureSigningConfiguration(); - - // Marshall and sign the object - XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(authnRequest).marshall(authnRequest); - Signer.signObject(signature); - - return authnRequest; - } @Bean public Saml2AuthenticationRequestResolver authenticationRequestResolver(RelyingPartyRegistrationRepository registrations) { From 98fc120cffc955f7788ced1a51abda6a9f2ee32f Mon Sep 17 00:00:00 2001 From: nisha Date: Tue, 24 Sep 2024 13:09:29 +0530 Subject: [PATCH 16/58] Updated response of application form data --- .../tendermanagement/dao/ApplicationDao.java | 97 +++++++++++++++++-- .../ApplicationFormFieldResponseBean.java | 2 +- .../service/DocumentService.java | 5 +- .../service/impl/DocumentServiceImpl.java | 7 ++ 4 files changed, 99 insertions(+), 12 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java index f8e86e7e..d153ed5c 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java @@ -4,6 +4,7 @@ import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.entities.*; import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum; +import net.gepafin.tendermanagement.enums.DocumentSourceTypeEnum; import net.gepafin.tendermanagement.enums.RoleStatusEnum; import net.gepafin.tendermanagement.model.request.ApplicationFormFieldRequestBean; import net.gepafin.tendermanagement.model.request.ApplicationRequest; @@ -13,6 +14,7 @@ import net.gepafin.tendermanagement.repositories.ApplicationFormFieldRepository; import net.gepafin.tendermanagement.repositories.ApplicationFormRepository; import net.gepafin.tendermanagement.repositories.ApplicationRepository; import net.gepafin.tendermanagement.service.CallService; +import net.gepafin.tendermanagement.service.DocumentService; import net.gepafin.tendermanagement.service.FormService; import net.gepafin.tendermanagement.util.DateTimeUtil; import net.gepafin.tendermanagement.util.Utils; @@ -48,6 +50,12 @@ public class ApplicationDao { @Autowired private FormService formService; + @Autowired + private DocumentService documentService; + + @Autowired + private CallDao callDao; + public ApplicationResponseBean createApplication(ApplicationRequestBean applicationRequestBean, UserEntity userEntity, Long formId,Long applicationId) { FormEntity formEntity = formService.validateForm(formId); CallEntity call = callService.validatePublishedCall(formEntity.getCall().getId()); @@ -57,7 +65,7 @@ public class ApplicationDao { } formService.validateFormField(applicationRequestBean.getFormFields(),applicationEntity,formEntity); ApplicationFormEntity applicationFormEntity = getApplicationFormOrCreate(formEntity, applicationEntity); - createOrUpdateMultipleFormFields(applicationRequestBean.getFormFields(), applicationFormEntity); + createOrUpdateMultipleFormFields(applicationRequestBean.getFormFields(), applicationFormEntity,formEntity); return getApplicationById(applicationEntity.getId(),formEntity.getId()); } @@ -97,15 +105,56 @@ public class ApplicationDao { List applicationFormFieldResponseBeans=new ArrayList<>(); ApplicationFormFieldResponseBean applicationFormFieldResponseBeans1=null; List applicationFormFieldEntities = applicationFormFieldRepository.findByApplicationFormId(applicationFormEntity.getId()); - for(ApplicationFormFieldEntity applicationFormFieldEntity:applicationFormFieldEntities) { - applicationFormFieldResponseBeans1 = convertApplicationFormFieldEntityToApplicationFormFieldResponseBean(applicationFormFieldEntity, applicationFormEntity.getId()); - applicationFormFieldResponseBeans.add(applicationFormFieldResponseBeans1); - } + applicationFormFieldResponseBeans=createApplicationFormFieldResponse(applicationFormFieldEntities, applicationFormEntity, applicationFormFieldResponseBeans); ApplicationResponseBean applicationResponseBean= convertApplicationEntityToApplicationResponseBean(applicationEntity); applicationResponseBean.setFormFields(applicationFormFieldResponseBeans); return applicationResponseBean; } + private List createApplicationFormFieldResponse( + List applicationFormFieldEntities, + ApplicationFormEntity applicationFormEntity, + List applicationFormFieldResponseBeans) { + + List contentResponseBeans = Utils.convertJsonStringToList( + applicationFormEntity.getForm().getContent(), ContentResponseBean.class); + + for (ApplicationFormFieldEntity applicationFormFieldEntity : applicationFormFieldEntities) { + + Optional fileUploadContent = contentResponseBeans.stream() + .filter(contentResponseBean -> "fileupload".equals(contentResponseBean.getName()) && + contentResponseBean.getId().equals(applicationFormFieldEntity.getFieldId())) + .findFirst(); + + List documentResponseBeans = new ArrayList<>(); + if (fileUploadContent.isPresent()) { + String documentId = applicationFormFieldEntity.getFieldValue(); + if (documentId != null && !documentId.isEmpty()) { + documentResponseBeans = Arrays.stream(documentId.split(",")) + .map(String::trim) + .map(Long::parseLong) + .map(docId -> { + DocumentEntity documentEntity = documentService.validateDocument(docId); + if (Boolean.FALSE.equals(DocumentSourceTypeEnum.APPLICATION.getValue().equals(documentEntity.getSource()))) { + throw new CustomValidationException(Status.NOT_FOUND,Translator.toLocale(GepafinConstant.DOCUMENT_NOT_FOUND)); + } + return documentEntity; + }) + .map(callDao::convertToDocumentResponseBean) + .collect(Collectors.toList()); + } + } + ApplicationFormFieldResponseBean responseBean = convertApplicationFormFieldEntityToApplicationFormFieldResponseBean( + applicationFormFieldEntity, applicationFormEntity.getId()); + if (!documentResponseBeans.isEmpty()) { + responseBean.setFieldValue(documentResponseBeans); + } + applicationFormFieldResponseBeans.add(responseBean); + } + + return applicationFormFieldResponseBeans; + } + public void deleteById(Long id) { log.info("Deleting application with ID: {}", id); @@ -188,18 +237,21 @@ public class ApplicationDao { return applicationFormEntity; } - public List createOrUpdateMultipleFormFields(List formFieldResponseBeans, ApplicationFormEntity applicationFormEntity) { + public List createOrUpdateMultipleFormFields(List formFieldResponseBeans, ApplicationFormEntity applicationFormEntity,FormEntity formEntity) { List existingFields = applicationFormFieldRepository.findByApplicationFormId(applicationFormEntity.getId()); List applicationFormFieldEntity = formFieldResponseBeans.stream() - .map(requestBean -> createOrUpdateApplicationFormField(requestBean, applicationFormEntity,existingFields)) + .map(requestBean -> createOrUpdateApplicationFormField(requestBean, applicationFormEntity,existingFields,formEntity)) .collect(Collectors.toList()); return applicationFormFieldEntity; } - public ApplicationFormFieldEntity createOrUpdateApplicationFormField(ApplicationFormFieldRequestBean applicationFormFieldRequestBean, ApplicationFormEntity applicationFormEntity,List applicationFormFieldEntities ) { + public ApplicationFormFieldEntity createOrUpdateApplicationFormField(ApplicationFormFieldRequestBean applicationFormFieldRequestBean, ApplicationFormEntity applicationFormEntity,List applicationFormFieldEntities ,FormEntity formEntity) { ApplicationFormFieldEntity applicationFormFieldEntity=null; + + validateFileUploadDocuments(applicationFormFieldRequestBean, formEntity); + if(applicationFormFieldEntities==null || applicationFormFieldEntities.isEmpty()){ applicationFormFieldEntity = new ApplicationFormFieldEntity(); applicationFormFieldEntity.setApplicationForm(applicationFormEntity); @@ -219,6 +271,31 @@ public class ApplicationDao { return applicationFormFieldRepository.save(applicationFormFieldEntity); } + private List validateFileUploadDocuments(ApplicationFormFieldRequestBean applicationFormFieldRequestBean, FormEntity formEntity) { + List documentIds=null; + List contentResponseBeans=Utils.convertJsonStringToList(formEntity.getContent(),ContentResponseBean.class); + for (ContentResponseBean contentResponseBean:contentResponseBeans){ + if(Boolean.TRUE.equals(contentResponseBean.getName().equals("fileupload"))){ + if(contentResponseBean.getId().equals(applicationFormFieldRequestBean.getFieldId())) { + String documentId = applicationFormFieldRequestBean.getFieldValue(); + documentIds = validateDocumentIds(documentId); + } + } + } + return documentIds; + } + + private List validateDocumentIds(String documentId) { + if (documentId != null && !documentId.isEmpty()) { + return Arrays.stream(documentId.split(",")) + .map(Long::parseLong) + .peek(docId -> documentService.validateDocument(docId)) + .collect(Collectors.toList()); + } + return Collections.emptyList(); + } + + public ApplicationFormFieldEntity validateApplicationFormField(Long applicationFormFieldId) { Optional applicationFormFieldEntity = applicationFormFieldRepository.findById(applicationFormFieldId); if (applicationFormFieldEntity.isEmpty()) { @@ -290,12 +367,12 @@ public class ApplicationDao { public FormApplicationResponse processForm(FormEntity formEntity, ApplicationEntity applicationEntity) { FormApplicationResponse formApplicationResponse = createFormApplicationResponse(formEntity); + List applicationFormFieldResponseBeans =new ArrayList<>(); ApplicationFormEntity applicationFormEntity = applicationFormRepository.findByApplicationIdAndFormId(applicationEntity.getId(), formEntity.getId()); if(applicationFormEntity!=null) { List applicationFormFieldEntities = applicationFormFieldRepository.findByApplicationFormId(applicationFormEntity.getId()); // formApplicationResponse = createFormApplicationResponse(formEntity); - List applicationFormFieldResponseBeans = convertApplicationFormFieldEntitiesToApplicationFormFieldResponseBeans(applicationFormFieldEntities, applicationFormEntity.getId()); - + applicationFormFieldResponseBeans = createApplicationFormFieldResponse(applicationFormFieldEntities, applicationFormEntity,applicationFormFieldResponseBeans); formApplicationResponse.setFormFields(applicationFormFieldResponseBeans); } return formApplicationResponse; diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationFormFieldResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationFormFieldResponseBean.java index f625d991..2e207f21 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationFormFieldResponseBean.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationFormFieldResponseBean.java @@ -12,5 +12,5 @@ public class ApplicationFormFieldResponseBean extends BaseBean { private String fieldId; - private String fieldValue; + private Object fieldValue; } diff --git a/src/main/java/net/gepafin/tendermanagement/service/DocumentService.java b/src/main/java/net/gepafin/tendermanagement/service/DocumentService.java index 4c57d3ca..6012a273 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/DocumentService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/DocumentService.java @@ -1,6 +1,7 @@ package net.gepafin.tendermanagement.service; import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.entities.DocumentEntity; import net.gepafin.tendermanagement.enums.DocumentSourceTypeEnum; import net.gepafin.tendermanagement.enums.DocumentTypeEnum; import net.gepafin.tendermanagement.model.response.DocumentResponseBean; @@ -17,4 +18,6 @@ public interface DocumentService { public DocumentResponseBean updateDocument(HttpServletRequest httpServletRequest, Long documentId, MultipartFile file, DocumentTypeEnum documentTypeEnum); public DocumentResponseBean getDocument(HttpServletRequest httpServletRequest,Long documentId); -} + + public DocumentEntity validateDocument(Long id); + } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/DocumentServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/DocumentServiceImpl.java index 5cbc8634..3b3fa310 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/DocumentServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/DocumentServiceImpl.java @@ -4,6 +4,7 @@ import java.util.List; import jakarta.servlet.http.HttpServletRequest; import net.gepafin.tendermanagement.dao.DocumentDao; +import net.gepafin.tendermanagement.entities.DocumentEntity; import net.gepafin.tendermanagement.enums.DocumentSourceTypeEnum; import net.gepafin.tendermanagement.enums.DocumentTypeEnum; import net.gepafin.tendermanagement.model.response.DocumentResponseBean; @@ -40,4 +41,10 @@ public class DocumentServiceImpl implements DocumentService { public DocumentResponseBean getDocument(HttpServletRequest httpServletRequest, Long documentId) { return documentDao.getDocument(documentId); } + + @Override + public DocumentEntity validateDocument(Long id){ + return documentDao.validateDocument(id); + } + } From 5212442417052afd3f7d0f5c63902ce6f7d34563 Mon Sep 17 00:00:00 2001 From: rajesh Date: Tue, 24 Sep 2024 12:39:45 -0700 Subject: [PATCH 17/58] Updated config --- pom.xml | 7 +++ .../config/SecurityConfig.java | 61 ++++++++++++++++++- 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index e8fb4bca..e10bc152 100644 --- a/pom.xml +++ b/pom.xml @@ -172,6 +172,13 @@ spring-cloud-starter-openfeign 4.1.3 + + + org.apache.santuario + xmlsec + 2.3.0 + + diff --git a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java index ac2ade2c..c645cee1 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java @@ -1,4 +1,6 @@ package net.gepafin.tendermanagement.config; + + import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; @@ -8,9 +10,12 @@ import java.security.PrivateKey; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.spec.PKCS8EncodedKeySpec; +import java.time.Instant; import java.util.UUID; import org.bouncycastle.util.io.pem.PemReader; +import org.opensaml.core.config.InitializationService; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; import org.opensaml.saml.common.SAMLVersion; import org.opensaml.saml.common.xml.SAMLConstants; import org.opensaml.saml.saml2.core.AuthnContextClassRef; @@ -19,6 +24,11 @@ import org.opensaml.saml.saml2.core.AuthnRequest; import org.opensaml.saml.saml2.core.RequestedAuthnContext; import org.opensaml.saml.saml2.core.impl.AuthnContextClassRefBuilder; import org.opensaml.saml.saml2.core.impl.RequestedAuthnContextBuilder; +import org.opensaml.security.x509.BasicX509Credential; +import org.opensaml.xmlsec.config.impl.DefaultSecurityConfigurationBootstrap; +import org.opensaml.xmlsec.signature.Signature; +import org.opensaml.xmlsec.signature.support.SignatureConstants; +import org.opensaml.xmlsec.signature.support.Signer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -55,19 +65,19 @@ import org.springframework.web.filter.CorsFilter; import org.springframework.web.servlet.handler.HandlerMappingIntrospector; import com.fasterxml.jackson.databind.ObjectMapper; - +import org.apache.xml.security.Init; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.security.SecurityScheme; import io.swagger.v3.oas.models.servers.Server; +import jakarta.annotation.PostConstruct; import net.gepafin.tendermanagement.config.jwt.JWTFilter; import net.gepafin.tendermanagement.config.jwt.TokenProvider; import net.gepafin.tendermanagement.entities.SamlResponseLogEntity; import net.gepafin.tendermanagement.repositories.SamlResponseLogRepository; //import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationRequestContext; //import org.springframework.security.saml2.core.Saml2AuthenticationRequest; - @Configuration @EnableWebSecurity @EnableMethodSecurity(prePostEnabled = true) @@ -85,6 +95,21 @@ public class SecurityConfig { public SecurityConfig(TokenProvider tokenProvider) { this.tokenProvider = tokenProvider; } + + + + @PostConstruct + public void initXmlSecurity() throws Exception { + // Initialize Apache XML Security (Santuario) + Init.init(); + } + + + @PostConstruct + public void initOpenSAML() throws Exception { + InitializationService.initialize(); + } + // // @Bean // public Saml2AuthenticationRequestResolver authenticationRequestResolver() { @@ -259,6 +284,38 @@ public class SecurityConfig { return new InMemoryRelyingPartyRegistrationRepository(registration); } + public AuthnRequest createSignedAuthnRequest(PrivateKey privateKey, X509Certificate certificate) throws Exception { + AuthnRequest authnRequest = (AuthnRequest) XMLObjectProviderRegistrySupport.getBuilderFactory() + .getBuilder(AuthnRequest.DEFAULT_ELEMENT_NAME) + .buildObject(AuthnRequest.DEFAULT_ELEMENT_NAME); + + authnRequest.setID("_" + UUID.randomUUID().toString()); + authnRequest.setVersion(SAMLVersion.VERSION_20); + // authnRequest.setIssueInstant(new DateTime()); + authnRequest.setIssueInstant(Instant.now()); + + + // Sign the AuthnRequest + // BasicCredential signingCredential = new BasicCredential(certificate, privateKey); + BasicX509Credential signingCredential = new BasicX509Credential(certificate, privateKey); + + Signature signature = (Signature) XMLObjectProviderRegistrySupport.getBuilderFactory() + .getBuilder(Signature.DEFAULT_ELEMENT_NAME) + .buildObject(Signature.DEFAULT_ELEMENT_NAME); + + signature.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); + signature.setSigningCredential(signingCredential); + signature.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1); // Set RSA-SHA1 + + authnRequest.setSignature(signature); + DefaultSecurityConfigurationBootstrap.buildDefaultSignatureSigningConfiguration(); + + // Marshall and sign the object + XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(authnRequest).marshall(authnRequest); + Signer.signObject(signature); + + return authnRequest; + } @Bean public Saml2AuthenticationRequestResolver authenticationRequestResolver(RelyingPartyRegistrationRepository registrations) { From 79bef1b8252e5ffb31652fceeacfdc556e7d0953 Mon Sep 17 00:00:00 2001 From: rajesh Date: Tue, 24 Sep 2024 13:57:33 -0700 Subject: [PATCH 18/58] Updated versions --- pom.xml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index e10bc152..a2a1e712 100644 --- a/pom.xml +++ b/pom.xml @@ -146,7 +146,7 @@ org.opensaml opensaml-core - 4.0.1 + 4.2.0 @@ -154,7 +154,7 @@ org.opensaml opensaml-saml-api - 4.0.1 + 4.2.0 @@ -162,7 +162,7 @@ org.opensaml opensaml-saml-impl - 4.0.1 + 4.2.0 @@ -181,6 +181,12 @@ + + + shibboleth + https://build.shibboleth.net/nexus/content/repositories/releases/ + + From 14b08497322a6699f2d3664b63952a4f737e34a9 Mon Sep 17 00:00:00 2001 From: nisha Date: Tue, 24 Sep 2024 15:25:43 +0530 Subject: [PATCH 19/58] Added call status in flow api response --- src/main/java/net/gepafin/tendermanagement/dao/FlowDao.java | 2 ++ .../tendermanagement/model/response/FlowResponseBean.java | 3 +++ 2 files changed, 5 insertions(+) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/FlowDao.java b/src/main/java/net/gepafin/tendermanagement/dao/FlowDao.java index 34bf0e59..6b4d34d5 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/FlowDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/FlowDao.java @@ -6,6 +6,7 @@ import net.gepafin.tendermanagement.entities.CallEntity; import net.gepafin.tendermanagement.entities.FlowDataEntity; import net.gepafin.tendermanagement.entities.FlowDataEntity; import net.gepafin.tendermanagement.entities.FlowEdgesEntity; +import net.gepafin.tendermanagement.enums.CallStatusEnum; import net.gepafin.tendermanagement.model.request.FlowDataRequestBean; import net.gepafin.tendermanagement.model.request.FlowEdgesRequestBean; import net.gepafin.tendermanagement.model.request.FlowRequestBean; @@ -193,6 +194,7 @@ public class FlowDao { return null; } flowResponseBean.setCallId(call.getId()); + flowResponseBean.setCallStatus(CallStatusEnum.valueOf(call.getStatus())); flowResponseBean.setInitialForm(call.getInitialForm()); flowResponseBean.setFinalForm(call.getFinalForm()); return flowResponseBean; diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/FlowResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/FlowResponseBean.java index 289f44b1..d97895e7 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/FlowResponseBean.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/FlowResponseBean.java @@ -1,6 +1,7 @@ package net.gepafin.tendermanagement.model.response; import lombok.Data; +import net.gepafin.tendermanagement.enums.CallStatusEnum; import net.gepafin.tendermanagement.model.request.FlowDataRequestBean; import net.gepafin.tendermanagement.model.request.FlowEdgesRequestBean; @@ -11,6 +12,8 @@ public class FlowResponseBean { private Long callId; + private CallStatusEnum callStatus; + private Long initialForm; private Long finalForm; From 385a9b7daa8043c4047c831cc27064f4f6c79aad Mon Sep 17 00:00:00 2001 From: rajesh Date: Tue, 24 Sep 2024 17:32:01 +0530 Subject: [PATCH 20/58] Updated code --- src/main/java/net/gepafin/tendermanagement/dao/FormDao.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java b/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java index 57568468..8121f9e6 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java @@ -206,14 +206,13 @@ public class FormDao { FieldValidator validator = FieldValidator.create(); formResponseBean.getContent().forEach(contentResponseBean -> { String fieldId = contentResponseBean.getId(); - String value = String.valueOf(formFieldMap.get(fieldId)); + String value = (String) formFieldMap.get(fieldId); if(value == null && isApplicationFormExist) { return; } FieldValidatorBean fieldValidatorBean = Utils.convertSourceObjectToDestinationObject(contentResponseBean.getValidators(), FieldValidatorBean.class); validator - .notNull(value, fieldId) .isRequired(value,fieldValidatorBean.getIsRequired(),fieldId) .minLength(value, fieldValidatorBean.getMinLength(), fieldId) // Only applies if minLength is not null .maxLength(value, fieldValidatorBean.getMaxLength(), fieldId) // Only applies if maxLength is not null From befd86cacbdd845879fc7009cb827225ea675fba Mon Sep 17 00:00:00 2001 From: harish Date: Tue, 24 Sep 2024 18:08:43 +0530 Subject: [PATCH 21/58] Configure production properties in application_prod.properties --- Jenkinsfile | 2 +- src/main/resources/application-production.properties | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 src/main/resources/application-production.properties diff --git a/Jenkinsfile b/Jenkinsfile index 968d3a2b..d488b39e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -56,7 +56,7 @@ pipeline { } } script { - sh 'ssh ubuntu@46.105.65.89 "sh gepafin-production-api.sh"' + sh 'ssh ubuntu@79.137.88.15 "sh gepafin-production-api.sh"' } } } diff --git a/src/main/resources/application-production.properties b/src/main/resources/application-production.properties new file mode 100644 index 00000000..2132264d --- /dev/null +++ b/src/main/resources/application-production.properties @@ -0,0 +1,11 @@ +# DataSource Configuration +spring.datasource.url=jdbc:postgresql://79.137.88.14:21543/gepaDb +spring.datasource.username=usergepa +spring.datasource.password=nRHMi7esdgHJiIm3L5ctrSJ0 +spring.datasource.driver-class-name=org.postgresql.Driver + +# JPA Configuration +spring.h2.console.enabled=true +base-url=https://api-dev-gepafin.memento.credit + +isVatCheckGloballyDisabled = false From 389b29995b58830b7317b762e4029d4be34a496d Mon Sep 17 00:00:00 2001 From: rajesh Date: Tue, 24 Sep 2024 15:32:20 -0700 Subject: [PATCH 22/58] updated config --- .../net/gepafin/tendermanagement/config/SecurityConfig.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java index c645cee1..5e2de88b 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java @@ -270,7 +270,9 @@ public class SecurityConfig { .entityId(entityId) .signingX509Credentials(credentials -> { try { - credentials.add(Saml2X509Credential.signing(readPrivateKey(), readCertificate())); + // credentials.add(Saml2X509Credential.signing(readPrivateKey(), readCertificate())); + AuthnRequest signedAuthnRequest = createSignedAuthnRequest(readPrivateKey(), readCertificate()); + //logger.info("Signed SAML AuthnRequest: " + SamlRequestLogger.convertSAMLObjectToString(signedAuthnRequest)); } catch (Exception e) { e.printStackTrace(); } From 2714f646af19c0e852d4d78606f47ec6028d2cc7 Mon Sep 17 00:00:00 2001 From: rajesh Date: Tue, 24 Sep 2024 15:39:06 -0700 Subject: [PATCH 23/58] updated config --- .../net/gepafin/tendermanagement/config/SecurityConfig.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java index 5e2de88b..e530b479 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java @@ -270,8 +270,8 @@ public class SecurityConfig { .entityId(entityId) .signingX509Credentials(credentials -> { try { - // credentials.add(Saml2X509Credential.signing(readPrivateKey(), readCertificate())); - AuthnRequest signedAuthnRequest = createSignedAuthnRequest(readPrivateKey(), readCertificate()); + credentials.add(Saml2X509Credential.signing(readPrivateKey(), readCertificate())); + // AuthnRequest signedAuthnRequest = createSignedAuthnRequest(readPrivateKey(), readCertificate()); //logger.info("Signed SAML AuthnRequest: " + SamlRequestLogger.convertSAMLObjectToString(signedAuthnRequest)); } catch (Exception e) { e.printStackTrace(); From aabb7ae55104271c89cb9eeadd4bbdcc58fe4823 Mon Sep 17 00:00:00 2001 From: rajesh Date: Tue, 24 Sep 2024 16:40:14 -0700 Subject: [PATCH 24/58] Updated config --- .../config/SecurityConfig.java | 42 +++++++++++++------ .../resources/dev/saml/idp-certificate.pem | 3 ++ 2 files changed, 33 insertions(+), 12 deletions(-) create mode 100644 src/main/resources/dev/saml/idp-certificate.pem diff --git a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java index e530b479..3b8f79b4 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java @@ -263,26 +263,35 @@ public class SecurityConfig { @Bean public RelyingPartyRegistrationRepository relyingPartyRegistrationRepository() { - - String entityId = baseUrl + "/v1/saml/gw/metadata"; - String acsUrl = baseUrl + "/login/saml2/sso/loginumbria"; + + String entityId = baseUrl + "/v1/saml/gw/metadata"; + String acsUrl = baseUrl + "/login/saml2/sso/loginumbria"; + RelyingPartyRegistration registration = RelyingPartyRegistration.withRegistrationId("loginumbria") .entityId(entityId) - .signingX509Credentials(credentials -> { + .signingX509Credentials(credentials -> { + try { + credentials.add(Saml2X509Credential.signing(readPrivateKey(), readCertificate())); + } catch (Exception e) { + e.printStackTrace(); + } + }) + .assertionConsumerServiceLocation(acsUrl) + .assertingPartyDetails(details -> details.entityId("https://federatest.umbriadigitale.it/gw/metadata") + .singleSignOnServiceLocation("https://federatest.umbriadigitale.it/gw/SSOProxy/SAML2") + .singleSignOnServiceBinding(Saml2MessageBinding.POST) + .wantAuthnRequestsSigned(true) + .verificationX509Credentials(credentials -> { try { - credentials.add(Saml2X509Credential.signing(readPrivateKey(), readCertificate())); - // AuthnRequest signedAuthnRequest = createSignedAuthnRequest(readPrivateKey(), readCertificate()); - //logger.info("Signed SAML AuthnRequest: " + SamlRequestLogger.convertSAMLObjectToString(signedAuthnRequest)); + // Load the IDP's public certificate for verifying the SAML response signature + credentials.add(Saml2X509Credential.verification(readIdpCertificate())); } catch (Exception e) { e.printStackTrace(); } }) - .assertionConsumerServiceLocation(acsUrl) - .assertingPartyDetails(details -> details.entityId("https://federatest.umbriadigitale.it/gw/metadata") - .singleSignOnServiceLocation("https://federatest.umbriadigitale.it/gw/SSOProxy/SAML2") - .singleSignOnServiceBinding(Saml2MessageBinding.POST).wantAuthnRequestsSigned(true).build() - ) + ) .build(); + return new InMemoryRelyingPartyRegistrationRepository(registration); } @@ -378,6 +387,15 @@ private RequestedAuthnContext buildRequestedAuthnContext() { } } + public X509Certificate readIdpCertificate() throws Exception { + // Path to your IDP public certificate PEM file + try (InputStream inStream = readKey("dev/saml/idp-certificate.pem")) { + CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); + return (X509Certificate) certFactory.generateCertificate(inStream); + } + } + + public InputStream readKey(String path) throws IOException { ClassLoader classLoader = getClass().getClassLoader(); InputStream inputStream = classLoader.getResourceAsStream(path); diff --git a/src/main/resources/dev/saml/idp-certificate.pem b/src/main/resources/dev/saml/idp-certificate.pem new file mode 100644 index 00000000..598749d1 --- /dev/null +++ b/src/main/resources/dev/saml/idp-certificate.pem @@ -0,0 +1,3 @@ +-----BEGIN CERTIFICATE----- +MIIDJDCCAgygAwIBAgIVAIq/MUgxPKO0cuX/GtD7YUvk87GtMA0GCSqGSIb3DQEBBQUAMBkxFzAVBgNVBAMTDmlkcC5tYWNoaW5lLml0MB4XDTA5MDMyNTEwNTM1OFoXDTI5MDMyNTA5NTM1OFowGTEXMBUGA1UEAxMOaWRwLm1hY2hpbmUuaXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQClXV18x0/yhZ+D3pHlmhrK4paA+xdJKAT7U7R9DeaTQygwtCjKmCrJbzdohckLz5pax7eaGeA53pPCY+JdiU0Uq4ES8nG2DCZgCtl4QGLUcTuUtJdPq+DbYD1cWBwEeeffsiClVyuhgLRPO1OQLl/TJp4slfoYTi0aONgQp03uG+ixL48myL7GrINHYXtDUDqo2BimyU0yrOe6ZmvxJchZ8nBuWKy0J8wsO/Mnasbvo79/c8gcn0HTst0QDlHXQlzwZ4Suq2os9qKjXAYOzA1VqmTyzJIge/ynHiJ0Fkw0HNxBaVFTJRNL8RvwJsMuBT7YZKRoNK7gjT5/6bGagYM/AgMBAAGjYzBhMEAGA1UdEQQ5MDeCDmlkcC5tYWNoaW5lLml0hiVodHRwczovL2lkcC5tYWNoaW5lLml0L2lkcC9zaGliYm9sZXRoMB0GA1UdDgQWBBSBOsPZiWZRXFqNINIguHfv7jnidDANBgkqhkiG9w0BAQUFAAOCAQEAeVLN9jczRINuPUvpXbgibL2c99dUReMcl47nSVtYeYEBkPPZrSz0h3AyVZyar2Vo+/fC3fRNmaOJvfiVSm+bo1069iROI1+dGGq2gAwWuQI1q0F7PNPX4zooY+LbZI0oUhuoyH81xed0WtMlpJ1aRSBMpR6oV3rguAkH6pdr725yv6m5WxKcOM/LzdD5Xt9fQRL7ino4HfiPPJNDG3UOKhoAWkVn/Y/CuMLcBPWh/3LxIv4A1bQbnkpdty+Qtwfp4QUKkisv7gufQP91aLqUvvRE6Uz8r51VH13e4mEJjJGxLKXWzlP50gp7b27AXCTKSS6fW6iBpfA14PGcWvDiPQ== +-----END CERTIFICATE----- From 27774895505f742c0bc283f193f94723d4d79710 Mon Sep 17 00:00:00 2001 From: rajesh Date: Tue, 24 Sep 2024 17:06:32 -0700 Subject: [PATCH 25/58] Updated config --- .../config/SecurityConfig.java | 107 ++++++++---------- 1 file changed, 48 insertions(+), 59 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java index 3b8f79b4..c83cc513 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java @@ -11,8 +11,11 @@ import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.spec.PKCS8EncodedKeySpec; import java.time.Instant; +import java.util.List; +import java.util.Map; import java.util.UUID; +import org.apache.xml.security.Init; import org.bouncycastle.util.io.pem.PemReader; import org.opensaml.core.config.InitializationService; import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; @@ -47,6 +50,8 @@ 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.saml2.core.Saml2X509Credential; +import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal; +import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication; import org.springframework.security.saml2.provider.service.registration.InMemoryRelyingPartyRegistrationRepository; import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration; import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository; @@ -65,7 +70,7 @@ import org.springframework.web.filter.CorsFilter; import org.springframework.web.servlet.handler.HandlerMappingIntrospector; import com.fasterxml.jackson.databind.ObjectMapper; -import org.apache.xml.security.Init; + import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.security.SecurityRequirement; @@ -184,70 +189,54 @@ public class SecurityConfig { .saml2Login(saml -> saml.defaultSuccessUrl("/") .successHandler((request, response, authentication) -> { - logger.error("SAML success login"); - SamlResponseLogEntity samlResponseLogEntity = new SamlResponseLogEntity(); - samlResponseLogEntity.setRequest(request.toString()); - samlResponseLogEntity.setResponse(response.toString()); - samlResponseLogEntity.setAuthenticationObject(authentication.toString()); - samlResponseLogRepository.save(samlResponseLogEntity); - try { - ObjectMapper objectMapper = new ObjectMapper(); - // Create a new SAML log entity - SamlResponseLogEntity samlResponseLogEntity1 = new SamlResponseLogEntity(); + try { + // Cast the authentication object to Saml2Authentication + Saml2Authentication samlAuth = (Saml2Authentication) authentication; + Saml2AuthenticatedPrincipal principal = (Saml2AuthenticatedPrincipal) samlAuth.getPrincipal(); - // Convert request, response, and authentication to JSON format - String requestJson = objectMapper.writeValueAsString(request.getParameterMap()); // Assuming request params to JSON - String responseJson = objectMapper.writeValueAsString(response); // This may need to be adapted based on your response object - String authenticationJson = objectMapper.writeValueAsString(authentication); // Authentication object to JSON + // Extract the user attributes from the principal + Map> userAttributes = principal.getAttributes(); - // Set the JSON strings in the entity - samlResponseLogEntity1.setRequest(requestJson); - samlResponseLogEntity1.setResponse(responseJson); - samlResponseLogEntity1.setAuthenticationObject(authenticationJson); - samlResponseLogRepository.save(samlResponseLogEntity1); - - logger.info("SAML Request: " + requestJson); - logger.info("SAML Response: " + responseJson); - logger.info("Authentication Details: " + authenticationJson); - }catch(Exception e) { - logger.info("Exception object" + e); - } -// samlResponseLogRepository - logger.info("SAML login successful for user: " + authentication.getName()); - response.sendRedirect("http://gepafin-staging-fe.s3-website.eu-central-1.amazonaws.com/"); - }).failureHandler((request, response, exception) -> { - logger.error("SAML login failed: " + exception.getMessage()); + // Log the user attributes for debugging purposes + logger.info("SAML User Attributes: " + userAttributes); - SamlResponseLogEntity samlResponseLogEntity = new SamlResponseLogEntity(); - samlResponseLogEntity.setRequest(request.toString()); - samlResponseLogEntity.setResponse(response.toString()); - samlResponseLogEntity.setExceptionObject(exception.toString()); - samlResponseLogRepository.save(samlResponseLogEntity); - try { - ObjectMapper objectMapper = new ObjectMapper(); + // Save the authentication details in the database (Optional) + SamlResponseLogEntity samlResponseLogEntity = new SamlResponseLogEntity(); + samlResponseLogEntity.setAuthenticationObject(authentication.toString()); - // Create a new SAML log entity - SamlResponseLogEntity samlResponseLogEntity1 = new SamlResponseLogEntity(); + // Convert user attributes to JSON and save in DB + ObjectMapper objectMapper = new ObjectMapper(); + String userAttributesJson = objectMapper.writeValueAsString(userAttributes); + samlResponseLogEntity.setAuthenticationObject(userAttributesJson); + samlResponseLogRepository.save(samlResponseLogEntity); + + // Successful login logic + logger.info("SAML login successful for user: " + principal.getName()); + response.sendRedirect("http://gepafin-staging-fe.s3-website.eu-central-1.amazonaws.com/login"); + } catch (Exception e) { + logger.error("Error processing SAML success handler", e); + } + }) + .failureHandler((request, response, exception) -> { + try { + logger.error("SAML login failed: " + exception.getMessage()); + + // Log the failure details to the database (Optional) + SamlResponseLogEntity samlResponseLogEntity = new SamlResponseLogEntity(); + samlResponseLogEntity.setRequest(request.toString()); + samlResponseLogEntity.setResponse(response.toString()); + samlResponseLogEntity.setExceptionObject(exception.toString()); + samlResponseLogRepository.save(samlResponseLogEntity); + + // Handle failure redirection + response.sendRedirect("http://gepafin-staging-fe.s3-website.eu-central-1.amazonaws.com/login"); + } catch (Exception e) { + logger.error("Error processing SAML failure handler", e); + } + }) + ); - // Convert request, response, and authentication to JSON format - String requestJson = objectMapper.writeValueAsString(request.getParameterMap()); // Assuming request params to JSON - String responseJson = objectMapper.writeValueAsString(response); // This may need to be adapted based on your response object - String exceptionJson = objectMapper.writeValueAsString(exception); // Authentication object to JSON - // Set the JSON strings in the entity - samlResponseLogEntity1.setRequest(requestJson); - samlResponseLogEntity1.setResponse(responseJson); - samlResponseLogEntity1.setAuthenticationObject(exceptionJson); - samlResponseLogRepository.save(samlResponseLogEntity1); - - logger.info("SAML Request: " + requestJson); - logger.info("SAML Response: " + responseJson); - logger.info("exception Details: " + exceptionJson); - }catch(Exception e) { - logger.info("Exception object" + e); - } - response.sendRedirect("http://gepafin-staging-fe.s3-website.eu-central-1.amazonaws.com/login"); - })); return http.build(); } From 2e2bb65bce792c2f096653ba7b3799fa44da7516 Mon Sep 17 00:00:00 2001 From: rajesh Date: Tue, 24 Sep 2024 19:32:37 +0530 Subject: [PATCH 26/58] Refactored saml code --- .../tendermanagement/config/SamlConfig.java | 197 ++++++++++++ .../config/SamlFailureHandler.java | 45 +++ .../config/SamlSuccessHandler.java | 64 ++++ .../config/SecurityConfig.java | 282 +----------------- 4 files changed, 315 insertions(+), 273 deletions(-) create mode 100644 src/main/java/net/gepafin/tendermanagement/config/SamlConfig.java create mode 100644 src/main/java/net/gepafin/tendermanagement/config/SamlFailureHandler.java create mode 100644 src/main/java/net/gepafin/tendermanagement/config/SamlSuccessHandler.java diff --git a/src/main/java/net/gepafin/tendermanagement/config/SamlConfig.java b/src/main/java/net/gepafin/tendermanagement/config/SamlConfig.java new file mode 100644 index 00000000..02a0ae27 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/config/SamlConfig.java @@ -0,0 +1,197 @@ +package net.gepafin.tendermanagement.config; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.security.KeyFactory; +import java.security.PrivateKey; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.security.spec.PKCS8EncodedKeySpec; +import java.time.Instant; +import java.util.UUID; + +import org.bouncycastle.util.io.pem.PemReader; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.saml.common.SAMLVersion; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.saml2.core.AuthnContextClassRef; +import org.opensaml.saml.saml2.core.AuthnContextComparisonTypeEnumeration; +import org.opensaml.saml.saml2.core.AuthnRequest; +import org.opensaml.saml.saml2.core.RequestedAuthnContext; +import org.opensaml.saml.saml2.core.impl.AuthnContextClassRefBuilder; +import org.opensaml.saml.saml2.core.impl.RequestedAuthnContextBuilder; +import org.opensaml.security.x509.BasicX509Credential; +import org.opensaml.xmlsec.config.impl.DefaultSecurityConfigurationBootstrap; +import org.opensaml.xmlsec.signature.Signature; +import org.opensaml.xmlsec.signature.support.SignatureConstants; +import org.opensaml.xmlsec.signature.support.Signer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.saml2.core.Saml2X509Credential; +import org.springframework.security.saml2.provider.service.registration.InMemoryRelyingPartyRegistrationRepository; +import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration; +import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository; +import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding; +import org.springframework.security.saml2.provider.service.web.DefaultRelyingPartyRegistrationResolver; +import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver; +import org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver; +import org.springframework.security.saml2.provider.service.web.authentication.Saml2AuthenticationRequestResolver; + +@Configuration +public class SamlConfig { + + private final Logger logger = LoggerFactory.getLogger(SamlConfig.class); + + @Value("${base-url}") + String baseUrl; + + @Bean + public RelyingPartyRegistrationRepository relyingPartyRegistrationRepository() { + + String entityId = baseUrl + "/v1/saml/gw/metadata"; + String acsUrl = baseUrl + "/login/saml2/sso/loginumbria"; + + RelyingPartyRegistration registration = RelyingPartyRegistration.withRegistrationId("loginumbria") + .entityId(entityId) + .signingX509Credentials(credentials -> { + try { + credentials.add(Saml2X509Credential.signing(readPrivateKey(), readCertificate())); + } catch (Exception e) { + e.printStackTrace(); + } + }) + .assertionConsumerServiceLocation(acsUrl) + .assertingPartyDetails(details -> details.entityId("https://federatest.umbriadigitale.it/gw/metadata") + .singleSignOnServiceLocation("https://federatest.umbriadigitale.it/gw/SSOProxy/SAML2") + .singleSignOnServiceBinding(Saml2MessageBinding.POST) + .wantAuthnRequestsSigned(true) + .verificationX509Credentials(credentials -> { + try { + // Load the IDP's public certificate for verifying the SAML response signature + credentials.add(Saml2X509Credential.verification(readIdpCertificate())); + } catch (Exception e) { + e.printStackTrace(); + } + }) + ) + .build(); + + return new InMemoryRelyingPartyRegistrationRepository(registration); + } + + public AuthnRequest createSignedAuthnRequest(PrivateKey privateKey, X509Certificate certificate) throws Exception { + AuthnRequest authnRequest = (AuthnRequest) XMLObjectProviderRegistrySupport.getBuilderFactory() + .getBuilder(AuthnRequest.DEFAULT_ELEMENT_NAME) + .buildObject(AuthnRequest.DEFAULT_ELEMENT_NAME); + + authnRequest.setID("_" + UUID.randomUUID().toString()); + authnRequest.setVersion(SAMLVersion.VERSION_20); + // authnRequest.setIssueInstant(new DateTime()); + authnRequest.setIssueInstant(Instant.now()); + + + // Sign the AuthnRequest + // BasicCredential signingCredential = new BasicCredential(certificate, privateKey); + BasicX509Credential signingCredential = new BasicX509Credential(certificate, privateKey); + + Signature signature = (Signature) XMLObjectProviderRegistrySupport.getBuilderFactory() + .getBuilder(Signature.DEFAULT_ELEMENT_NAME) + .buildObject(Signature.DEFAULT_ELEMENT_NAME); + + signature.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); + signature.setSigningCredential(signingCredential); + signature.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1); // Set RSA-SHA1 + + authnRequest.setSignature(signature); + DefaultSecurityConfigurationBootstrap.buildDefaultSignatureSigningConfiguration(); + + // Marshall and sign the object + XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(authnRequest).marshall(authnRequest); + Signer.signObject(signature); + + return authnRequest; + } + +@Bean +public Saml2AuthenticationRequestResolver authenticationRequestResolver(RelyingPartyRegistrationRepository registrations) { + RelyingPartyRegistrationResolver registrationResolver = new DefaultRelyingPartyRegistrationResolver(registrations); + OpenSaml4AuthenticationRequestResolver authenticationRequestResolver = new OpenSaml4AuthenticationRequestResolver(registrationResolver); + + authenticationRequestResolver.setAuthnRequestCustomizer((context) -> { + // Set the required attributes + AuthnRequest authnRequest = context.getAuthnRequest(); + authnRequest.setID("_" + UUID.randomUUID().toString()); // Add a unique ID + authnRequest.setVersion(SAMLVersion.VERSION_20); // Ensure version is 2.0 + authnRequest.setProtocolBinding(SAMLConstants.SAML2_POST_BINDING_URI); // HTTP-POST + + // Set Authentication Context + authnRequest.setRequestedAuthnContext(buildRequestedAuthnContext()); + + // Log the SAML AuthnRequest after setting context + String samlRequest = SamlRequestLogger.convertSAMLObjectToString(authnRequest); + logger.info("SAML AuthnRequest after setting context: " + samlRequest); + }); + + return authenticationRequestResolver; +} + +private RequestedAuthnContext buildRequestedAuthnContext() { + AuthnContextClassRefBuilder authnContextClassRefBuilder = new AuthnContextClassRefBuilder(); + AuthnContextClassRef authnContextClassRef = authnContextClassRefBuilder.buildObject( + SAMLConstants.SAML20_NS, AuthnContextClassRef.DEFAULT_ELEMENT_LOCAL_NAME, SAMLConstants.SAML20_PREFIX + ); + // Set the SPID Level 2 authentication context + authnContextClassRef.setURI("urn:oasis:names:tc:SAML:2.0:ac:classes:SecureRemotePassword"); + + RequestedAuthnContextBuilder requestedAuthnContextBuilder = new RequestedAuthnContextBuilder(); + RequestedAuthnContext requestedAuthnContext = requestedAuthnContextBuilder.buildObject(); + requestedAuthnContext.setComparison(AuthnContextComparisonTypeEnumeration.EXACT); + requestedAuthnContext.getAuthnContextClassRefs().add(authnContextClassRef); + + return requestedAuthnContext; +} + + public PrivateKey readPrivateKey() throws Exception { + // Path to your private key PEM file + try (PemReader pemReader = new PemReader(new InputStreamReader(readKey("dev/saml/private-key.pem")))) { + // Read the PEM content + byte[] pemContent = pemReader.readPemObject().getContent(); + // Decode the PEM content + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pemContent); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); // Use RSA algorithm + // Generate and return the PrivateKey + return keyFactory.generatePrivate(keySpec); + } + } + public X509Certificate readCertificate() throws Exception { + // Path to your certificate PEM fileFile + try (InputStream inStream = readKey("dev/saml/public-cert.pem")) { + CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); + return (X509Certificate) certFactory.generateCertificate(inStream); + } + } + + public X509Certificate readIdpCertificate() throws Exception { + // Path to your IDP public certificate PEM file + try (InputStream inStream = readKey("dev/saml/idp-certificate.pem")) { + CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); + return (X509Certificate) certFactory.generateCertificate(inStream); + } + } + + + public InputStream readKey(String path) throws IOException { + ClassLoader classLoader = getClass().getClassLoader(); + InputStream inputStream = classLoader.getResourceAsStream(path); + + if (inputStream == null) { + throw new FileNotFoundException("file not found : "+path); + } + return inputStream; + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/config/SamlFailureHandler.java b/src/main/java/net/gepafin/tendermanagement/config/SamlFailureHandler.java new file mode 100644 index 00000000..da5f3a65 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/config/SamlFailureHandler.java @@ -0,0 +1,45 @@ +package net.gepafin.tendermanagement.config; + +import java.io.IOException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; +import org.springframework.stereotype.Component; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import net.gepafin.tendermanagement.entities.SamlResponseLogEntity; +import net.gepafin.tendermanagement.repositories.SamlResponseLogRepository; + +@Component +public class SamlFailureHandler implements AuthenticationFailureHandler { + + private final Logger logger = LoggerFactory.getLogger(SamlSuccessHandler.class); + + @Autowired + private SamlResponseLogRepository samlResponseLogRepository; + + @Override + public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, + AuthenticationException exception) throws IOException { + try { + logger.error("SAML login failed: " + exception.getMessage()); + + // Log the failure details to the database (Optional) + SamlResponseLogEntity samlResponseLogEntity = new SamlResponseLogEntity(); + samlResponseLogEntity.setRequest(request.toString()); + samlResponseLogEntity.setResponse(response.toString()); + samlResponseLogEntity.setExceptionObject(exception.toString()); + samlResponseLogRepository.save(samlResponseLogEntity); + + // Handle failure redirection + response.sendRedirect("http://gepafin-staging-fe.s3-website.eu-central-1.amazonaws.com/login"); + } catch (Exception e) { + logger.error("Error processing SAML failure handler", e); + } + } + +} diff --git a/src/main/java/net/gepafin/tendermanagement/config/SamlSuccessHandler.java b/src/main/java/net/gepafin/tendermanagement/config/SamlSuccessHandler.java new file mode 100644 index 00000000..ef7c0bb7 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/config/SamlSuccessHandler.java @@ -0,0 +1,64 @@ +package net.gepafin.tendermanagement.config; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.Authentication; +import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal; +import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; +import org.springframework.stereotype.Component; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import net.gepafin.tendermanagement.entities.SamlResponseLogEntity; +import net.gepafin.tendermanagement.repositories.SamlResponseLogRepository; + +@Component +public class SamlSuccessHandler implements AuthenticationSuccessHandler{ + + + private final Logger logger = LoggerFactory.getLogger(SamlSuccessHandler.class); + + @Autowired + private SamlResponseLogRepository samlResponseLogRepository; + + @Override + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, + Authentication authentication) throws IOException { + try { + // Cast the authentication object to Saml2Authentication + Saml2Authentication samlAuth = (Saml2Authentication) authentication; + Saml2AuthenticatedPrincipal principal = (Saml2AuthenticatedPrincipal) samlAuth.getPrincipal(); + + // Extract the user attributes from the principal + Map> userAttributes = principal.getAttributes(); + + // Log the user attributes for debugging purposes + logger.info("SAML User Attributes: " + userAttributes); + + // Save the authentication details in the database (Optional) + SamlResponseLogEntity samlResponseLogEntity = new SamlResponseLogEntity(); + samlResponseLogEntity.setAuthenticationObject(authentication.toString()); + + // Convert user attributes to JSON and save in DB + ObjectMapper objectMapper = new ObjectMapper(); + String userAttributesJson = objectMapper.writeValueAsString(userAttributes); + samlResponseLogEntity.setAuthenticationObject(userAttributesJson); + samlResponseLogRepository.save(samlResponseLogEntity); + + // Successful login logic + logger.info("SAML login successful for user: " + principal.getName()); + response.sendRedirect("http://gepafin-staging-fe.s3-website.eu-central-1.amazonaws.com/login"); + } catch (Exception e) { + logger.error("Error processing SAML success handler", e); + } + } + +} diff --git a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java index c83cc513..17cf0253 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java @@ -1,39 +1,5 @@ package net.gepafin.tendermanagement.config; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.security.KeyFactory; -import java.security.PrivateKey; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.security.spec.PKCS8EncodedKeySpec; -import java.time.Instant; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import org.apache.xml.security.Init; -import org.bouncycastle.util.io.pem.PemReader; -import org.opensaml.core.config.InitializationService; -import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; -import org.opensaml.saml.common.SAMLVersion; -import org.opensaml.saml.common.xml.SAMLConstants; -import org.opensaml.saml.saml2.core.AuthnContextClassRef; -import org.opensaml.saml.saml2.core.AuthnContextComparisonTypeEnumeration; -import org.opensaml.saml.saml2.core.AuthnRequest; -import org.opensaml.saml.saml2.core.RequestedAuthnContext; -import org.opensaml.saml.saml2.core.impl.AuthnContextClassRefBuilder; -import org.opensaml.saml.saml2.core.impl.RequestedAuthnContextBuilder; -import org.opensaml.security.x509.BasicX509Credential; -import org.opensaml.xmlsec.config.impl.DefaultSecurityConfigurationBootstrap; -import org.opensaml.xmlsec.signature.Signature; -import org.opensaml.xmlsec.signature.support.SignatureConstants; -import org.opensaml.xmlsec.signature.support.Signer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; @@ -49,17 +15,6 @@ import org.springframework.security.config.annotation.web.configurers.AbstractHt 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.saml2.core.Saml2X509Credential; -import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal; -import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication; -import org.springframework.security.saml2.provider.service.registration.InMemoryRelyingPartyRegistrationRepository; -import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration; -import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository; -import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding; -import org.springframework.security.saml2.provider.service.web.DefaultRelyingPartyRegistrationResolver; -import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver; -import org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver; -import org.springframework.security.saml2.provider.service.web.authentication.Saml2AuthenticationRequestResolver; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher; @@ -69,63 +24,34 @@ import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; import org.springframework.web.servlet.handler.HandlerMappingIntrospector; -import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.security.SecurityScheme; import io.swagger.v3.oas.models.servers.Server; -import jakarta.annotation.PostConstruct; import net.gepafin.tendermanagement.config.jwt.JWTFilter; import net.gepafin.tendermanagement.config.jwt.TokenProvider; -import net.gepafin.tendermanagement.entities.SamlResponseLogEntity; -import net.gepafin.tendermanagement.repositories.SamlResponseLogRepository; -//import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationRequestContext; -//import org.springframework.security.saml2.core.Saml2AuthenticationRequest; + @Configuration @EnableWebSecurity @EnableMethodSecurity(prePostEnabled = true) public class SecurityConfig { - private final Logger logger = LoggerFactory.getLogger(SecurityConfig.class); private final TokenProvider tokenProvider; + private final SamlSuccessHandler samlSuccessHandler; + private final SamlFailureHandler samlFailureHandler; @Value("${base-url}") String baseUrl; @Autowired - private SamlResponseLogRepository samlResponseLogRepository; - - @Autowired - public SecurityConfig(TokenProvider tokenProvider) { + public SecurityConfig(TokenProvider tokenProvider, SamlSuccessHandler samlSuccessHandler, SamlFailureHandler samlFailureHandler) { this.tokenProvider = tokenProvider; + this.samlSuccessHandler =samlSuccessHandler; + this.samlFailureHandler=samlFailureHandler; } - - @PostConstruct - public void initXmlSecurity() throws Exception { - // Initialize Apache XML Security (Santuario) - Init.init(); - } - - - @PostConstruct - public void initOpenSAML() throws Exception { - InitializationService.initialize(); - } - -// -// @Bean -// public Saml2AuthenticationRequestResolver authenticationRequestResolver() { -// return (Saml2AuthenticationRequestContext context) -> { -// Saml2AuthenticationRequest request = Saml2AuthenticationRequest.withAuthenticationRequestContext(context) -// .authenticationContextClassRef("urn:oasis:names:tc:SAML:2.0:ac:classes:SecureRemotePassword") // Add context here -// .build(); -// return request; -// }; -// } - @Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception { return config.getAuthenticationManager(); @@ -186,55 +112,8 @@ public class SecurityConfig { * .saml2Login(saml -> saml.loginPage("/saml/login") // Entry point for SAML * login .defaultSuccessUrl("/") // Redirect after successful SAML login ); */ - .saml2Login(saml -> - saml.defaultSuccessUrl("/") - .successHandler((request, response, authentication) -> { - try { - // Cast the authentication object to Saml2Authentication - Saml2Authentication samlAuth = (Saml2Authentication) authentication; - Saml2AuthenticatedPrincipal principal = (Saml2AuthenticatedPrincipal) samlAuth.getPrincipal(); - - // Extract the user attributes from the principal - Map> userAttributes = principal.getAttributes(); - - // Log the user attributes for debugging purposes - logger.info("SAML User Attributes: " + userAttributes); - - // Save the authentication details in the database (Optional) - SamlResponseLogEntity samlResponseLogEntity = new SamlResponseLogEntity(); - samlResponseLogEntity.setAuthenticationObject(authentication.toString()); - - // Convert user attributes to JSON and save in DB - ObjectMapper objectMapper = new ObjectMapper(); - String userAttributesJson = objectMapper.writeValueAsString(userAttributes); - samlResponseLogEntity.setAuthenticationObject(userAttributesJson); - samlResponseLogRepository.save(samlResponseLogEntity); - - // Successful login logic - logger.info("SAML login successful for user: " + principal.getName()); - response.sendRedirect("http://gepafin-staging-fe.s3-website.eu-central-1.amazonaws.com/login"); - } catch (Exception e) { - logger.error("Error processing SAML success handler", e); - } - }) - .failureHandler((request, response, exception) -> { - try { - logger.error("SAML login failed: " + exception.getMessage()); - - // Log the failure details to the database (Optional) - SamlResponseLogEntity samlResponseLogEntity = new SamlResponseLogEntity(); - samlResponseLogEntity.setRequest(request.toString()); - samlResponseLogEntity.setResponse(response.toString()); - samlResponseLogEntity.setExceptionObject(exception.toString()); - samlResponseLogRepository.save(samlResponseLogEntity); - - // Handle failure redirection - response.sendRedirect("http://gepafin-staging-fe.s3-website.eu-central-1.amazonaws.com/login"); - } catch (Exception e) { - logger.error("Error processing SAML failure handler", e); - } - }) - ); + .saml2Login(saml -> saml.defaultSuccessUrl("/").successHandler(samlSuccessHandler) + .failureHandler(samlFailureHandler)); return http.build(); @@ -250,148 +129,5 @@ public class SecurityConfig { .scheme("bearer").bearerFormat("JWT"))); } - @Bean - public RelyingPartyRegistrationRepository relyingPartyRegistrationRepository() { - - String entityId = baseUrl + "/v1/saml/gw/metadata"; - String acsUrl = baseUrl + "/login/saml2/sso/loginumbria"; - - RelyingPartyRegistration registration = RelyingPartyRegistration.withRegistrationId("loginumbria") - .entityId(entityId) - .signingX509Credentials(credentials -> { - try { - credentials.add(Saml2X509Credential.signing(readPrivateKey(), readCertificate())); - } catch (Exception e) { - e.printStackTrace(); - } - }) - .assertionConsumerServiceLocation(acsUrl) - .assertingPartyDetails(details -> details.entityId("https://federatest.umbriadigitale.it/gw/metadata") - .singleSignOnServiceLocation("https://federatest.umbriadigitale.it/gw/SSOProxy/SAML2") - .singleSignOnServiceBinding(Saml2MessageBinding.POST) - .wantAuthnRequestsSigned(true) - .verificationX509Credentials(credentials -> { - try { - // Load the IDP's public certificate for verifying the SAML response signature - credentials.add(Saml2X509Credential.verification(readIdpCertificate())); - } catch (Exception e) { - e.printStackTrace(); - } - }) - ) - .build(); - - return new InMemoryRelyingPartyRegistrationRepository(registration); - } - - public AuthnRequest createSignedAuthnRequest(PrivateKey privateKey, X509Certificate certificate) throws Exception { - AuthnRequest authnRequest = (AuthnRequest) XMLObjectProviderRegistrySupport.getBuilderFactory() - .getBuilder(AuthnRequest.DEFAULT_ELEMENT_NAME) - .buildObject(AuthnRequest.DEFAULT_ELEMENT_NAME); - - authnRequest.setID("_" + UUID.randomUUID().toString()); - authnRequest.setVersion(SAMLVersion.VERSION_20); - // authnRequest.setIssueInstant(new DateTime()); - authnRequest.setIssueInstant(Instant.now()); - - - // Sign the AuthnRequest - // BasicCredential signingCredential = new BasicCredential(certificate, privateKey); - BasicX509Credential signingCredential = new BasicX509Credential(certificate, privateKey); - - Signature signature = (Signature) XMLObjectProviderRegistrySupport.getBuilderFactory() - .getBuilder(Signature.DEFAULT_ELEMENT_NAME) - .buildObject(Signature.DEFAULT_ELEMENT_NAME); - - signature.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); - signature.setSigningCredential(signingCredential); - signature.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1); // Set RSA-SHA1 - - authnRequest.setSignature(signature); - DefaultSecurityConfigurationBootstrap.buildDefaultSignatureSigningConfiguration(); - - // Marshall and sign the object - XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(authnRequest).marshall(authnRequest); - Signer.signObject(signature); - - return authnRequest; - } - -@Bean -public Saml2AuthenticationRequestResolver authenticationRequestResolver(RelyingPartyRegistrationRepository registrations) { - RelyingPartyRegistrationResolver registrationResolver = new DefaultRelyingPartyRegistrationResolver(registrations); - OpenSaml4AuthenticationRequestResolver authenticationRequestResolver = new OpenSaml4AuthenticationRequestResolver(registrationResolver); - - authenticationRequestResolver.setAuthnRequestCustomizer((context) -> { - // Set the required attributes - AuthnRequest authnRequest = context.getAuthnRequest(); - authnRequest.setID("_" + UUID.randomUUID().toString()); // Add a unique ID - authnRequest.setVersion(SAMLVersion.VERSION_20); // Ensure version is 2.0 - authnRequest.setProtocolBinding(SAMLConstants.SAML2_POST_BINDING_URI); // HTTP-POST - - // Set Authentication Context - authnRequest.setRequestedAuthnContext(buildRequestedAuthnContext()); - - // Log the SAML AuthnRequest after setting context - String samlRequest = SamlRequestLogger.convertSAMLObjectToString(authnRequest); - logger.info("SAML AuthnRequest after setting context: " + samlRequest); - }); - - return authenticationRequestResolver; -} - -private RequestedAuthnContext buildRequestedAuthnContext() { - AuthnContextClassRefBuilder authnContextClassRefBuilder = new AuthnContextClassRefBuilder(); - AuthnContextClassRef authnContextClassRef = authnContextClassRefBuilder.buildObject( - SAMLConstants.SAML20_NS, AuthnContextClassRef.DEFAULT_ELEMENT_LOCAL_NAME, SAMLConstants.SAML20_PREFIX - ); - // Set the SPID Level 2 authentication context - authnContextClassRef.setURI("urn:oasis:names:tc:SAML:2.0:ac:classes:SecureRemotePassword"); - - RequestedAuthnContextBuilder requestedAuthnContextBuilder = new RequestedAuthnContextBuilder(); - RequestedAuthnContext requestedAuthnContext = requestedAuthnContextBuilder.buildObject(); - requestedAuthnContext.setComparison(AuthnContextComparisonTypeEnumeration.EXACT); - requestedAuthnContext.getAuthnContextClassRefs().add(authnContextClassRef); - - return requestedAuthnContext; -} - - public PrivateKey readPrivateKey() throws Exception { - // Path to your private key PEM file - try (PemReader pemReader = new PemReader(new InputStreamReader(readKey("dev/saml/private-key.pem")))) { - // Read the PEM content - byte[] pemContent = pemReader.readPemObject().getContent(); - // Decode the PEM content - PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pemContent); - KeyFactory keyFactory = KeyFactory.getInstance("RSA"); // Use RSA algorithm - // Generate and return the PrivateKey - return keyFactory.generatePrivate(keySpec); - } - } - public X509Certificate readCertificate() throws Exception { - // Path to your certificate PEM fileFile - try (InputStream inStream = readKey("dev/saml/public-cert.pem")) { - CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); - return (X509Certificate) certFactory.generateCertificate(inStream); - } - } - - public X509Certificate readIdpCertificate() throws Exception { - // Path to your IDP public certificate PEM file - try (InputStream inStream = readKey("dev/saml/idp-certificate.pem")) { - CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); - return (X509Certificate) certFactory.generateCertificate(inStream); - } - } - - - public InputStream readKey(String path) throws IOException { - ClassLoader classLoader = getClass().getClassLoader(); - InputStream inputStream = classLoader.getResourceAsStream(path); - - if (inputStream == null) { - throw new FileNotFoundException("file not found : "+path); - } - return inputStream; - } + } \ No newline at end of file From b997fb3a5aa89ddf75dfe350b0e9dfdf0e64c17e Mon Sep 17 00:00:00 2001 From: nisha Date: Tue, 24 Sep 2024 20:03:28 +0530 Subject: [PATCH 27/58] Added callStatus in get api of form --- src/main/java/net/gepafin/tendermanagement/dao/FormDao.java | 1 + .../tendermanagement/model/response/FormResponseBean.java | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java b/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java index 8121f9e6..1d5ad1a1 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java @@ -73,6 +73,7 @@ public class FormDao { formResponseBean.setContent(Utils.convertJsonStringToList(formEntity.getContent(), ContentResponseBean.class)); formResponseBean.setLabel(formEntity.getLabel()); formResponseBean.setCallId(formEntity.getCall().getId()); + formResponseBean.setCallStatus(formEntity.getCall().getStatus()); return formResponseBean; } public FormResponseBean createForm(Long callId,FormRequest formRequest){ diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/FormResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/FormResponseBean.java index 7e3ebce1..7a1d178e 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/FormResponseBean.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/FormResponseBean.java @@ -9,6 +9,8 @@ public class FormResponseBean { private Long id; + private String callStatus; + private String label; private Long callId; From 30061c514ddc97a434f64dca9a5314761fb03180 Mon Sep 17 00:00:00 2001 From: harish Date: Wed, 25 Sep 2024 11:59:42 +0530 Subject: [PATCH 28/58] Updated code --- src/main/resources/application-production.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/application-production.properties b/src/main/resources/application-production.properties index 2132264d..51940c65 100644 --- a/src/main/resources/application-production.properties +++ b/src/main/resources/application-production.properties @@ -6,6 +6,6 @@ spring.datasource.driver-class-name=org.postgresql.Driver # JPA Configuration spring.h2.console.enabled=true -base-url=https://api-dev-gepafin.memento.credit +base-url=http://79.137.88.15 isVatCheckGloballyDisabled = false From 49f5eb08838f21e360395b63508d9a0d502dd348 Mon Sep 17 00:00:00 2001 From: nisha Date: Wed, 25 Sep 2024 12:25:29 +0530 Subject: [PATCH 29/58] Updated response of application api --- .../constants/GepafinConstant.java | 3 +- .../tendermanagement/dao/ApplicationDao.java | 32 +++++++++++++++++++ .../tendermanagement/dao/FlowFormDao.java | 28 ++++++++++------ .../model/response/ApplicationResponse.java | 8 +++++ src/main/resources/message_en.properties | 2 ++ src/main/resources/message_it.properties | 3 ++ 6 files changed, 66 insertions(+), 10 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index 395d883c..ad8ca5b4 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -155,6 +155,7 @@ public class GepafinConstant { public static final String IS_CAP="isCAP"; public static final String IS_CODICE_FISCALE="isCodiceFiscale"; public static final String IS_PIVA="isPIVA"; - public static final String FAILED_RETAIN_FIELD="failed.retain.field"; + public static final String TOTAL_STEPS_NOT_BE_ZERO="total.steps.not.zero"; + public static final String COMPLETED_STEPS_NOT_VALID="completed.steps.not.valid"; } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java index d153ed5c..8d19b48d 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java @@ -13,14 +13,17 @@ import net.gepafin.tendermanagement.model.response.*; import net.gepafin.tendermanagement.repositories.ApplicationFormFieldRepository; import net.gepafin.tendermanagement.repositories.ApplicationFormRepository; import net.gepafin.tendermanagement.repositories.ApplicationRepository; +import net.gepafin.tendermanagement.repositories.FlowEdgesRepository; import net.gepafin.tendermanagement.service.CallService; import net.gepafin.tendermanagement.service.DocumentService; import net.gepafin.tendermanagement.service.FormService; import net.gepafin.tendermanagement.util.DateTimeUtil; +import net.gepafin.tendermanagement.util.FieldValidator; import net.gepafin.tendermanagement.util.Utils; import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException; import net.gepafin.tendermanagement.web.rest.api.errors.Status; +import org.checkerframework.checker.units.qual.A; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -56,6 +59,12 @@ public class ApplicationDao { @Autowired private CallDao callDao; + @Autowired + private FlowFormDao flowFormDao; + + @Autowired + private FlowEdgesRepository flowEdgesRepository; + public ApplicationResponseBean createApplication(ApplicationRequestBean applicationRequestBean, UserEntity userEntity, Long formId,Long applicationId) { FormEntity formEntity = formService.validateForm(formId); CallEntity call = callService.validatePublishedCall(formEntity.getCall().getId()); @@ -204,7 +213,16 @@ public class ApplicationDao { private ApplicationResponse getApplicationResponse(ApplicationEntity applicationEntity) { ApplicationResponse responseBean = new ApplicationResponse(); + List flowEdgesList = flowEdgesRepository.findByCallId(applicationEntity.getCall().getId()); + Long totalFormSteps = flowFormDao.calculateTotalSteps(flowEdgesList); + List applicationFormList = applicationFormRepository.findByApplicationId(applicationEntity.getId()); + Long completedSteps=(Long.valueOf(applicationFormList.size())); + Integer progress=calculateProgress(totalFormSteps,completedSteps); responseBean.setId(applicationEntity.getId()); + responseBean.setProgress(progress); + responseBean.setCallTitle(applicationEntity.getCall().getName()); + responseBean.setCallEndDate(applicationEntity.getCall().getEndDate()); + responseBean.setModifiedDate(applicationEntity.getCall().getUpdatedDate()); responseBean.setCallId(applicationEntity.getCall().getId()); responseBean.setSubmissionDate(applicationEntity.getSubmissionDate()); responseBean.setStatus(applicationEntity.getStatus()); @@ -451,4 +469,18 @@ public class ApplicationDao { } saveApplicationEntity(applicationEntity); } + + public Integer calculateProgress(Long totalSteps, Long completedSteps) { + if (FieldValidator.isNullOrZero(totalSteps)) { + throw new CustomValidationException(Status.BAD_REQUEST,Translator.toLocale(GepafinConstant.TOTAL_STEPS_NOT_BE_ZERO)); + } + + if (completedSteps < 0 || completedSteps > totalSteps) { + throw new CustomValidationException(Status.BAD_REQUEST,Translator.toLocale(GepafinConstant.COMPLETED_STEPS_NOT_VALID)); + } + + double progress = ((double) completedSteps / totalSteps) * 100; + return (int) Math.round(progress); + } + } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java b/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java index a6f6a867..63287e0d 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java @@ -290,21 +290,31 @@ public class FlowFormDao { nextOrPreviousFormResponse.setCallTitle(applicationEntity.getCall().getName()); List flowEdgesList = flowEdgesRepository.findByCallId(applicationEntity.getCall().getId()); - Long totalFormSteps = 3l; - if (flowEdgesList.size() == 1) { - totalFormSteps = 2l; - } + Long totalFormSteps = calculateTotalSteps(flowEdgesList); + Long currentStep = calculateCurrentStep(formEntity); + List applicationFormList = applicationFormRepository.findByApplicationId(applicationEntity.getId()); + nextOrPreviousFormResponse.setTotalFormSteps(totalFormSteps); + nextOrPreviousFormResponse.setCompletedSteps(Long.valueOf(applicationFormList.size())); + nextOrPreviousFormResponse.setCurrentStep(currentStep); + return nextOrPreviousFormResponse; + } + + public Long calculateCurrentStep(FormEntity formEntity) { Long currentStep = 2l; if (formEntity.getId().equals(formEntity.getCall().getInitialForm())) { currentStep = 1l; } else if (formEntity.getId().equals(formEntity.getCall().getFinalForm())) { currentStep = 3l; } - List applicationFormList = applicationFormRepository.findByApplicationId(applicationEntity.getId()); - nextOrPreviousFormResponse.setTotalFormSteps(totalFormSteps); - nextOrPreviousFormResponse.setCompletedSteps(Long.valueOf(applicationFormList.size())); - nextOrPreviousFormResponse.setCurrentStep(currentStep); - return nextOrPreviousFormResponse; + return currentStep; + } + + public Long calculateTotalSteps(List flowEdgesList) { + Long totalFormSteps = 3l; + if (flowEdgesList.size() == 1) { + totalFormSteps = 2l; + } + return totalFormSteps; } private Long getDefaultForm(ApplicationEntity applicationEntity) { diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationResponse.java index fdb0f6f3..b5a0fbb2 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationResponse.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationResponse.java @@ -13,6 +13,14 @@ public class ApplicationResponse{ private Long callId; + private String callTitle; + + private LocalDateTime callEndDate; + + private LocalDateTime modifiedDate; + + private Integer progress; + private LocalDateTime submissionDate; private String status; diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index 981ed852..12b06608 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -184,3 +184,5 @@ valid.vat.number=The VAT number is not valid for field {0}. failed.retain.field=Failed to retain specific fields. application.is.incomplete = The application is incomplete. +total.steps.not.zero=Total steps cannot be zero. +completed.steps.not.valid=Completed steps should be between 0 and total steps. \ No newline at end of file diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index 5a7899df..a7d9068e 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -176,3 +176,6 @@ validation.marca.da.bollo=Il campo {0} deve essere una Marca Da Bollo valida con validation.piva=Il numero di partita IVA per {0} deve essere lungo fino a 11 cifre. valid.vat.number=Il numero di partita IVA non � valido per il campo {0}. failed.retain.field=Impossibile conservare campi specifici. + +total.steps.not.zero=Il totale dei passaggi non può essere zero. +completed.steps.not.valid=I passaggi completati devono essere compresi tra 0 e il totale dei passaggi. From cfdb872f49a44a7a217d124555f3596a5c57161a Mon Sep 17 00:00:00 2001 From: nisha Date: Wed, 25 Sep 2024 16:33:41 +0530 Subject: [PATCH 30/58] updated code --- .../tendermanagement/dao/ApplicationDao.java | 18 ++++++++++++++---- .../repositories/ApplicationRepository.java | 3 +++ .../tendermanagement/web/rest/api/FormApi.java | 2 ++ .../web/rest/api/FormFieldApi.java | 6 ++++++ 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java index 8d19b48d..6b310bc6 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java @@ -174,10 +174,9 @@ public class ApplicationDao { } public List getAllApplications(UserEntity userEntity, Long callId) { - RoleStatusEnum roleStatus = RoleStatusEnum.valueOf(userEntity.getRoleEntity().getRoleType()); - boolean isBeneficiary = RoleStatusEnum.ROLE_BENEFICIARY.equals(roleStatus); + boolean isBeneficiary = isBeneficiary(userEntity); - log.info("Fetching applications for RoleType: {}", roleStatus); + log.info("Fetching applications for RoleType: {}", userEntity.getRoleEntity().getRoleType()); List applicationResponses = new ArrayList<>(); if (callId != null) { @@ -351,7 +350,12 @@ public class ApplicationDao { public ApplicationGetResponseBean getApplicationByFormId( Long applicationId,Long formId, UserEntity userEntity) { List formApplicationResponses = new ArrayList<>(); List formEntities = new ArrayList<>(); - ApplicationEntity applicationEntity = applicationRepository.findById(applicationId) + boolean isBeneficiary = isBeneficiary(userEntity); + ApplicationEntity applicationEntity = isBeneficiary + ? applicationRepository.findByIdAndUserIdAndIsDeletedFalse(applicationId,userEntity.getId()) + .orElseThrow(() -> new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPLICATION_NOT_FOUND_MSG))) + : applicationRepository.findById(applicationId) + .stream().findFirst() .orElseThrow(() -> new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPLICATION_NOT_FOUND_MSG))); if (formId != null) { @@ -374,6 +378,12 @@ public class ApplicationDao { return createApplicationGetResponseBean(applicationEntity, formEntities, formApplicationResponses); } + private boolean isBeneficiary(UserEntity userEntity) { + RoleStatusEnum roleStatus = RoleStatusEnum.valueOf(userEntity.getRoleEntity().getRoleType()); + boolean isBeneficiary = RoleStatusEnum.ROLE_BENEFICIARY.equals(roleStatus); + return isBeneficiary; + } + private void addFormApplication(FormEntity formEntity, ApplicationEntity applicationEntity, List formApplicationResponses) { FormApplicationResponse formApplicationResponse = processForm(formEntity, applicationEntity); diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java index 8d41608c..ad9104a5 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java @@ -23,4 +23,7 @@ public interface ApplicationRepository extends JpaRepository findByCallIdAndIsDeletedFalse(Long callId); public List findByIsDeletedFalse(); + + public Optional findByIdAndUserIdAndIsDeletedFalse(Long id,Long userId); + } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/FormApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/FormApi.java index 04417439..99eb8835 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/FormApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/FormApi.java @@ -49,6 +49,7 @@ public interface FormApi { @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) @PutMapping(value = "/{formId}", produces = { "application/json" }) + @PreAuthorize("hasRole('ROLE_SUPER_ADMIN')") ResponseEntity> updateForm(HttpServletRequest request, @Parameter(description = "The form ID", required = true) @PathVariable("formId") Long formId, @Parameter(description = "form request object", required = true) @Valid @RequestBody FormRequest formRequest,@Parameter(description = "force delete flow ",required = true)@RequestParam(value = "forceDeleteFlow",required = true)Boolean forceDeleteFlow); @@ -78,6 +79,7 @@ public interface FormApi { @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) @DeleteMapping(value = "/{formId}") + @PreAuthorize("hasRole('ROLE_SUPER_ADMIN')") ResponseEntity> deleteForm(HttpServletRequest request, @Parameter(description = "The form ID", required = true) @PathVariable("formId") Long formId); diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/FormFieldApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/FormFieldApi.java index 341b3fed..0aeecf0f 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/FormFieldApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/FormFieldApi.java @@ -13,6 +13,7 @@ import net.gepafin.tendermanagement.model.util.Response; import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import java.util.List; @@ -30,6 +31,7 @@ public interface FormFieldApi { @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) @PostMapping(value = "", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE) + @PreAuthorize("hasRole('ROLE_SUPER_ADMIN')") public ResponseEntity> createFormField(HttpServletRequest request, @Parameter(description = "form field request object", required = true) @Valid @RequestBody FormFieldRequest formFieldRequest); @@ -46,6 +48,7 @@ public interface FormFieldApi { @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) @PutMapping(value = "/{formFieldId}", produces = { "application/json" }) + @PreAuthorize("hasRole('ROLE_SUPER_ADMIN')") ResponseEntity> updateFormField(HttpServletRequest request, @Parameter(description = "The form field ID", required = true) @PathVariable("formFieldId") Long formFieldId, @Parameter(description = "form field request object", required = true) @Valid @RequestBody FormFieldRequest formFieldRequest); @@ -61,6 +64,7 @@ public interface FormFieldApi { @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) @GetMapping(value = "/{formFieldId}", produces = { "application/json" }) + @PreAuthorize("hasRole('ROLE_SUPER_ADMIN')") ResponseEntity> getFormFieldById(HttpServletRequest request, @Parameter(description = "The form field ID", required = true) @PathVariable("formFieldId") Long formFieldId); @@ -75,6 +79,7 @@ public interface FormFieldApi { @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) @DeleteMapping(value = "/{formFieldId}") + @PreAuthorize("hasRole('ROLE_SUPER_ADMIN')") ResponseEntity> deleteForm(HttpServletRequest request, @Parameter(description = "The form field ID", required = true) @PathVariable("formFieldId") Long formFieldId); @@ -89,6 +94,7 @@ public interface FormFieldApi { @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) @GetMapping(value = "", produces = { "application/json" }) + @PreAuthorize("hasRole('ROLE_SUPER_ADMIN')") ResponseEntity>> getAllFormField(HttpServletRequest request); } From db42874e75ff4c57151532ad02119b74247bdede Mon Sep 17 00:00:00 2001 From: nisha Date: Wed, 25 Sep 2024 18:12:31 +0530 Subject: [PATCH 31/58] Applied validation application form field --- .../constants/GepafinConstant.java | 1 + .../tendermanagement/dao/ApplicationDao.java | 21 +++++++++++++++++++ src/main/resources/message_en.properties | 3 ++- src/main/resources/message_it.properties | 1 + 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index ad8ca5b4..00fdc267 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -158,4 +158,5 @@ public class GepafinConstant { public static final String FAILED_RETAIN_FIELD="failed.retain.field"; public static final String TOTAL_STEPS_NOT_BE_ZERO="total.steps.not.zero"; public static final String COMPLETED_STEPS_NOT_VALID="completed.steps.not.valid"; + public static final String FIELD_ID_NOT_FOUND="field.id.not.found"; } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java index 6b310bc6..8c05ca89 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java @@ -29,6 +29,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.text.MessageFormat; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; @@ -68,6 +69,7 @@ public class ApplicationDao { public ApplicationResponseBean createApplication(ApplicationRequestBean applicationRequestBean, UserEntity userEntity, Long formId,Long applicationId) { FormEntity formEntity = formService.validateForm(formId); CallEntity call = callService.validatePublishedCall(formEntity.getCall().getId()); + validateFormFields(applicationRequestBean,formEntity); ApplicationEntity applicationEntity = validateApplication(applicationId); if(Boolean.TRUE.equals(applicationEntity.getStatus().equals(ApplicationStatusTypeEnum.SUBMIT.getValue()))){ throw new CustomValidationException(Status.BAD_REQUEST,Translator.toLocale(GepafinConstant.APPLICATION_ALREADY_SUBMITTED)); @@ -492,5 +494,24 @@ public class ApplicationDao { double progress = ((double) completedSteps / totalSteps) * 100; return (int) Math.round(progress); } + public void validateFormFields(ApplicationRequestBean request, FormEntity formEntity) { + List errors=new ArrayList<>(); + List contentResponseBeans=Utils.convertJsonStringToList(formEntity.getContent(),ContentResponseBean.class); + + List requestFields = request.getFormFields(); + + Map contentMap = contentResponseBeans.stream() + .collect(Collectors.toMap(ContentResponseBean::getId, ContentResponseBean::getLabel)); // Change getLabel() if needed + FieldValidator validator = FieldValidator.create(); + for (ApplicationFormFieldRequestBean requestField : requestFields) { + String fieldId = requestField.getFieldId(); + + if (!contentMap.containsKey(fieldId)) { + validator.addError(MessageFormat.format(Translator.toLocale(GepafinConstant.FIELD_ID_NOT_FOUND), fieldId)); + } + + } + validator.validate(); + } } diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index 12b06608..9f10dba0 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -185,4 +185,5 @@ failed.retain.field=Failed to retain specific fields. application.is.incomplete = The application is incomplete. total.steps.not.zero=Total steps cannot be zero. -completed.steps.not.valid=Completed steps should be between 0 and total steps. \ No newline at end of file +completed.steps.not.valid=Completed steps should be between 0 and total steps. +field.id.not.found=Field ID {0} does not exist in the form structure. \ No newline at end of file diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index a7d9068e..7a90dd8e 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -179,3 +179,4 @@ failed.retain.field=Impossibile conservare campi specifici. total.steps.not.zero=Il totale dei passaggi non può essere zero. completed.steps.not.valid=I passaggi completati devono essere compresi tra 0 e il totale dei passaggi. +field.id.not.found=L'ID campo {0} non esiste nella struttura del modulo. From ccaa3c9ffef279d69aa1023844d878b000cc7491 Mon Sep 17 00:00:00 2001 From: nisha Date: Wed, 25 Sep 2024 19:06:05 +0530 Subject: [PATCH 32/58] Updated code for form field value --- .../java/net/gepafin/tendermanagement/dao/ApplicationDao.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java index 8c05ca89..aae686d7 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java @@ -286,7 +286,7 @@ public class ApplicationDao { } } Utils.setIfUpdated(applicationFormFieldEntity::getFieldId, applicationFormFieldEntity::setFieldId, applicationFormFieldRequestBean.getFieldId()); - Utils.setIfUpdated(applicationFormFieldEntity::getFieldValue, applicationFormFieldEntity::setFieldValue, applicationFormFieldRequestBean.getFieldValue()); + applicationFormFieldEntity.setFieldValue(applicationFormFieldRequestBean.getFieldValue()); return applicationFormFieldRepository.save(applicationFormFieldEntity); } From d5524b7cc989f636884d58080133101d734d6c54 Mon Sep 17 00:00:00 2001 From: rajesh Date: Wed, 25 Sep 2024 20:12:34 +0530 Subject: [PATCH 33/58] created new api's for login with spid --- .../config/SamlFailureHandler.java | 18 +--- .../config/SamlSuccessHandler.java | 100 ++++++++++++------ .../config/SecurityConfig.java | 3 + .../config/jwt/TokenProvider.java | 11 +- .../constants/GepafinConstant.java | 4 + .../gepafin/tendermanagement/dao/UserDao.java | 47 +++++--- ...LogEntity.java => SamlResponseEntity.java} | 14 +-- .../tendermanagement/entities/UserEntity.java | 9 +- .../model/request/UserReq.java | 7 +- .../model/response/UserSamlResponse.java | 13 +++ .../SamlResponseLogRepository.java | 11 -- .../repositories/SamlResponseRepository.java | 13 +++ .../repositories/UserRepository.java | 7 ++ .../tendermanagement/service/UserService.java | 7 +- .../service/impl/AuthenticationService.java | 92 +++++++++++++--- .../service/impl/UserServiceImpl.java | 35 ++++-- .../gepafin/tendermanagement/util/Utils.java | 29 +++++ .../tendermanagement/util/Validator.java | 28 +++++ .../web/rest/api/UserApi.java | 41 ++++++- .../web/rest/api/impl/UserApiController.java | 20 +++- src/main/resources/application.properties | 1 + .../db/changelog/db.changelog-1.0.0.xml | 38 +++---- src/main/resources/message_en.properties | 4 + src/main/resources/message_it.properties | 4 + 24 files changed, 407 insertions(+), 149 deletions(-) rename src/main/java/net/gepafin/tendermanagement/entities/{SamlResponseLogEntity.java => SamlResponseEntity.java} (50%) create mode 100644 src/main/java/net/gepafin/tendermanagement/model/response/UserSamlResponse.java delete mode 100644 src/main/java/net/gepafin/tendermanagement/repositories/SamlResponseLogRepository.java create mode 100644 src/main/java/net/gepafin/tendermanagement/repositories/SamlResponseRepository.java diff --git a/src/main/java/net/gepafin/tendermanagement/config/SamlFailureHandler.java b/src/main/java/net/gepafin/tendermanagement/config/SamlFailureHandler.java index da5f3a65..1e740869 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SamlFailureHandler.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SamlFailureHandler.java @@ -4,23 +4,21 @@ import java.io.IOException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.stereotype.Component; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import net.gepafin.tendermanagement.entities.SamlResponseLogEntity; -import net.gepafin.tendermanagement.repositories.SamlResponseLogRepository; @Component public class SamlFailureHandler implements AuthenticationFailureHandler { private final Logger logger = LoggerFactory.getLogger(SamlSuccessHandler.class); - @Autowired - private SamlResponseLogRepository samlResponseLogRepository; + @Value("fe.base.url") + private String feBaseUrl; @Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, @@ -28,15 +26,7 @@ public class SamlFailureHandler implements AuthenticationFailureHandler { try { logger.error("SAML login failed: " + exception.getMessage()); - // Log the failure details to the database (Optional) - SamlResponseLogEntity samlResponseLogEntity = new SamlResponseLogEntity(); - samlResponseLogEntity.setRequest(request.toString()); - samlResponseLogEntity.setResponse(response.toString()); - samlResponseLogEntity.setExceptionObject(exception.toString()); - samlResponseLogRepository.save(samlResponseLogEntity); - - // Handle failure redirection - response.sendRedirect("http://gepafin-staging-fe.s3-website.eu-central-1.amazonaws.com/login"); + response.sendRedirect(feBaseUrl + "/login"); } catch (Exception e) { logger.error("Error processing SAML failure handler", e); } diff --git a/src/main/java/net/gepafin/tendermanagement/config/SamlSuccessHandler.java b/src/main/java/net/gepafin/tendermanagement/config/SamlSuccessHandler.java index ef7c0bb7..1ef52f87 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SamlSuccessHandler.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SamlSuccessHandler.java @@ -7,6 +7,7 @@ import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.Authentication; import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal; import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication; @@ -17,48 +18,77 @@ import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import net.gepafin.tendermanagement.entities.SamlResponseLogEntity; -import net.gepafin.tendermanagement.repositories.SamlResponseLogRepository; +import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.entities.SamlResponseEntity; +import net.gepafin.tendermanagement.entities.UserEntity; +import net.gepafin.tendermanagement.repositories.SamlResponseRepository; +import net.gepafin.tendermanagement.repositories.UserRepository; +import net.gepafin.tendermanagement.util.Utils; +import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; +import net.gepafin.tendermanagement.web.rest.api.errors.Status; @Component -public class SamlSuccessHandler implements AuthenticationSuccessHandler{ - +public class SamlSuccessHandler implements AuthenticationSuccessHandler { - private final Logger logger = LoggerFactory.getLogger(SamlSuccessHandler.class); - - @Autowired - private SamlResponseLogRepository samlResponseLogRepository; - - @Override - public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, - Authentication authentication) throws IOException { - try { - // Cast the authentication object to Saml2Authentication - Saml2Authentication samlAuth = (Saml2Authentication) authentication; - Saml2AuthenticatedPrincipal principal = (Saml2AuthenticatedPrincipal) samlAuth.getPrincipal(); + private final Logger logger = LoggerFactory.getLogger(SamlSuccessHandler.class); - // Extract the user attributes from the principal - Map> userAttributes = principal.getAttributes(); + @Autowired + private SamlResponseRepository samlResponseLogRepository; - // Log the user attributes for debugging purposes - logger.info("SAML User Attributes: " + userAttributes); + @Autowired + private UserRepository userRepository; - // Save the authentication details in the database (Optional) - SamlResponseLogEntity samlResponseLogEntity = new SamlResponseLogEntity(); - samlResponseLogEntity.setAuthenticationObject(authentication.toString()); + @Value("fe.base.url") + private String feBaseUrl; - // Convert user attributes to JSON and save in DB - ObjectMapper objectMapper = new ObjectMapper(); - String userAttributesJson = objectMapper.writeValueAsString(userAttributes); - samlResponseLogEntity.setAuthenticationObject(userAttributesJson); - samlResponseLogRepository.save(samlResponseLogEntity); + @Override + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, + Authentication authentication) throws IOException { + try { + Saml2Authentication samlAuth = (Saml2Authentication) authentication; + Saml2AuthenticatedPrincipal principal = (Saml2AuthenticatedPrincipal) samlAuth.getPrincipal(); - // Successful login logic - logger.info("SAML login successful for user: " + principal.getName()); - response.sendRedirect("http://gepafin-staging-fe.s3-website.eu-central-1.amazonaws.com/login"); - } catch (Exception e) { - logger.error("Error processing SAML success handler", e); - } - } + Map> userAttributes = principal.getAttributes(); + String token = Utils.generateSecureToken(); + logger.info("SAML User Attributes: " + userAttributes); + + SamlResponseEntity samlResponseLogEntity = new SamlResponseEntity(); + samlResponseLogEntity.setAuthenticationObject(authentication.toString()); + + ObjectMapper objectMapper = new ObjectMapper(); + String userAttributesJson = objectMapper.writeValueAsString(userAttributes); + samlResponseLogEntity.setAuthenticationObject(userAttributesJson); + samlResponseLogEntity.setToken(token); + samlResponseLogRepository.save(samlResponseLogEntity); + + // Successful login logic + logger.info("SAML login successful for user: " + principal.getName()); + String cf = userAttributes.get("CodiceFiscale").get(0).toString(); + UserEntity userEntity = userRepository.findByCodiceFiscale(cf).orElse(null); + if (userEntity == null) { + response.sendRedirect(feBaseUrl + "/registration?temp_token=" + token); + } else { + response.sendRedirect(feBaseUrl + "/login?temp_token=" + token); + } + } catch (Exception e) { + logger.error("Error processing SAML success handler", e); + } + } + + public void validateToken(String token, String codiceFiscale) { + SamlResponseEntity samlResponseLogEntity = samlResponseLogRepository.findByToken(token); + if (samlResponseLogEntity == null) { + throw new CustomValidationException(Status.VALIDATION_ERROR, + Translator.toLocale(GepafinConstant.INVALID_TOKEN_MSG)); + } + Map> userAttributes = Utils + .convertStringIntoMap(samlResponseLogEntity.getAuthenticationObject()); + String cf = userAttributes.get("CodiceFiscale").get(0).toString(); + if (codiceFiscale == null || Boolean.FALSE.equals(codiceFiscale.equals(cf))) { + throw new CustomValidationException(Status.VALIDATION_ERROR, + Translator.toLocale(GepafinConstant.INVALID_TOKEN_MSG)); + } + samlResponseLogRepository.delete(samlResponseLogEntity); + } } diff --git a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java index 17cf0253..91424195 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java @@ -99,6 +99,9 @@ public class SecurityConfig { http.csrf(AbstractHttpConfigurer::disable).authorizeHttpRequests(auth -> auth // Allow public access to the login endpoints .requestMatchers("/v1/user/login").permitAll() // JWT-based login + .requestMatchers("/v1/user").permitAll() // User registration + .requestMatchers("/v1/user/sso/validate/existing-user/{token}").permitAll() + .requestMatchers("/v1/user/sso/validate/new-user/{token}").permitAll() .requestMatchers("/v1/saml/**").permitAll() // JWT-based login .requestMatchers("/saml2/**").permitAll() // SAML login initiation .requestMatchers("/swagger-ui/**").permitAll() // Swagger docs diff --git a/src/main/java/net/gepafin/tendermanagement/config/jwt/TokenProvider.java b/src/main/java/net/gepafin/tendermanagement/config/jwt/TokenProvider.java index 15c51b7a..d299b6ff 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/jwt/TokenProvider.java +++ b/src/main/java/net/gepafin/tendermanagement/config/jwt/TokenProvider.java @@ -82,10 +82,11 @@ public class TokenProvider { log.info("JWT Secret Key initialized."); } - public String createToken(Authentication authentication, Boolean rememberMe, UserEntity user) { - String authorities = authentication.getAuthorities().stream() - .map(GrantedAuthority::getAuthority) - .collect(Collectors.joining(",")); + public String createToken(Boolean rememberMe, UserEntity user) { +// String authorities = authentication.getAuthorities().stream() +// .map(GrantedAuthority::getAuthority) +// .collect(Collectors.joining(",")); + String authorities = user.getRoleEntity().getRoleType(); Long now; Date validity; @@ -99,7 +100,7 @@ public class TokenProvider { log.info("Creating token with standard validity of {} seconds.", this.tokenValidityInSeconds); } - String payload = authentication.getName(); + String payload = user.getEmail(); if(user != null) { payload += ":"+user.getId(); } diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index 395d883c..874fafac 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -157,4 +157,8 @@ public class GepafinConstant { public static final String IS_PIVA="isPIVA"; public static final String FAILED_RETAIN_FIELD="failed.retain.field"; + public static final String USER_ALREADY_EXIST_MSG = "user.already.exist.msg"; + public static final String TOKEN_VALIDATE_SUCCESS_MGE = "token.validate.success.mge"; + public static final String INVALID_REQUEST = "invalid.request"; + public static final String CODICE_FISCALE_EXISTS = "codice.fiscale.exists"; } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java index 81033b05..8dddbfea 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java @@ -9,20 +9,22 @@ import net.gepafin.tendermanagement.entities.UserEntity; import net.gepafin.tendermanagement.enums.UserStatusEnum; import net.gepafin.tendermanagement.model.request.*; import net.gepafin.tendermanagement.model.response.RoleResponseBean; +import net.gepafin.tendermanagement.model.response.UserSamlResponse; import net.gepafin.tendermanagement.model.response.UserResponseBean; import net.gepafin.tendermanagement.model.util.JWTToken; import net.gepafin.tendermanagement.repositories.UserRepository; import net.gepafin.tendermanagement.service.impl.AuthenticationService; +import net.gepafin.tendermanagement.util.Utils; import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException; import net.gepafin.tendermanagement.web.rest.api.errors.Status; + +import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Repository; -import java.security.SecureRandom; -import java.util.Base64; import static net.gepafin.tendermanagement.util.Utils.setIfUpdated; @@ -43,24 +45,32 @@ public class UserDao { @Autowired private RoleDao roleDao; - public UserResponseBean createUser(UserReq userReq) { + public JWTToken createUser(HttpServletRequest request, String tempToken, UserReq userReq) { log.info("Creating user with email: {}", userReq.getEmail()); if (userRepository.existsByEmailIgnoreCase(userReq.getEmail())) { log.error("User creation failed: Email {} already exists", userReq.getEmail()); throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.EMAIL_ALREADY_EXISTS)); } - if (!userReq.getPassword().equals(userReq.getConfPassword())) { + if (Boolean.FALSE.equals(StringUtils.isEmpty(userReq.getCodiceFiscale())) && userRepository.existsByCodiceFiscale(userReq.getCodiceFiscale())) { + log.error("User creation failed: CodiceFiscale {} already exists", userReq.getCodiceFiscale()); + throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.CODICE_FISCALE_EXISTS)); + } + if(tempToken == null && (StringUtils.isEmpty(userReq.getPassword()) || StringUtils.isEmpty(userReq.getConfPassword()))) { + throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.INVALID_REQUEST)); + } + if (tempToken == null && !userReq.getPassword().equals(userReq.getConfPassword())) { log.error("User creation failed: Passwords do not match for email {}", userReq.getEmail()); throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.PASSWORD_DOESNT_MATCH)); } - if (userReq.getPassword().length() < 8) { + if (tempToken == null && userReq.getPassword().length() < 8) { log.error("User creation failed: Password length is less than 8 characters for email {}", userReq.getEmail()); throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.PASSWORD_MIN_LEN)); } + UserEntity userEntity = convertUserRequestToUserEntity(userReq); userEntity = userRepository.save(userEntity); log.info("User created with ID: {}", userEntity.getId()); - return convertUserEntityToUserResponse(userEntity); + return authService.getJWTTokenBean(userEntity, Boolean.TRUE); } public UserResponseBean updateUser(Long userId, UpdateUserReq userReq) { @@ -88,15 +98,18 @@ public class UserDao { private UserEntity convertUserRequestToUserEntity(UserReq userReq) { UserEntity userEntity = new UserEntity(); - userEntity.setPassword(passwordEncoder.encode(userReq.getPassword())); + if(Boolean.FALSE.equals(StringUtils.isEmpty(userReq.getPassword()))) { + userEntity.setPassword(passwordEncoder.encode(userReq.getPassword())); + } userEntity.setEmail(userReq.getEmail()); userEntity.setFirstName(userReq.getFirstName()); - userEntity.setStatus(UserStatusEnum.PENDING_VERIFICATION.getValue()); + userEntity.setStatus(UserStatusEnum.ACTIVE.getValue()); userEntity.setLastName(userReq.getLastName()); userEntity.setOrganization(userReq.getOrganization()); userEntity.setAddress(userReq.getAddress()); userEntity.setPhoneNumber(userReq.getPhoneNumber()); userEntity.setRoleEntity(roleDao.validateRole(userReq.getRoleId())); + userEntity.setCodiceFiscale(userReq.getCodiceFiscale()); return userEntity; } @@ -150,14 +163,6 @@ public class UserDao { .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG))); } - public String generateSecureToken() { - SecureRandom secureRandom = new SecureRandom(); - byte[] tokenBytes = new byte[24]; - secureRandom.nextBytes(tokenBytes); - String token = Base64.getUrlEncoder().withoutPadding().encodeToString(tokenBytes); - log.debug("Generated secure token: {}", token); - return token; - } public String initiatePasswordReset(InitiatePasswordResetReq resetReq) { UserEntity user = userRepository.findByEmail(resetReq.getEmail()); @@ -165,7 +170,7 @@ public class UserDao { log.info("Password reset attempt for non-existent user: {}", resetReq.getEmail()); throw new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG)); } - String token = generateSecureToken(); + String token = Utils.generateSecureToken(); user.setResetPasswordToken(token); userRepository.save(user); log.info("Password reset token generated for user: {}", resetReq.getEmail()); @@ -227,4 +232,12 @@ public class UserDao { return convertUserEntityToUserResponse(userEntity); } + public JWTToken validateExistingUserToken(String token) { + return authService.validateExistingUserToken(token); + } + + public UserSamlResponse validateNewUserToken(String token) { + return authService.validateNewUserToken(token); + } + } diff --git a/src/main/java/net/gepafin/tendermanagement/entities/SamlResponseLogEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/SamlResponseEntity.java similarity index 50% rename from src/main/java/net/gepafin/tendermanagement/entities/SamlResponseLogEntity.java rename to src/main/java/net/gepafin/tendermanagement/entities/SamlResponseEntity.java index 53e262e9..732edfd9 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/SamlResponseLogEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/SamlResponseEntity.java @@ -6,21 +6,15 @@ import jakarta.persistence.Table; import lombok.Data; @Entity -@Table(name = "SAML_RESPONSE_LOG") +@Table(name = "SAML_RESPONSE") @Data -public class SamlResponseLogEntity extends BaseEntity{ - - @Column(name = "REQUEST") - private String request; - - @Column(name = "RESPONSE") - private String response; +public class SamlResponseEntity extends BaseEntity{ @Column(name = "AUTHENTICATION_OBJECT") private String authenticationObject; - @Column(name = "EXCEPTION_OBJECT") - private String exceptionObject; + @Column(name = "TOKEN") + private String token; } diff --git a/src/main/java/net/gepafin/tendermanagement/entities/UserEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/UserEntity.java index 5bd88f33..0a0c9016 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/UserEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/UserEntity.java @@ -1,6 +1,5 @@ package net.gepafin.tendermanagement.entities; -import com.fasterxml.jackson.annotation.JsonValue; import jakarta.persistence.*; import jakarta.validation.constraints.Email; @@ -17,7 +16,7 @@ import java.time.LocalDateTime; @Setter public class UserEntity extends BaseEntity { - @Column(name = "PASSWORD", columnDefinition = "TEXT",nullable = false) + @Column(name = "PASSWORD", columnDefinition = "TEXT",nullable = true) @JsonIgnore private String password; @@ -29,8 +28,7 @@ public class UserEntity extends BaseEntity { @JoinColumn(name = "ROLE_ID") @JsonIgnore private RoleEntity roleEntity; - - + @Column(name = "LAST_LOGIN") private LocalDateTime lastLogin; @@ -60,4 +58,7 @@ public class UserEntity extends BaseEntity { @Column(name = "RESET_PASSWORD_TOKEN", length = 255, nullable = true) private String resetPasswordToken; + + @Column(name = "CODICE_FISCALE") + private String codiceFiscale; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/UserReq.java b/src/main/java/net/gepafin/tendermanagement/model/request/UserReq.java index 7dacab15..e81bdaf3 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/request/UserReq.java +++ b/src/main/java/net/gepafin/tendermanagement/model/request/UserReq.java @@ -2,7 +2,6 @@ package net.gepafin.tendermanagement.model.request; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -12,9 +11,9 @@ public class UserReq { @NotBlank @Email private String email; - @NotEmpty + private String password; - @NotEmpty + private String confPassword; private String firstName; @@ -32,5 +31,7 @@ public class UserReq { private String city; private String country; + + private String codiceFiscale; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/UserSamlResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/UserSamlResponse.java new file mode 100644 index 00000000..da732bd4 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/UserSamlResponse.java @@ -0,0 +1,13 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; + +@Data +public class UserSamlResponse { + + private String codiceFiscale; + + private String firstName; + + private String lastName; +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/SamlResponseLogRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/SamlResponseLogRepository.java deleted file mode 100644 index 3f98e083..00000000 --- a/src/main/java/net/gepafin/tendermanagement/repositories/SamlResponseLogRepository.java +++ /dev/null @@ -1,11 +0,0 @@ -package net.gepafin.tendermanagement.repositories; - -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -import net.gepafin.tendermanagement.entities.SamlResponseLogEntity; - -@Repository -public interface SamlResponseLogRepository extends JpaRepository { - -} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/SamlResponseRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/SamlResponseRepository.java new file mode 100644 index 00000000..9183f339 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/repositories/SamlResponseRepository.java @@ -0,0 +1,13 @@ +package net.gepafin.tendermanagement.repositories; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import net.gepafin.tendermanagement.entities.SamlResponseEntity; + +@Repository +public interface SamlResponseRepository extends JpaRepository { + + SamlResponseEntity findByToken(String token); + +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java index 7720430c..68289e6d 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java @@ -6,7 +6,14 @@ import org.springframework.data.jpa.repository.JpaRepository; import java.util.Optional; public interface UserRepository extends JpaRepository { + Optional findByEmailIgnoreCase(String email); + boolean existsByEmailIgnoreCase(String email); + UserEntity findByEmail(String email); + + Optional findByCodiceFiscale(String cf); + + boolean existsByCodiceFiscale(String codiceFiscale); } diff --git a/src/main/java/net/gepafin/tendermanagement/service/UserService.java b/src/main/java/net/gepafin/tendermanagement/service/UserService.java index f925d7dd..57421978 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/UserService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/UserService.java @@ -8,11 +8,12 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import net.gepafin.tendermanagement.enums.UserStatusEnum; import net.gepafin.tendermanagement.model.request.*; +import net.gepafin.tendermanagement.model.response.UserSamlResponse; import net.gepafin.tendermanagement.model.response.UserResponseBean; import net.gepafin.tendermanagement.model.util.JWTToken; public interface UserService { - UserResponseBean createUser(UserReq userReq); + JWTToken createUser(HttpServletRequest request, String tempToken, UserReq userReq); UserResponseBean updateUser(Long userId, UpdateUserReq userReq); @@ -35,4 +36,8 @@ public interface UserService { UserResponseBean updateUserStatus(Long userId, UserStatusEnum statusReq); UserResponseBean getValidUser(HttpServletRequest request); + + JWTToken validateExistingUserToken(HttpServletRequest request, String token); + + UserSamlResponse validateNewUserToken(HttpServletRequest request, String token); } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java b/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java index bf853124..1b61baa7 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java @@ -6,15 +6,20 @@ import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.config.jwt.TokenProvider; import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.dao.RoleDao; +import net.gepafin.tendermanagement.entities.SamlResponseEntity; import net.gepafin.tendermanagement.entities.UserEntity; import net.gepafin.tendermanagement.enums.UserStatusEnum; import net.gepafin.tendermanagement.model.request.LoginReq; import net.gepafin.tendermanagement.model.response.LoginResponse; import net.gepafin.tendermanagement.model.response.RoleResponseBean; +import net.gepafin.tendermanagement.model.response.UserSamlResponse; import net.gepafin.tendermanagement.model.util.JWTToken; +import net.gepafin.tendermanagement.repositories.SamlResponseRepository; import net.gepafin.tendermanagement.repositories.UserRepository; import net.gepafin.tendermanagement.util.DateTimeUtil; +import net.gepafin.tendermanagement.util.Utils; import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; +import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException; import net.gepafin.tendermanagement.web.rest.api.errors.Status; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -27,6 +32,8 @@ import org.springframework.security.web.authentication.logout.SecurityContextLog import org.springframework.stereotype.Service; import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; @Service public class AuthenticationService { @@ -41,6 +48,9 @@ public class AuthenticationService { @Autowired private RoleDao roleDao; + + @Autowired + private SamlResponseRepository samlResponseLogRepository; @Autowired public AuthenticationService(TokenProvider tokenProvider, AuthenticationManager authenticationManager) { @@ -55,27 +65,32 @@ public class AuthenticationService { Authentication authentication = this.authenticationManager.authenticate(authenticationToken); SecurityContextHolder.getContext().setAuthentication(authentication); log.info("Authentication successful for email: {}", loginReq.getEmail()); - UserEntity user = userRepository.findByEmailIgnoreCase(loginReq.getEmail()).orElseThrow(()-> new CustomValidationException(Status.NOT_FOUND, - Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG))); - if (Boolean.FALSE.equals(UserStatusEnum.ACTIVE.getValue().equals(user.getStatus()))) { - throw new CustomValidationException(Status.NOT_FOUND, - Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG)); + UserEntity user = userRepository.findByEmailIgnoreCase(loginReq.getEmail()) + .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, + Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG))); + if (Boolean.FALSE.equals(UserStatusEnum.ACTIVE.getValue().equals(user.getStatus()))) { + throw new ResourceNotFoundException(Status.NOT_FOUND, + Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG)); } + return getJWTTokenBean(user, loginReq.getRememberMe()); + } + + public JWTToken getJWTTokenBean(UserEntity user, Boolean rememberMe) { user.setLastLogin(DateTimeUtil.DateServerToUTC(LocalDateTime.now())); userRepository.save(user); - String token = tokenProvider.createToken(authentication, loginReq.getRememberMe(), user); - log.info("JWT token generated for email: {}", loginReq.getEmail()); + String token = tokenProvider.createToken(rememberMe, user); + log.info("JWT token generated for email: {}", user.getEmail()); RoleResponseBean roleResponseBean = roleDao.convertRoleEntityToRoleResponse(user.getRoleEntity()); LoginResponse loginResponse = getLoginResponse(user, roleResponseBean); JWTToken jwtToken = new JWTToken(token, loginResponse); - log.info("Login successful for email: {}", loginReq.getEmail()); - return jwtToken; - } - - private static LoginResponse getLoginResponse(UserEntity user, RoleResponseBean roleResponseBean) { + log.info("Login successful for email: {}", user.getEmail()); + return jwtToken; + } + + private static LoginResponse getLoginResponse(UserEntity user, RoleResponseBean roleResponseBean) { LoginResponse loginResponse = new LoginResponse(); loginResponse.setId(user.getId()); loginResponse.setEmail(user.getEmail()); @@ -93,8 +108,8 @@ public class AuthenticationService { loginResponse.setUpdatedDate(user.getUpdatedDate()); return loginResponse; } - public void logout(HttpServletRequest request, HttpServletResponse response) - { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + public void logout(HttpServletRequest request, HttpServletResponse response) { + Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth != null) { String token = tokenProvider.extractTokenFromRequest(request); tokenProvider.invalidateToken(token); @@ -102,6 +117,53 @@ public class AuthenticationService { } SecurityContextHolder.getContext().setAuthentication(null); SecurityContextHolder.clearContext(); -} + } + + public JWTToken validateExistingUserToken(String token) { + SamlResponseEntity samlResponseLogEntity = samlResponseLogRepository.findByToken(token); + if (samlResponseLogEntity == null) { + log.info("Invalid spid login token : {}", token); + throw new CustomValidationException(Status.VALIDATION_ERROR, + Translator.toLocale(GepafinConstant.INVALID_TOKEN_MSG)); + } + Map> userAttributes = Utils + .convertStringIntoMap(samlResponseLogEntity.getAuthenticationObject()); + String cf = userAttributes.get("CodiceFiscale").get(0).toString(); + UserEntity userEntity = userRepository.findByCodiceFiscale(cf) + .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, + Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG))); + samlResponseLogRepository.delete(samlResponseLogEntity); + + return getJWTTokenBean(userEntity, Boolean.TRUE); + } + + + public UserSamlResponse validateNewUserToken(String token) { + SamlResponseEntity samlResponseLogEntity = samlResponseLogRepository.findByToken(token); + if (samlResponseLogEntity == null) { + log.info("Invalid spid login token : {}", token); + throw new CustomValidationException(Status.VALIDATION_ERROR, + Translator.toLocale(GepafinConstant.INVALID_TOKEN_MSG)); + } + Map> userAttributes = Utils + .convertStringIntoMap(samlResponseLogEntity.getAuthenticationObject()); + String cf = userAttributes.get("CodiceFiscale").get(0).toString(); + if (userRepository.findByCodiceFiscale(cf).isPresent()) { + throw new ResourceNotFoundException(Status.NOT_FOUND, + Translator.toLocale(GepafinConstant.USER_ALREADY_EXIST_MSG)); + } + UserSamlResponse userSamlResponse = new UserSamlResponse(); + userSamlResponse.setCodiceFiscale(cf); + if (userAttributes.containsKey("nome") && userAttributes.get("nome") != null + && !userAttributes.get("nome").isEmpty()) { + userSamlResponse.setFirstName(userAttributes.get("nome").get(0).toString()); + } + if (userAttributes.containsKey("cognome") && userAttributes.get("cognome") != null + && !userAttributes.get("cognome").isEmpty()) { + userSamlResponse.setLastName(userAttributes.get("cognome").get(0).toString()); + } + userSamlResponse.setCodiceFiscale(cf); + return userSamlResponse; + } } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java index 9dc8378e..c109e6bb 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java @@ -2,22 +2,25 @@ package net.gepafin.tendermanagement.service.impl; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import net.gepafin.tendermanagement.config.jwt.TokenProvider; +import net.gepafin.tendermanagement.config.SamlSuccessHandler; import net.gepafin.tendermanagement.dao.UserDao; import net.gepafin.tendermanagement.entities.UserEntity; import net.gepafin.tendermanagement.model.request.LoginReq; import net.gepafin.tendermanagement.model.request.UpdateUserReq; import net.gepafin.tendermanagement.model.request.UserReq; +import net.gepafin.tendermanagement.enums.RoleStatusEnum; import net.gepafin.tendermanagement.enums.UserStatusEnum; import net.gepafin.tendermanagement.model.request.*; +import net.gepafin.tendermanagement.model.response.UserSamlResponse; import net.gepafin.tendermanagement.model.response.UserResponseBean; import net.gepafin.tendermanagement.model.util.JWTToken; import net.gepafin.tendermanagement.service.UserService; +import net.gepafin.tendermanagement.util.Validator; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.Map; @Service @@ -25,12 +28,21 @@ public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; + @Autowired - private TokenProvider tokenProvider; + private Validator validator; + + @Autowired + private SamlSuccessHandler samlSuccessHandler; @Transactional(rollbackFor = Exception.class) - public UserResponseBean createUser(UserReq userReq) { - return userDao.createUser(userReq); + public JWTToken createUser(HttpServletRequest request, String tempToken, UserReq userReq) { + if (tempToken == null) { + validator.validateRequest(request,RoleStatusEnum.ROLE_SUPER_ADMIN); + }else { + samlSuccessHandler.validateToken(tempToken, userReq.getCodiceFiscale()); + } + return userDao.createUser(request, tempToken, userReq); } @@ -89,8 +101,17 @@ public class UserServiceImpl implements UserService { @Override @Transactional(readOnly = true) public UserResponseBean getValidUser(HttpServletRequest request) { - Map userInfo= tokenProvider.getUserInfoAndUserIdFromToken(request); - UserEntity user=tokenProvider.validateUser(userInfo); + UserEntity user=validator.validateUser(request); return userDao.getUserById(user.getId()); } + + @Override + @Transactional(rollbackFor = Exception.class) + public JWTToken validateExistingUserToken(HttpServletRequest request, String token) { + return userDao.validateExistingUserToken(token); + } + @Override + public UserSamlResponse validateNewUserToken(HttpServletRequest request, String token) { + return userDao.validateNewUserToken(token); + } } \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/util/Utils.java b/src/main/java/net/gepafin/tendermanagement/util/Utils.java index 055fb8e8..9de26d9c 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/Utils.java +++ b/src/main/java/net/gepafin/tendermanagement/util/Utils.java @@ -15,6 +15,7 @@ import org.slf4j.LoggerFactory; import java.lang.reflect.Field; import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; +import java.security.SecureRandom; import java.util.Base64; import java.util.List; import java.util.Map; @@ -161,4 +162,32 @@ public class Utils { } } } + + public static String encodeData(String data) { + return Base64.getEncoder().encodeToString(data.getBytes(StandardCharsets.UTF_8)); + } + + public static String decodeData(String token) { + byte[] decodedBytes = Base64.getDecoder().decode(token); + return new String(decodedBytes, StandardCharsets.UTF_8); + } + + public static String generateSecureToken() { + SecureRandom secureRandom = new SecureRandom(); + byte[] tokenBytes = new byte[24]; + secureRandom.nextBytes(tokenBytes); + String token = Base64.getUrlEncoder().withoutPadding().encodeToString(tokenBytes); + log.debug("Generated secure token: {}", token); + return token; + } + + public static Map> convertStringIntoMap(String jsonString) { + try { + return mapper.readValue(jsonString, new TypeReference>>() { + }); + } catch (Exception e) { + log.error("Error converting object: " + e.getMessage(), e); + return null; + } + } } diff --git a/src/main/java/net/gepafin/tendermanagement/util/Validator.java b/src/main/java/net/gepafin/tendermanagement/util/Validator.java index a831c2dc..f4f53d0b 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/Validator.java +++ b/src/main/java/net/gepafin/tendermanagement/util/Validator.java @@ -1,11 +1,19 @@ package net.gepafin.tendermanagement.util; import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.config.jwt.TokenProvider; +import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.entities.UserEntity; +import net.gepafin.tendermanagement.enums.RoleStatusEnum; import net.gepafin.tendermanagement.service.UserService; +import net.gepafin.tendermanagement.web.rest.api.errors.Status; +import net.gepafin.tendermanagement.web.rest.api.errors.UnauthorizedAccessException; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; import java.util.Map; @@ -28,4 +36,24 @@ public class Validator { return userService.validateUser(Long.parseLong(userInfo.get("userId").toString())); } + public Boolean checkIsSuperAdmin(HttpServletRequest request) { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + + if (authentication != null && authentication.isAuthenticated()) { + // Check if the user has the ROLE_SUPER_ADMIN authority + for (GrantedAuthority authority : authentication.getAuthorities()) { + if (RoleStatusEnum.ROLE_SUPER_ADMIN.getValue().equals(authority.getAuthority())) { + return true; + } + } + } + return false; + } + + public void validateRequest(HttpServletRequest request,RoleStatusEnum role) { + if (RoleStatusEnum.ROLE_SUPER_ADMIN.equals(role) && Boolean.FALSE.equals(checkIsSuperAdmin(request))) { + throw new UnauthorizedAccessException(Status.UNAUTHORIZED, Translator.toLocale(GepafinConstant.INVALID_USER)); + } + } + } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/UserApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/UserApi.java index 8eaeca2d..18281f96 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/UserApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/UserApi.java @@ -10,6 +10,7 @@ import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; import net.gepafin.tendermanagement.enums.UserStatusEnum; import net.gepafin.tendermanagement.model.request.*; +import net.gepafin.tendermanagement.model.response.UserSamlResponse; import net.gepafin.tendermanagement.model.response.UserResponseBean; import net.gepafin.tendermanagement.model.util.JWTToken; import net.gepafin.tendermanagement.model.util.Response; @@ -37,10 +38,11 @@ public interface UserApi { @RequestMapping(value = "", produces = {"application/json"}, method = RequestMethod.POST) - @PreAuthorize("hasRole('ROLE_SUPER_ADMIN')") - default ResponseEntity> createUser( +// @PreAuthorize("hasRole('ROLE_SUPER_ADMIN')") + default ResponseEntity> createUser(HttpServletRequest request, + @Parameter(description = "temp spid Token", required = false) @RequestParam(value = "tempToken", required = false) String tempToken, @Parameter(description = "User request object", required = true) @Validated @RequestBody UserReq userReq) { - return new ResponseEntity>(HttpStatus.NOT_IMPLEMENTED); + return new ResponseEntity>(HttpStatus.NOT_IMPLEMENTED); } @Operation(summary = "Api to update user", @@ -174,6 +176,7 @@ public interface UserApi { @Parameter(description = "status", required = true)@RequestParam(value = "status", required = true) UserStatusEnum status) { return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); } + @Operation(summary = "Api to get valid user from token", responses = { @ApiResponse(responseCode = "200", description = "OK"), @@ -186,6 +189,38 @@ public interface UserApi { @GetMapping(value = "/me", produces = { "application/json" }) ResponseEntity> getValidUser(HttpServletRequest request); + + @Operation(summary = "Api to validate existing user from saml token", + responses = { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @GetMapping(value = "/sso/validate/existing-user/{token}", + produces = { "application/json" }) + ResponseEntity> validateExistingUserToken(HttpServletRequest request, + @Parameter(description = "The spid token", required = true) @PathVariable("token") String token); + + + @Operation(summary = "Api to validate new user from saml token", + responses = { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @GetMapping(value = "/sso/validate/new-user/{token}", + produces = { "application/json" }) + ResponseEntity> validateNewUserToken(HttpServletRequest request, + @Parameter(description = "The spid token", required = true) @PathVariable("token") String token); + + + } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/UserApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/UserApiController.java index d036a7f0..ccb255c1 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/UserApiController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/UserApiController.java @@ -7,6 +7,7 @@ import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.enums.UserStatusEnum; import net.gepafin.tendermanagement.model.request.*; +import net.gepafin.tendermanagement.model.response.UserSamlResponse; import net.gepafin.tendermanagement.model.response.UserResponseBean; import net.gepafin.tendermanagement.model.util.JWTToken; import net.gepafin.tendermanagement.model.util.Response; @@ -33,9 +34,9 @@ public class UserApiController implements UserApi { private UserService userService; @Override - public ResponseEntity> createUser(@RequestBody UserReq userReq) { + public ResponseEntity> createUser(HttpServletRequest request, String tempToken, @RequestBody UserReq userReq) { log.info("Create User with - Request Body: {}", userReq); - UserResponseBean createdUser = userService.createUser(userReq); + JWTToken createdUser = userService.createUser(request, tempToken, userReq); return ResponseEntity.status(HttpStatus.CREATED) .body(new Response<>(createdUser, Status.SUCCESS, Translator.toLocale(GepafinConstant.USER_CREATED_SUCCESS_MSG))); } @@ -124,4 +125,19 @@ public class UserApiController implements UserApi { .body(new Response<>(user, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_USER_SUCCESS_MSG))); } + + @Override + public ResponseEntity> validateExistingUserToken(HttpServletRequest request, String token) { + log.info("User login attempt via spid token"); + JWTToken data = userService.validateExistingUserToken(request, token); + return ResponseEntity.ok(new Response<>(data, Status.SUCCESS, Translator.toLocale(GepafinConstant.TOKEN_VALIDATE_SUCCESS_MGE))); + } + + @Override + public ResponseEntity> validateNewUserToken(HttpServletRequest request, String token) { + log.info("User validating spid token"); + UserSamlResponse data = userService.validateNewUserToken(request,token); + return ResponseEntity.ok(new Response<>(data, Status.SUCCESS, Translator.toLocale(GepafinConstant.TOKEN_VALIDATE_SUCCESS_MGE))); + } + } \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 1e41a2e9..1c16a251 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -42,4 +42,5 @@ spring.main.allow-circular-references=true isVatCheckGloballyDisabled = true vatCheckNewToken: 66026bd891a51044e90e08c4 +fe.base.url=http://gepafin-staging-fe.s3-website.eu-central-1.amazonaws.com diff --git a/src/main/resources/db/changelog/db.changelog-1.0.0.xml b/src/main/resources/db/changelog/db.changelog-1.0.0.xml index d7377f5c..212db4d3 100644 --- a/src/main/resources/db/changelog/db.changelog-1.0.0.xml +++ b/src/main/resources/db/changelog/db.changelog-1.0.0.xml @@ -712,28 +712,22 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + - + + + + + + + + + + diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index 981ed852..fcba1c30 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -8,6 +8,7 @@ delete_user_error_msg=An error occurred while deleting the user. get_user_success_msg=User retrieved successfully. get_user_error_msg=An error occurred while retrieving the user. user.not.active=User is not active. Please contact support. +user.already.exist.msg=User already exist for this codice fiscale. # Role-related messages role.created.success=Role created successfully. role.updated.success=Role updated successfully. @@ -184,3 +185,6 @@ valid.vat.number=The VAT number is not valid for field {0}. failed.retain.field=Failed to retain specific fields. application.is.incomplete = The application is incomplete. +token.validate.success=Token validated successfully. +invalid.request=Invalid Request. +codice.fiscale.exists=This codice fiscale is already associated with another user. diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index 5a7899df..aa815e8c 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -8,6 +8,7 @@ delete_user_error_msg=Si � verificato un errore durante l'eliminazione dell'ut get_user_success_msg=Utente recuperato con successo. get_user_error_msg=Si � verificato un errore durante il recupero dell'utente. user.not.active=Utente non attivo. Si prega di contattare il supporto. +user.already.exist.msg=L'utente esiste già per questo codice fiscale. # Role-related messages role.created.success=Ruolo creato con successo. role.updated.success=Ruolo aggiornato con successo. @@ -176,3 +177,6 @@ validation.marca.da.bollo=Il campo {0} deve essere una Marca Da Bollo valida con validation.piva=Il numero di partita IVA per {0} deve essere lungo fino a 11 cifre. valid.vat.number=Il numero di partita IVA non � valido per il campo {0}. failed.retain.field=Impossibile conservare campi specifici. +token.validate.success=Token convalidato con successo. +invalid.request=Richiesta non valida. +codice.fiscale.exists=Questo codice fiscale è già associato ad un altro utente. From d521dc464c3a612887c4f91acc444786ff97ee31 Mon Sep 17 00:00:00 2001 From: rajesh Date: Wed, 25 Sep 2024 20:29:57 +0530 Subject: [PATCH 34/58] added logger for saml --- .../tendermanagement/config/SamlSuccessHandler.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/config/SamlSuccessHandler.java b/src/main/java/net/gepafin/tendermanagement/config/SamlSuccessHandler.java index 1ef52f87..32d07a8f 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SamlSuccessHandler.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SamlSuccessHandler.java @@ -60,16 +60,19 @@ public class SamlSuccessHandler implements AuthenticationSuccessHandler { samlResponseLogEntity.setAuthenticationObject(userAttributesJson); samlResponseLogEntity.setToken(token); samlResponseLogRepository.save(samlResponseLogEntity); + + String redirectUrl = feBaseUrl; - // Successful login logic logger.info("SAML login successful for user: " + principal.getName()); String cf = userAttributes.get("CodiceFiscale").get(0).toString(); UserEntity userEntity = userRepository.findByCodiceFiscale(cf).orElse(null); if (userEntity == null) { - response.sendRedirect(feBaseUrl + "/registration?temp_token=" + token); + redirectUrl += "/registration?temp_token=" + token; } else { - response.sendRedirect(feBaseUrl + "/login?temp_token=" + token); + redirectUrl += "/login?temp_token=" + token; } + response.sendRedirect(redirectUrl); + logger.info("SAML redirect Url: " + redirectUrl); } catch (Exception e) { logger.error("Error processing SAML success handler", e); } From 9cc3ca14161206ee765befdb7f2f6b2f38abc956 Mon Sep 17 00:00:00 2001 From: rajesh Date: Wed, 25 Sep 2024 20:33:53 +0530 Subject: [PATCH 35/58] updated code --- .../net/gepafin/tendermanagement/config/SamlSuccessHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/gepafin/tendermanagement/config/SamlSuccessHandler.java b/src/main/java/net/gepafin/tendermanagement/config/SamlSuccessHandler.java index 32d07a8f..a8af08a7 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SamlSuccessHandler.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SamlSuccessHandler.java @@ -38,7 +38,7 @@ public class SamlSuccessHandler implements AuthenticationSuccessHandler { @Autowired private UserRepository userRepository; - @Value("fe.base.url") + @Value("${fe.base.url}") private String feBaseUrl; @Override From c89adce8508e077b40323b012aa94ffb9856f954 Mon Sep 17 00:00:00 2001 From: rajesh Date: Wed, 25 Sep 2024 20:43:27 +0530 Subject: [PATCH 36/58] updated code --- .../gepafin/tendermanagement/constants/GepafinConstant.java | 2 +- .../tendermanagement/web/rest/api/impl/UserApiController.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index 39e01825..3866e145 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -157,7 +157,7 @@ public class GepafinConstant { public static final String IS_PIVA="isPIVA"; public static final String FAILED_RETAIN_FIELD="failed.retain.field"; public static final String USER_ALREADY_EXIST_MSG = "user.already.exist.msg"; - public static final String TOKEN_VALIDATE_SUCCESS_MGE = "token.validate.success.mge"; + public static final String TOKEN_VALIDATE_SUCCESS_MSE = "token.validate.success"; public static final String INVALID_REQUEST = "invalid.request"; public static final String CODICE_FISCALE_EXISTS = "codice.fiscale.exists"; public static final String TOTAL_STEPS_NOT_BE_ZERO="total.steps.not.zero"; diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/UserApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/UserApiController.java index ccb255c1..ca13268a 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/UserApiController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/UserApiController.java @@ -130,14 +130,14 @@ public class UserApiController implements UserApi { public ResponseEntity> validateExistingUserToken(HttpServletRequest request, String token) { log.info("User login attempt via spid token"); JWTToken data = userService.validateExistingUserToken(request, token); - return ResponseEntity.ok(new Response<>(data, Status.SUCCESS, Translator.toLocale(GepafinConstant.TOKEN_VALIDATE_SUCCESS_MGE))); + return ResponseEntity.ok(new Response<>(data, Status.SUCCESS, Translator.toLocale(GepafinConstant.TOKEN_VALIDATE_SUCCESS_MSE))); } @Override public ResponseEntity> validateNewUserToken(HttpServletRequest request, String token) { log.info("User validating spid token"); UserSamlResponse data = userService.validateNewUserToken(request,token); - return ResponseEntity.ok(new Response<>(data, Status.SUCCESS, Translator.toLocale(GepafinConstant.TOKEN_VALIDATE_SUCCESS_MGE))); + return ResponseEntity.ok(new Response<>(data, Status.SUCCESS, Translator.toLocale(GepafinConstant.TOKEN_VALIDATE_SUCCESS_MSE))); } } \ No newline at end of file From 39b0ba994c35f9ae94aa54da8713e7d770f26860 Mon Sep 17 00:00:00 2001 From: nisha Date: Wed, 25 Sep 2024 21:41:50 +0530 Subject: [PATCH 37/58] Updated form field data --- src/main/resources/db/changelog/db.changelog-1.0.0.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/resources/db/changelog/db.changelog-1.0.0.xml b/src/main/resources/db/changelog/db.changelog-1.0.0.xml index d7377f5c..60292ab0 100644 --- a/src/main/resources/db/changelog/db.changelog-1.0.0.xml +++ b/src/main/resources/db/changelog/db.changelog-1.0.0.xml @@ -736,4 +736,10 @@ + + + + id = 13 + + From ff74b9afcaaef2e68db42fce22afd0ccac99b5c8 Mon Sep 17 00:00:00 2001 From: harish Date: Thu, 26 Sep 2024 12:29:33 +0530 Subject: [PATCH 38/58] Updated configuration --- src/main/resources/application-production.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/application-production.properties b/src/main/resources/application-production.properties index 51940c65..af9d5e38 100644 --- a/src/main/resources/application-production.properties +++ b/src/main/resources/application-production.properties @@ -6,6 +6,6 @@ spring.datasource.driver-class-name=org.postgresql.Driver # JPA Configuration spring.h2.console.enabled=true -base-url=http://79.137.88.15 +base-url=http://bandi.gepafin.it isVatCheckGloballyDisabled = false From ea30c41002441827bc8cb812759c056ebd2ed1d1 Mon Sep 17 00:00:00 2001 From: rajesh Date: Thu, 26 Sep 2024 13:25:57 +0530 Subject: [PATCH 39/58] added dob filed for user --- .../gepafin/tendermanagement/config/SamlFailureHandler.java | 2 +- src/main/java/net/gepafin/tendermanagement/dao/UserDao.java | 3 +++ .../net/gepafin/tendermanagement/entities/UserEntity.java | 3 +++ .../net/gepafin/tendermanagement/model/request/UserReq.java | 4 ++++ .../tendermanagement/model/response/LoginResponse.java | 4 ++++ .../tendermanagement/model/response/UserResponseBean.java | 4 ++++ .../tendermanagement/service/impl/AuthenticationService.java | 2 ++ src/main/resources/db/changelog/db.changelog-1.0.0.xml | 1 + 8 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/gepafin/tendermanagement/config/SamlFailureHandler.java b/src/main/java/net/gepafin/tendermanagement/config/SamlFailureHandler.java index 1e740869..81df79e3 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SamlFailureHandler.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SamlFailureHandler.java @@ -17,7 +17,7 @@ public class SamlFailureHandler implements AuthenticationFailureHandler { private final Logger logger = LoggerFactory.getLogger(SamlSuccessHandler.class); - @Value("fe.base.url") + @Value("${fe.base.url}") private String feBaseUrl; @Override diff --git a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java index 8dddbfea..b615f263 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java @@ -110,6 +110,7 @@ public class UserDao { userEntity.setPhoneNumber(userReq.getPhoneNumber()); userEntity.setRoleEntity(roleDao.validateRole(userReq.getRoleId())); userEntity.setCodiceFiscale(userReq.getCodiceFiscale()); + userEntity.setDateOfBirth(userReq.getDateOfBirth()); return userEntity; } @@ -130,6 +131,8 @@ public class UserDao { RoleResponseBean roleResponseBean = roleDao.convertRoleEntityToRoleResponse(userEntity.getRoleEntity()); userResponseBean.setRole(roleResponseBean); userResponseBean.setLastLogin(userEntity.getLastLogin()); + userResponseBean.setCodiceFiscale(userEntity.getCodiceFiscale()); + userResponseBean.setDateOfBirth(userEntity.getDateOfBirth()); return userResponseBean; } diff --git a/src/main/java/net/gepafin/tendermanagement/entities/UserEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/UserEntity.java index 0a0c9016..37b0ab57 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/UserEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/UserEntity.java @@ -61,4 +61,7 @@ public class UserEntity extends BaseEntity { @Column(name = "CODICE_FISCALE") private String codiceFiscale; + + @Column(name = "DATE_OF_BIRTH") + private LocalDateTime dateOfBirth; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/UserReq.java b/src/main/java/net/gepafin/tendermanagement/model/request/UserReq.java index e81bdaf3..508baabe 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/request/UserReq.java +++ b/src/main/java/net/gepafin/tendermanagement/model/request/UserReq.java @@ -1,5 +1,7 @@ package net.gepafin.tendermanagement.model.request; +import java.time.LocalDateTime; + import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; @@ -33,5 +35,7 @@ public class UserReq { private String country; private String codiceFiscale; + + private LocalDateTime dateOfBirth; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/LoginResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/LoginResponse.java index 64af6b1a..6317724e 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/LoginResponse.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/LoginResponse.java @@ -35,6 +35,10 @@ public class LoginResponse { private String status; private LocalDateTime lastLogin; + + private String codiceFiscale; + + private LocalDateTime dateOfBirth; private LocalDateTime createdDate; diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/UserResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/UserResponseBean.java index 5c1a8ef2..565e2561 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/UserResponseBean.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/UserResponseBean.java @@ -32,5 +32,9 @@ public class UserResponseBean extends BaseBean { private UserStatusEnum status; private LocalDateTime lastLogin; + + private String codiceFiscale; + + private LocalDateTime dateOfBirth; } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java b/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java index 1b61baa7..457a1e5d 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java @@ -104,6 +104,8 @@ public class AuthenticationService { loginResponse.setStatus(user.getStatus()); loginResponse.setCity(user.getCity()); loginResponse.setLastLogin(user.getLastLogin()); + loginResponse.setCodiceFiscale(user.getCodiceFiscale()); + loginResponse.setDateOfBirth(user.getDateOfBirth()); loginResponse.setCreatedDate(user.getCreatedDate()); loginResponse.setUpdatedDate(user.getUpdatedDate()); return loginResponse; diff --git a/src/main/resources/db/changelog/db.changelog-1.0.0.xml b/src/main/resources/db/changelog/db.changelog-1.0.0.xml index 212db4d3..cfde8228 100644 --- a/src/main/resources/db/changelog/db.changelog-1.0.0.xml +++ b/src/main/resources/db/changelog/db.changelog-1.0.0.xml @@ -726,6 +726,7 @@ + From 40e5ab9e910e4ffcc6ea4dda52c89f87ab44fcdb Mon Sep 17 00:00:00 2001 From: rajesh Date: Thu, 26 Sep 2024 17:31:44 +0530 Subject: [PATCH 40/58] updated code for create user api --- .../constants/GepafinConstant.java | 4 + .../gepafin/tendermanagement/dao/RoleDao.java | 5 ++ .../gepafin/tendermanagement/dao/UserDao.java | 90 ++++++++++++++----- .../model/request/UserReq.java | 8 +- .../repositories/RoleRepository.java | 2 + src/main/resources/message_en.properties | 3 + src/main/resources/message_it.properties | 3 + 7 files changed, 86 insertions(+), 29 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index 3866e145..d79edb37 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -163,4 +163,8 @@ public class GepafinConstant { public static final String TOTAL_STEPS_NOT_BE_ZERO="total.steps.not.zero"; public static final String COMPLETED_STEPS_NOT_VALID="completed.steps.not.valid"; public static final String FIELD_ID_NOT_FOUND="field.id.not.found"; + public static final String VALIDATE_EMAIL = "validate.email"; + public static final String ROLE_ID_MANDATORY = "role.id.mandatory"; + public static final String VALIDATE_PASSWORD = "validate.password"; + } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/RoleDao.java b/src/main/java/net/gepafin/tendermanagement/dao/RoleDao.java index ef80acbb..cb4f41fd 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/RoleDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/RoleDao.java @@ -4,6 +4,7 @@ import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.entities.RegionEntity; import net.gepafin.tendermanagement.entities.RoleEntity; +import net.gepafin.tendermanagement.enums.RoleStatusEnum; import net.gepafin.tendermanagement.model.request.RoleReq; import net.gepafin.tendermanagement.model.response.RegionResponseBean; import net.gepafin.tendermanagement.model.response.RoleResponseBean; @@ -119,4 +120,8 @@ public class RoleDao { log.info("Total roles found: {}", roles.size()); return roles; } + + public RoleEntity getRoleByType(RoleStatusEnum roleStatus) { + return roleRepository.findByRoleType(roleStatus.getValue()); + } } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java index b615f263..252c88f7 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java @@ -6,6 +6,7 @@ import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.entities.RoleEntity; import net.gepafin.tendermanagement.entities.UserEntity; +import net.gepafin.tendermanagement.enums.RoleStatusEnum; import net.gepafin.tendermanagement.enums.UserStatusEnum; import net.gepafin.tendermanagement.model.request.*; import net.gepafin.tendermanagement.model.response.RoleResponseBean; @@ -28,6 +29,8 @@ import org.springframework.stereotype.Repository; import static net.gepafin.tendermanagement.util.Utils.setIfUpdated; +import java.util.regex.Pattern; + @Repository public class UserDao { @@ -46,32 +49,57 @@ public class UserDao { private RoleDao roleDao; public JWTToken createUser(HttpServletRequest request, String tempToken, UserReq userReq) { - log.info("Creating user with email: {}", userReq.getEmail()); - if (userRepository.existsByEmailIgnoreCase(userReq.getEmail())) { - log.error("User creation failed: Email {} already exists", userReq.getEmail()); - throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.EMAIL_ALREADY_EXISTS)); - } - if (Boolean.FALSE.equals(StringUtils.isEmpty(userReq.getCodiceFiscale())) && userRepository.existsByCodiceFiscale(userReq.getCodiceFiscale())) { - log.error("User creation failed: CodiceFiscale {} already exists", userReq.getCodiceFiscale()); - throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.CODICE_FISCALE_EXISTS)); - } - if(tempToken == null && (StringUtils.isEmpty(userReq.getPassword()) || StringUtils.isEmpty(userReq.getConfPassword()))) { - throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.INVALID_REQUEST)); - } - if (tempToken == null && !userReq.getPassword().equals(userReq.getConfPassword())) { - log.error("User creation failed: Passwords do not match for email {}", userReq.getEmail()); - throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.PASSWORD_DOESNT_MATCH)); - } - if (tempToken == null && userReq.getPassword().length() < 8) { - log.error("User creation failed: Password length is less than 8 characters for email {}", userReq.getEmail()); - throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.PASSWORD_MIN_LEN)); - } + + if (Boolean.FALSE.equals(isValidEmail(userReq.getEmail()))) { + throw new CustomValidationException(Status.VALIDATION_ERROR, + Translator.toLocale(GepafinConstant.VALIDATE_EMAIL)); + } + log.info("Creating user with email: {}", userReq.getEmail()); + if (userRepository.existsByEmailIgnoreCase(userReq.getEmail())) { + log.error("User creation failed: Email {} already exists", userReq.getEmail()); + throw new CustomValidationException(Status.VALIDATION_ERROR, + Translator.toLocale(GepafinConstant.EMAIL_ALREADY_EXISTS)); + } + if (Boolean.FALSE.equals(StringUtils.isEmpty(userReq.getCodiceFiscale())) + && userRepository.existsByCodiceFiscale(userReq.getCodiceFiscale())) { + log.error("User creation failed: CodiceFiscale {} already exists", userReq.getCodiceFiscale()); + throw new CustomValidationException(Status.VALIDATION_ERROR, + Translator.toLocale(GepafinConstant.CODICE_FISCALE_EXISTS)); + } + if (tempToken == null && userReq.getRoleId() == null) { + throw new ResourceNotFoundException(Status.VALIDATION_ERROR, + Translator.toLocale(GepafinConstant.ROLE_ID_MANDATORY)); + } + if(tempToken != null) { + userReq.setRoleId(null); + } + validatePassword(userReq.getPassword(), userReq.getConfPassword(), tempToken); UserEntity userEntity = convertUserRequestToUserEntity(userReq); userEntity = userRepository.save(userEntity); log.info("User created with ID: {}", userEntity.getId()); return authService.getJWTTokenBean(userEntity, Boolean.TRUE); } + + private void validatePassword(String password, String confirmPassword, String tempToken) { + if (StringUtils.isEmpty(password) || StringUtils.isEmpty(confirmPassword)) { + if(tempToken == null) { + throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.VALIDATE_PASSWORD)); + }else if(Boolean.FALSE.equals(StringUtils.isEmpty(password) && StringUtils.isEmpty(confirmPassword))){ + throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.VALIDATE_PASSWORD)); + } + } + + if (password != null && !password.equals(confirmPassword)) { + log.error("User creation failed: Passwords do not match"); + throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.PASSWORD_DOESNT_MATCH)); + } + + if (password != null && password.length() < 8) { + log.error("User creation failed: Password length is less than 8 characters"); + throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.PASSWORD_MIN_LEN)); + } + } public UserResponseBean updateUser(Long userId, UpdateUserReq userReq) { log.info("Updating user with ID: {}", userId); @@ -108,13 +136,21 @@ public class UserDao { userEntity.setOrganization(userReq.getOrganization()); userEntity.setAddress(userReq.getAddress()); userEntity.setPhoneNumber(userReq.getPhoneNumber()); - userEntity.setRoleEntity(roleDao.validateRole(userReq.getRoleId())); + userEntity.setRoleEntity(getRoleEntity(userReq.getRoleId())); userEntity.setCodiceFiscale(userReq.getCodiceFiscale()); userEntity.setDateOfBirth(userReq.getDateOfBirth()); return userEntity; } - private UserResponseBean convertUserEntityToUserResponse(UserEntity userEntity) { + private RoleEntity getRoleEntity(Long roleId) { + if(roleId != null) { + return roleDao.validateRole(roleId); + } else { + return roleDao.getRoleByType(RoleStatusEnum.ROLE_BENEFICIARY); + } + } + + private UserResponseBean convertUserEntityToUserResponse(UserEntity userEntity) { UserResponseBean userResponseBean = new UserResponseBean(); userResponseBean.setId(userEntity.getId()); userResponseBean.setCreatedDate(userEntity.getCreatedDate()); @@ -225,6 +261,16 @@ public class UserDao { authService.logout(request, response); log.info("User successfully logged out."); } + + + public static Boolean isValidEmail(String email) { + String EMAIL_REGEX = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$"; + if (email == null || email.isEmpty()) { + return false; + } + Pattern pattern = Pattern.compile(EMAIL_REGEX); + return pattern.matcher(email).matches(); + } public UserResponseBean updateUserStatus(Long userId, UserStatusEnum statusReq) { log.info("Updating status for user with ID: {}", userId); diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/UserReq.java b/src/main/java/net/gepafin/tendermanagement/model/request/UserReq.java index 508baabe..c53d65aa 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/request/UserReq.java +++ b/src/main/java/net/gepafin/tendermanagement/model/request/UserReq.java @@ -1,17 +1,11 @@ package net.gepafin.tendermanagement.model.request; import java.time.LocalDateTime; - -import jakarta.validation.constraints.Email; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; import lombok.Data; @Data public class UserReq { - @NotBlank - @Email private String email; private String password; @@ -23,7 +17,7 @@ public class UserReq { private String lastName; private String phoneNumber; - @NotNull + private Long roleId; private String organization; diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/RoleRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/RoleRepository.java index e009e6a3..a48eade5 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/RoleRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/RoleRepository.java @@ -6,4 +6,6 @@ import org.springframework.stereotype.Repository; @Repository public interface RoleRepository extends JpaRepository { + + RoleEntity findByRoleType(String roleType); } diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index d58e019b..cf80165c 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -9,6 +9,8 @@ get_user_success_msg=User retrieved successfully. get_user_error_msg=An error occurred while retrieving the user. user.not.active=User is not active. Please contact support. user.already.exist.msg=User already exist for this codice fiscale. +validate.email=The email is mandatory and must be in the correct format. Please verify and try again. +validate.password=The password and confPassword are mandatory. Please verify and try again. # Role-related messages role.created.success=Role created successfully. role.updated.success=Role updated successfully. @@ -18,6 +20,7 @@ create.role.error=Error occurred while creating the role. update.role.error=Error occurred while updating the role. role.fetch.success=Role fetched successfully. delete.role.error=Error occurred while deleting the role. +role.id.mandatory=Role id is mandatory. # Region-related messages region.created.success=Region created successfully. diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index 87077449..9582a89d 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -9,6 +9,8 @@ get_user_success_msg=Utente recuperato con successo. get_user_error_msg=Si � verificato un errore durante il recupero dell'utente. user.not.active=Utente non attivo. Si prega di contattare il supporto. user.already.exist.msg=L'utente esiste gi� per questo codice fiscale. +validate.email=L'email è obbligatoria e deve essere nel formato corretto. Si prega di verificare e riprovare. +validate.password=La password e confPassword sono obbligatorie. Verifica e riprova. # Role-related messages role.created.success=Ruolo creato con successo. role.updated.success=Ruolo aggiornato con successo. @@ -18,6 +20,7 @@ create.role.error=Errore durante la creazione del ruolo. update.role.error=Errore durante l'aggiornamento del ruolo. role.fetch.success=Ruolo recuperato con successo. delete.role.error=Errore durante l'eliminazione del ruolo. +role.id.mandatory=L'ID del ruolo è obbligatorio. # Region-related messages region.created.success=Regione creata con successo. From d8d4396a04e52303a74cde0641b3bb6a4550d469 Mon Sep 17 00:00:00 2001 From: harish Date: Thu, 26 Sep 2024 20:01:19 +0530 Subject: [PATCH 41/58] Updated configuration --- src/main/resources/application-production.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/application-production.properties b/src/main/resources/application-production.properties index af9d5e38..4860dd7e 100644 --- a/src/main/resources/application-production.properties +++ b/src/main/resources/application-production.properties @@ -1,5 +1,5 @@ # DataSource Configuration -spring.datasource.url=jdbc:postgresql://79.137.88.14:21543/gepaDb +spring.datasource.url=jdbc:postgresql://bandidb.gepafin.it:21543/gepaDb spring.datasource.username=usergepa spring.datasource.password=nRHMi7esdgHJiIm3L5ctrSJ0 spring.datasource.driver-class-name=org.postgresql.Driver From fb75408152087d7d3b9647c4c8f2994ce06f7071 Mon Sep 17 00:00:00 2001 From: rajeshkhore <36757840+rajeshkhore@users.noreply.github.com> Date: Fri, 27 Sep 2024 11:59:32 +0530 Subject: [PATCH 42/58] Update base url in application production properties --- src/main/resources/application-production.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/application-production.properties b/src/main/resources/application-production.properties index 4860dd7e..be371126 100644 --- a/src/main/resources/application-production.properties +++ b/src/main/resources/application-production.properties @@ -6,6 +6,6 @@ spring.datasource.driver-class-name=org.postgresql.Driver # JPA Configuration spring.h2.console.enabled=true -base-url=http://bandi.gepafin.it +base-url=http://bandi-api.gepafin.it isVatCheckGloballyDisabled = false From ee809593290ac6c507fa899ed2a318ee2b7d1103 Mon Sep 17 00:00:00 2001 From: rajesh Date: Fri, 27 Sep 2024 16:44:39 +0530 Subject: [PATCH 43/58] Created beneficiary and associated with user --- .../tendermanagement/config/SamlConfig.java | 4 +- .../config/SamlSuccessHandler.java | 2 +- .../gepafin/tendermanagement/dao/UserDao.java | 143 +++++++++++------- .../entities/BeneficiaryEntity.java | 47 ++++++ .../tendermanagement/entities/UserEntity.java | 7 +- .../repositories/BeneficiaryRepository.java | 11 ++ .../repositories/UserRepository.java | 6 +- .../service/impl/AuthenticationService.java | 46 +++--- .../tendermanagement/util/Validator.java | 2 +- .../db/changelog/db.changelog-1.0.0.xml | 32 ++++ 10 files changed, 223 insertions(+), 77 deletions(-) create mode 100644 src/main/java/net/gepafin/tendermanagement/entities/BeneficiaryEntity.java create mode 100644 src/main/java/net/gepafin/tendermanagement/repositories/BeneficiaryRepository.java diff --git a/src/main/java/net/gepafin/tendermanagement/config/SamlConfig.java b/src/main/java/net/gepafin/tendermanagement/config/SamlConfig.java index 02a0ae27..67fd71e0 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SamlConfig.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SamlConfig.java @@ -133,8 +133,8 @@ public Saml2AuthenticationRequestResolver authenticationRequestResolver(RelyingP authnRequest.setRequestedAuthnContext(buildRequestedAuthnContext()); // Log the SAML AuthnRequest after setting context - String samlRequest = SamlRequestLogger.convertSAMLObjectToString(authnRequest); - logger.info("SAML AuthnRequest after setting context: " + samlRequest); +// String samlRequest = SamlRequestLogger.convertSAMLObjectToString(authnRequest); + logger.info("SAML Authentication Request."); }); return authenticationRequestResolver; diff --git a/src/main/java/net/gepafin/tendermanagement/config/SamlSuccessHandler.java b/src/main/java/net/gepafin/tendermanagement/config/SamlSuccessHandler.java index a8af08a7..37aec12f 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SamlSuccessHandler.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SamlSuccessHandler.java @@ -65,7 +65,7 @@ public class SamlSuccessHandler implements AuthenticationSuccessHandler { logger.info("SAML login successful for user: " + principal.getName()); String cf = userAttributes.get("CodiceFiscale").get(0).toString(); - UserEntity userEntity = userRepository.findByCodiceFiscale(cf).orElse(null); + UserEntity userEntity = userRepository.findByBeneficiaryCodiceFiscale(cf).orElse(null); if (userEntity == null) { redirectUrl += "/registration?temp_token=" + token; } else { diff --git a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java index 252c88f7..aa6e5cfc 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java @@ -4,6 +4,7 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.entities.BeneficiaryEntity; import net.gepafin.tendermanagement.entities.RoleEntity; import net.gepafin.tendermanagement.entities.UserEntity; import net.gepafin.tendermanagement.enums.RoleStatusEnum; @@ -13,6 +14,7 @@ import net.gepafin.tendermanagement.model.response.RoleResponseBean; import net.gepafin.tendermanagement.model.response.UserSamlResponse; import net.gepafin.tendermanagement.model.response.UserResponseBean; import net.gepafin.tendermanagement.model.util.JWTToken; +import net.gepafin.tendermanagement.repositories.BeneficiaryRepository; import net.gepafin.tendermanagement.repositories.UserRepository; import net.gepafin.tendermanagement.service.impl.AuthenticationService; import net.gepafin.tendermanagement.util.Utils; @@ -47,9 +49,41 @@ public class UserDao { @Autowired private RoleDao roleDao; + + @Autowired + private BeneficiaryRepository beneficiaryRepository; + public JWTToken createUser(HttpServletRequest request, String tempToken, UserReq userReq) { - + validateUserRequest(tempToken, userReq); + validatePassword(userReq.getPassword(), userReq.getConfPassword(), tempToken); + + RoleEntity roleEntity = getRoleEntity(userReq.getRoleId()); + BeneficiaryEntity beneficiary = createBeneficiary(roleEntity, userReq); + UserEntity userEntity = convertUserRequestToUserEntity(beneficiary, roleEntity, userReq); + log.info("User created with ID: {}", userEntity.getId()); + return authService.getJWTTokenBean(userEntity, Boolean.TRUE); + } + + private BeneficiaryEntity createBeneficiary(RoleEntity roleEntity, UserReq userReq) { + BeneficiaryEntity beneficiaryEntity = null; + if (RoleStatusEnum.ROLE_BENEFICIARY.getValue().equals(roleEntity.getRoleType())) { + beneficiaryEntity = new BeneficiaryEntity(); + beneficiaryEntity.setAddress(userReq.getAddress()); + beneficiaryEntity.setCity(userReq.getCity()); + beneficiaryEntity.setCodiceFiscale(userReq.getCodiceFiscale()); + beneficiaryEntity.setCountry(userReq.getCountry()); + beneficiaryEntity.setDateOfBirth(userReq.getDateOfBirth()); + beneficiaryEntity.setEmail(userReq.getEmail()); + beneficiaryEntity.setFirstName(userReq.getFirstName()); + beneficiaryEntity.setLastName(userReq.getLastName()); + beneficiaryEntity.setOrganization(userReq.getOrganization()); + beneficiaryEntity.setPhoneNumber(userReq.getPhoneNumber()); + } + return beneficiaryRepository.save(beneficiaryEntity); + } + + private void validateUserRequest(String tempToken, UserReq userReq) { if (Boolean.FALSE.equals(isValidEmail(userReq.getEmail()))) { throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.VALIDATE_EMAIL)); @@ -61,27 +95,21 @@ public class UserDao { Translator.toLocale(GepafinConstant.EMAIL_ALREADY_EXISTS)); } if (Boolean.FALSE.equals(StringUtils.isEmpty(userReq.getCodiceFiscale())) - && userRepository.existsByCodiceFiscale(userReq.getCodiceFiscale())) { + && userRepository.existsByBeneficiaryCodiceFiscale(userReq.getCodiceFiscale())) { log.error("User creation failed: CodiceFiscale {} already exists", userReq.getCodiceFiscale()); throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.CODICE_FISCALE_EXISTS)); } if (tempToken == null && userReq.getRoleId() == null) { - throw new ResourceNotFoundException(Status.VALIDATION_ERROR, - Translator.toLocale(GepafinConstant.ROLE_ID_MANDATORY)); + throw new ResourceNotFoundException(Status.VALIDATION_ERROR, + Translator.toLocale(GepafinConstant.ROLE_ID_MANDATORY)); } - if(tempToken != null) { - userReq.setRoleId(null); + if (tempToken != null) { + userReq.setRoleId(null); } - validatePassword(userReq.getPassword(), userReq.getConfPassword(), tempToken); - - UserEntity userEntity = convertUserRequestToUserEntity(userReq); - userEntity = userRepository.save(userEntity); - log.info("User created with ID: {}", userEntity.getId()); - return authService.getJWTTokenBean(userEntity, Boolean.TRUE); - } - - private void validatePassword(String password, String confirmPassword, String tempToken) { + } + + private void validatePassword(String password, String confirmPassword, String tempToken) { if (StringUtils.isEmpty(password) || StringUtils.isEmpty(confirmPassword)) { if(tempToken == null) { throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.VALIDATE_PASSWORD)); @@ -124,22 +152,24 @@ public class UserDao { return convertUserEntityToUserResponse(userEntity); } - private UserEntity convertUserRequestToUserEntity(UserReq userReq) { + private UserEntity convertUserRequestToUserEntity(BeneficiaryEntity beneficiary, RoleEntity roleEntity, UserReq userReq) { UserEntity userEntity = new UserEntity(); if(Boolean.FALSE.equals(StringUtils.isEmpty(userReq.getPassword()))) { userEntity.setPassword(passwordEncoder.encode(userReq.getPassword())); } + userEntity.setRoleEntity(roleEntity); userEntity.setEmail(userReq.getEmail()); - userEntity.setFirstName(userReq.getFirstName()); userEntity.setStatus(UserStatusEnum.ACTIVE.getValue()); - userEntity.setLastName(userReq.getLastName()); - userEntity.setOrganization(userReq.getOrganization()); - userEntity.setAddress(userReq.getAddress()); - userEntity.setPhoneNumber(userReq.getPhoneNumber()); - userEntity.setRoleEntity(getRoleEntity(userReq.getRoleId())); - userEntity.setCodiceFiscale(userReq.getCodiceFiscale()); - userEntity.setDateOfBirth(userReq.getDateOfBirth()); - return userEntity; + userEntity.setBeneficiary(beneficiary); + if (Boolean.FALSE.equals(RoleStatusEnum.ROLE_BENEFICIARY.getValue().equals(roleEntity.getRoleType()))) { + userEntity.setFirstName(userReq.getFirstName()); + userEntity.setLastName(userReq.getLastName()); + userEntity.setOrganization(userReq.getOrganization()); + userEntity.setAddress(userReq.getAddress()); + userEntity.setPhoneNumber(userReq.getPhoneNumber()); + userEntity.setDateOfBirth(userReq.getDateOfBirth()); + } + return userRepository.save(userEntity); } private RoleEntity getRoleEntity(Long roleId) { @@ -151,37 +181,48 @@ public class UserDao { } private UserResponseBean convertUserEntityToUserResponse(UserEntity userEntity) { - UserResponseBean userResponseBean = new UserResponseBean(); - userResponseBean.setId(userEntity.getId()); - userResponseBean.setCreatedDate(userEntity.getCreatedDate()); - userResponseBean.setUpdatedDate(userEntity.getUpdatedDate()); - userResponseBean.setEmail(userEntity.getEmail()); - userResponseBean.setFirstName(userEntity.getFirstName()); - userResponseBean.setLastName(userEntity.getLastName()); - userResponseBean.setPhoneNumber(userEntity.getPhoneNumber()); - userResponseBean.setOrganization(userEntity.getOrganization()); - userResponseBean.setAddress(userEntity.getAddress()); - userResponseBean.setCity(userEntity.getCity()); - userResponseBean.setCountry(userEntity.getCountry()); - userResponseBean.setStatus(UserStatusEnum.valueOf(userEntity.getStatus())); - RoleResponseBean roleResponseBean = roleDao.convertRoleEntityToRoleResponse(userEntity.getRoleEntity()); - userResponseBean.setRole(roleResponseBean); - userResponseBean.setLastLogin(userEntity.getLastLogin()); - userResponseBean.setCodiceFiscale(userEntity.getCodiceFiscale()); - userResponseBean.setDateOfBirth(userEntity.getDateOfBirth()); - return userResponseBean; - } + UserResponseBean userResponseBean = new UserResponseBean(); + userResponseBean.setId(userEntity.getId()); + userResponseBean.setCreatedDate(userEntity.getCreatedDate()); + userResponseBean.setUpdatedDate(userEntity.getUpdatedDate()); + userResponseBean.setEmail(userEntity.getEmail()); + userResponseBean.setStatus(UserStatusEnum.valueOf(userEntity.getStatus())); + RoleResponseBean roleResponseBean = roleDao.convertRoleEntityToRoleResponse(userEntity.getRoleEntity()); + userResponseBean.setRole(roleResponseBean); + userResponseBean.setLastLogin(userEntity.getLastLogin()); + if (userEntity.getBeneficiary() == null) { + userResponseBean.setFirstName(userEntity.getFirstName()); + userResponseBean.setLastName(userEntity.getLastName()); + userResponseBean.setPhoneNumber(userEntity.getPhoneNumber()); + userResponseBean.setOrganization(userEntity.getOrganization()); + userResponseBean.setAddress(userEntity.getAddress()); + userResponseBean.setCity(userEntity.getCity()); + userResponseBean.setCountry(userEntity.getCountry()); + userResponseBean.setDateOfBirth(userEntity.getDateOfBirth()); + } else { + userResponseBean.setFirstName(userEntity.getBeneficiary().getFirstName()); + userResponseBean.setLastName(userEntity.getBeneficiary().getLastName()); + userResponseBean.setPhoneNumber(userEntity.getBeneficiary().getPhoneNumber()); + userResponseBean.setOrganization(userEntity.getBeneficiary().getOrganization()); + userResponseBean.setAddress(userEntity.getBeneficiary().getAddress()); + userResponseBean.setCity(userEntity.getBeneficiary().getCity()); + userResponseBean.setCountry(userEntity.getBeneficiary().getCountry()); + userResponseBean.setCodiceFiscale(userEntity.getBeneficiary().getCodiceFiscale()); + userResponseBean.setDateOfBirth(userEntity.getBeneficiary().getDateOfBirth()); + } + return userResponseBean; + } - public UserResponseBean getUserById(Long id) { - log.info("Fetching user with ID: {}", id); - UserEntity userEntity=validateUser(id); + public UserResponseBean getUserById(Long id) { + log.info("Fetching user with ID: {}", id); + UserEntity userEntity = validateUser(id); // if (!UserStatusEnum.ACTIVE.getValue().equals(userEntity.getStatus())) { // log.info("User with ID: {} is not active", id); // throw new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG)); // } - log.info("User found: {}", userEntity); - return convertUserEntityToUserResponse(userEntity); - } + log.info("User found: {}", userEntity); + return convertUserEntityToUserResponse(userEntity); + } public void deleteUser(Long id) { log.info("Deleting user with ID: {}", id); diff --git a/src/main/java/net/gepafin/tendermanagement/entities/BeneficiaryEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/BeneficiaryEntity.java new file mode 100644 index 00000000..c0f31927 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/entities/BeneficiaryEntity.java @@ -0,0 +1,47 @@ +package net.gepafin.tendermanagement.entities; + +import java.time.LocalDateTime; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; +import jakarta.validation.constraints.Email; +import lombok.Data; + +@Entity +@Table(name = "beneficiary") +@Data +public class BeneficiaryEntity extends BaseEntity { + + @Email + @Column(name = "EMAIL") + private String email; + + @Column(name = "FIRST_NAME") + private String firstName; + + @Column(name = "LAST_NAME") + private String lastName; + + @Column(name = "PHONE_NUMBER") + private String phoneNumber; + + @Column(name = "ORGANIZATION") + private String organization; + + @Column(name = "ADDRESS") + private String address; + + @Column(name = "CITY") + private String city; + + @Column(name = "COUNTRY") + private String country; + + @Column(name = "CODICE_FISCALE") + private String codiceFiscale; + + @Column(name = "DATE_OF_BIRTH") + private LocalDateTime dateOfBirth; + +} diff --git a/src/main/java/net/gepafin/tendermanagement/entities/UserEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/UserEntity.java index 37b0ab57..f8d34ea2 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/UserEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/UserEntity.java @@ -59,9 +59,10 @@ public class UserEntity extends BaseEntity { @Column(name = "RESET_PASSWORD_TOKEN", length = 255, nullable = true) private String resetPasswordToken; - @Column(name = "CODICE_FISCALE") - private String codiceFiscale; - @Column(name = "DATE_OF_BIRTH") private LocalDateTime dateOfBirth; + + @OneToOne + @JoinColumn(name = "BENEFICIARY_ID") + private BeneficiaryEntity beneficiary; } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/BeneficiaryRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/BeneficiaryRepository.java new file mode 100644 index 00000000..ecb6ed7d --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/repositories/BeneficiaryRepository.java @@ -0,0 +1,11 @@ +package net.gepafin.tendermanagement.repositories; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import net.gepafin.tendermanagement.entities.BeneficiaryEntity; + +@Repository +public interface BeneficiaryRepository extends JpaRepository { + +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java index 68289e6d..829cd7ef 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java @@ -2,9 +2,11 @@ package net.gepafin.tendermanagement.repositories; import net.gepafin.tendermanagement.entities.UserEntity; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; import java.util.Optional; +@Repository public interface UserRepository extends JpaRepository { Optional findByEmailIgnoreCase(String email); @@ -13,7 +15,7 @@ public interface UserRepository extends JpaRepository { UserEntity findByEmail(String email); - Optional findByCodiceFiscale(String cf); + Optional findByBeneficiaryCodiceFiscale(String codiceFiscale); - boolean existsByCodiceFiscale(String codiceFiscale); + boolean existsByBeneficiaryCodiceFiscale(String codiceFiscale); } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java b/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java index 457a1e5d..96c0ce05 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java @@ -91,23 +91,35 @@ public class AuthenticationService { } private static LoginResponse getLoginResponse(UserEntity user, RoleResponseBean roleResponseBean) { - LoginResponse loginResponse = new LoginResponse(); - loginResponse.setId(user.getId()); - loginResponse.setEmail(user.getEmail()); - loginResponse.setFirstName(user.getFirstName()); - loginResponse.setLastName(user.getLastName()); - loginResponse.setRole(roleResponseBean); - loginResponse.setPhoneNumber(user.getPhoneNumber()); - loginResponse.setAddress(user.getAddress()); - loginResponse.setOrganization(user.getOrganization()); - loginResponse.setCountry(user.getCountry()); - loginResponse.setStatus(user.getStatus()); - loginResponse.setCity(user.getCity()); - loginResponse.setLastLogin(user.getLastLogin()); - loginResponse.setCodiceFiscale(user.getCodiceFiscale()); - loginResponse.setDateOfBirth(user.getDateOfBirth()); + LoginResponse loginResponse = new LoginResponse(); + loginResponse.setEmail(user.getEmail()); + loginResponse.setId(user.getId()); + loginResponse.setRole(roleResponseBean); + loginResponse.setStatus(user.getStatus()); + loginResponse.setLastLogin(user.getLastLogin()); loginResponse.setCreatedDate(user.getCreatedDate()); loginResponse.setUpdatedDate(user.getUpdatedDate()); + if (user.getBeneficiary() == null) { + loginResponse.setFirstName(user.getFirstName()); + loginResponse.setLastName(user.getLastName()); + loginResponse.setPhoneNumber(user.getPhoneNumber()); + loginResponse.setAddress(user.getAddress()); + loginResponse.setOrganization(user.getOrganization()); + loginResponse.setCountry(user.getCountry()); + loginResponse.setCity(user.getCity()); + loginResponse.setDateOfBirth(user.getDateOfBirth()); + }else { + loginResponse.setFirstName(user.getBeneficiary().getFirstName()); + loginResponse.setLastName(user.getBeneficiary().getLastName()); + loginResponse.setPhoneNumber(user.getBeneficiary().getPhoneNumber()); + loginResponse.setAddress(user.getBeneficiary().getAddress()); + loginResponse.setOrganization(user.getBeneficiary().getOrganization()); + loginResponse.setCountry(user.getBeneficiary().getCountry()); + loginResponse.setCity(user.getBeneficiary().getCity()); + loginResponse.setCodiceFiscale(user.getBeneficiary().getCodiceFiscale()); + loginResponse.setDateOfBirth(user.getBeneficiary().getDateOfBirth()); + } + return loginResponse; } public void logout(HttpServletRequest request, HttpServletResponse response) { @@ -131,7 +143,7 @@ public class AuthenticationService { Map> userAttributes = Utils .convertStringIntoMap(samlResponseLogEntity.getAuthenticationObject()); String cf = userAttributes.get("CodiceFiscale").get(0).toString(); - UserEntity userEntity = userRepository.findByCodiceFiscale(cf) + UserEntity userEntity = userRepository.findByBeneficiaryCodiceFiscale(cf) .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG))); samlResponseLogRepository.delete(samlResponseLogEntity); @@ -150,7 +162,7 @@ public class AuthenticationService { Map> userAttributes = Utils .convertStringIntoMap(samlResponseLogEntity.getAuthenticationObject()); String cf = userAttributes.get("CodiceFiscale").get(0).toString(); - if (userRepository.findByCodiceFiscale(cf).isPresent()) { + if (userRepository.existsByBeneficiaryCodiceFiscale(cf)) { throw new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.USER_ALREADY_EXIST_MSG)); } diff --git a/src/main/java/net/gepafin/tendermanagement/util/Validator.java b/src/main/java/net/gepafin/tendermanagement/util/Validator.java index f4f53d0b..37c5c29f 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/Validator.java +++ b/src/main/java/net/gepafin/tendermanagement/util/Validator.java @@ -52,7 +52,7 @@ public class Validator { public void validateRequest(HttpServletRequest request,RoleStatusEnum role) { if (RoleStatusEnum.ROLE_SUPER_ADMIN.equals(role) && Boolean.FALSE.equals(checkIsSuperAdmin(request))) { - throw new UnauthorizedAccessException(Status.UNAUTHORIZED, Translator.toLocale(GepafinConstant.INVALID_USER)); + throw new UnauthorizedAccessException(Status.UNAUTHORIZED, Translator.toLocale(GepafinConstant.INVALID_REQUEST)); } } diff --git a/src/main/resources/db/changelog/db.changelog-1.0.0.xml b/src/main/resources/db/changelog/db.changelog-1.0.0.xml index e8d546cd..7f349fd8 100644 --- a/src/main/resources/db/changelog/db.changelog-1.0.0.xml +++ b/src/main/resources/db/changelog/db.changelog-1.0.0.xml @@ -737,5 +737,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From e5e2894b3d7886427cec383a881baddd4f8f0777 Mon Sep 17 00:00:00 2001 From: nisha Date: Sat, 28 Sep 2024 08:03:01 +0530 Subject: [PATCH 44/58] Implemnted new flow for application form data --- .../tendermanagement/dao/ApplicationDao.java | 79 +++++++++++++++---- .../tendermanagement/dao/FlowFormDao.java | 40 +++++++--- .../gepafin/tendermanagement/dao/FormDao.java | 47 +++++++++-- .../response/NextOrPreviousFormResponse.java | 3 + .../tendermanagement/util/FieldValidator.java | 23 +++--- 5 files changed, 151 insertions(+), 41 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java index aae686d7..c7ad96c5 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java @@ -10,10 +10,7 @@ import net.gepafin.tendermanagement.model.request.ApplicationFormFieldRequestBea import net.gepafin.tendermanagement.model.request.ApplicationRequest; import net.gepafin.tendermanagement.model.request.ApplicationRequestBean; import net.gepafin.tendermanagement.model.response.*; -import net.gepafin.tendermanagement.repositories.ApplicationFormFieldRepository; -import net.gepafin.tendermanagement.repositories.ApplicationFormRepository; -import net.gepafin.tendermanagement.repositories.ApplicationRepository; -import net.gepafin.tendermanagement.repositories.FlowEdgesRepository; +import net.gepafin.tendermanagement.repositories.*; import net.gepafin.tendermanagement.service.CallService; import net.gepafin.tendermanagement.service.DocumentService; import net.gepafin.tendermanagement.service.FormService; @@ -66,6 +63,10 @@ public class ApplicationDao { @Autowired private FlowEdgesRepository flowEdgesRepository; + @Autowired + private FlowDataRepository flowDataRepository; + + public ApplicationResponseBean createApplication(ApplicationRequestBean applicationRequestBean, UserEntity userEntity, Long formId,Long applicationId) { FormEntity formEntity = formService.validateForm(formId); CallEntity call = callService.validatePublishedCall(formEntity.getCall().getId()); @@ -85,12 +86,6 @@ public class ApplicationDao { return applicationFormEntity1; } - public void validateFormId(FormEntity formEntity, CallEntity callEntity) { - if (Boolean.FALSE.equals(formEntity.getId().equals(callEntity.getInitialForm()))) { - throw new CustomValidationException(Status.BAD_REQUEST,Translator.toLocale(GepafinConstant.FORM_ID_DOES_NOT_MACTHES)); - } - } - public ApplicationFormEntity createApplicationFormEntity(ApplicationEntity application, FormEntity formEntity) { ApplicationFormEntity applicationFormEntity = new ApplicationFormEntity(); applicationFormEntity.setApplication(application); @@ -278,6 +273,9 @@ public class ApplicationDao { for (ApplicationFormFieldEntity applicationFormFieldEntity1 : applicationFormFieldEntities) { if (applicationFormFieldEntity1.getFieldId().equals(applicationFormFieldRequestBean.getFieldId())) { applicationFormFieldEntity = applicationFormFieldEntity1; + if(applicationFormEntity.getForm().getId().equals(applicationFormEntity.getApplication().getCall().getInitialForm())){ + validateRequiredFields(applicationFormEntity.getForm(),applicationFormEntity.getApplication(), applicationFormFieldRequestBean.getFieldId()); + } break; } else { applicationFormFieldEntity = new ApplicationFormFieldEntity(); @@ -286,7 +284,9 @@ public class ApplicationDao { } } Utils.setIfUpdated(applicationFormFieldEntity::getFieldId, applicationFormFieldEntity::setFieldId, applicationFormFieldRequestBean.getFieldId()); + if(applicationFormFieldRequestBean.getFieldValue() ==null || Boolean.FALSE.equals(applicationFormFieldRequestBean.getFieldValue().isEmpty())) { applicationFormFieldEntity.setFieldValue(applicationFormFieldRequestBean.getFieldValue()); + } return applicationFormFieldRepository.save(applicationFormFieldEntity); } @@ -464,14 +464,20 @@ public class ApplicationDao { if (status.equals(ApplicationStatusTypeEnum.SUBMIT)) { CallEntity callEntity = applicationEntity.getCall(); - Long initialFormId = callEntity.getInitialForm(); - Long finalFormId = callEntity.getFinalForm(); -// if (initialFormId == null || finalFormId == null) { +// Long initialFormId = callEntity.getInitialForm(); +// Long finalFormId = callEntity.getFinalForm(); +//// if (initialFormId == null || finalFormId == null) { +//// throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPLICATION_IS_INCOMPLETE_MSG)); +//// } +// ApplicationFormEntity initialApplicationForm = applicationFormRepository.findByApplicationIdAndFormId(applicationEntity.getId(), initialFormId); +// ApplicationFormEntity finalApplicationForm = applicationFormRepository.findByApplicationIdAndFormId(applicationEntity.getId(), finalFormId); +// if (initialApplicationForm == null || finalApplicationForm == null) { // throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPLICATION_IS_INCOMPLETE_MSG)); // } - ApplicationFormEntity initialApplicationForm = applicationFormRepository.findByApplicationIdAndFormId(applicationEntity.getId(), initialFormId); - ApplicationFormEntity finalApplicationForm = applicationFormRepository.findByApplicationIdAndFormId(applicationEntity.getId(), finalFormId); - if (initialApplicationForm == null || finalApplicationForm == null) { + List flowEdgesList = flowEdgesRepository.findByCallId(applicationEntity.getCall().getId()); + Long totalSteps=flowFormDao.calculateTotalSteps(flowEdgesList); + Integer completedSteps=flowFormDao.getCompletedSteps(applicationEntity); + if (totalSteps.intValue() != completedSteps) { throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPLICATION_IS_INCOMPLETE_MSG)); } applicationEntity.setStatus(ApplicationStatusTypeEnum.SUBMIT.getValue()); @@ -514,4 +520,45 @@ public class ApplicationDao { validator.validate(); } + public void validateRequiredFields(FormEntity formEntity, ApplicationEntity applicationEntity, String fieldId) { + FlowDataEntity flowDataEntity = flowDataRepository.findByFormIdAndCallId( + formEntity.getId(), applicationEntity.getCall().getId()); + + if (flowDataEntity == null) { + return; + } + + ApplicationFormFieldEntity applicationFormFieldEntity = applicationFormFieldRepository + .findByFieldIdAndApplicationFormFormIdAndApplicationFormApplicationId( + flowDataEntity.getChoosenField(), formEntity.getId(), applicationEntity.getId()) + .orElse(null); + + if (applicationFormFieldEntity == null || !fieldId.equals(applicationFormFieldEntity.getFieldId())) { + return; + } + List nextFormIds = flowEdgesRepository.findBySourceIdAndCallId( + formEntity.getId(), applicationEntity.getCall().getId()) + .stream() + .map(FlowEdgesEntity::getTargetId) + .collect(Collectors.toList()); + + Optional nextFormIdOptional = flowDataRepository.findByChoosenValueAndFormIdIn( + applicationFormFieldEntity.getFieldValue(), nextFormIds) + .map(FlowDataEntity::getFormId); + + if (nextFormIdOptional.isPresent()) { + Long nextFormId = nextFormIdOptional.get(); + + FormEntity nextForm = formService.validateForm(nextFormId); + ApplicationFormEntity nextApplicationFormEntity = applicationFormRepository.findByApplicationIdAndFormId( + applicationEntity.getId(), nextForm.getId()); + + if (nextApplicationFormEntity != null) { + List nextApplicationFormFieldEntities = applicationFormFieldRepository.findByApplicationFormId(nextApplicationFormEntity.getId()); + applicationFormFieldRepository.deleteAll(nextApplicationFormFieldEntities); + applicationFormRepository.delete(nextApplicationFormEntity); + } + } + } + } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java b/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java index 63287e0d..57f3c756 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java @@ -1,11 +1,9 @@ package net.gepafin.tendermanagement.dao; -import java.util.Comparator; -import java.util.List; -import java.util.Optional; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; +import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum; import net.gepafin.tendermanagement.repositories.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -46,7 +44,9 @@ public class FlowFormDao { @Autowired private FormService formService; @Autowired - private FormRepository formRepository; + private FormDao formDao; + + // Long getNextForm(FormEntity currentFormEntity, ApplicationEntity applicationEntity) { // // vlaidation if next form findout and cuuent from is not fill the give error @@ -274,16 +274,24 @@ public class FlowFormDao { } } NextOrPreviousFormResponse nextOrPreviousFormResponse = null; - if (calculatedFormId != null) { - nextOrPreviousFormResponse = setNextOrPreviousResponse(calculatedFormId, applicationEntity); + if (calculatedFormId == null && formId == null) { + FormEntity form=formService.validateForm(applicationEntity.getCall().getInitialForm()); + calculatedFormId=form.getId(); } + if (calculatedFormId == null) { + calculatedFormId=formId; + } + nextOrPreviousFormResponse = setNextOrPreviousResponse(calculatedFormId, applicationEntity); + return nextOrPreviousFormResponse; } private NextOrPreviousFormResponse setNextOrPreviousResponse(Long calculatedFormId, ApplicationEntity applicationEntity) { NextOrPreviousFormResponse nextOrPreviousFormResponse = new NextOrPreviousFormResponse(); + Integer completedSteps=0; FormEntity formEntity = formService.validateForm(calculatedFormId); nextOrPreviousFormResponse.setFormId(calculatedFormId); + nextOrPreviousFormResponse.setApplicationStatus(ApplicationStatusTypeEnum.valueOf(applicationEntity.getStatus())); nextOrPreviousFormResponse.setApplicationFormResponse( applicationDao.processForm(formEntity, applicationEntity)); nextOrPreviousFormResponse.setCallId(applicationEntity.getCall().getId()); @@ -292,13 +300,27 @@ public class FlowFormDao { List flowEdgesList = flowEdgesRepository.findByCallId(applicationEntity.getCall().getId()); Long totalFormSteps = calculateTotalSteps(flowEdgesList); Long currentStep = calculateCurrentStep(formEntity); - List applicationFormList = applicationFormRepository.findByApplicationId(applicationEntity.getId()); nextOrPreviousFormResponse.setTotalFormSteps(totalFormSteps); - nextOrPreviousFormResponse.setCompletedSteps(Long.valueOf(applicationFormList.size())); + completedSteps = getCompletedSteps(applicationEntity); + nextOrPreviousFormResponse.setCompletedSteps(Long.valueOf(completedSteps)); nextOrPreviousFormResponse.setCurrentStep(currentStep); return nextOrPreviousFormResponse; } + public Integer getCompletedSteps(ApplicationEntity applicationEntity) { + Integer completedSteps=0; + List applicationFormList = applicationFormRepository.findByApplicationId(applicationEntity.getId()); + List applicationFormFieldEntities=new ArrayList<>(); + for (ApplicationFormEntity applicationFormEntity:applicationFormList){ + applicationFormFieldEntities=applicationFormFieldRepository.findByApplicationFormId(applicationFormEntity.getId()); + Boolean isCompleted=formDao.validateCompletedSteps(applicationFormFieldEntities, applicationEntity, applicationFormEntity.getForm()); + if(Boolean.TRUE.equals(isCompleted)){ + completedSteps++; + } + } + return completedSteps; + } + public Long calculateCurrentStep(FormEntity formEntity) { Long currentStep = 2l; if (formEntity.getId().equals(formEntity.getCall().getInitialForm())) { diff --git a/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java b/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java index 1d5ad1a1..318253d2 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java @@ -198,6 +198,8 @@ public class FormDao { public void validateFormField(List applicationFormFieldRequestList, ApplicationEntity applicationEntity, FormEntity formEntity) { Map formFieldMap = new LinkedHashMap(); for(ApplicationFormFieldRequestBean applicationFormFieldRequestBean:applicationFormFieldRequestList) { + if(applicationFormFieldRequestBean.getFieldValue()==null || applicationFormFieldRequestBean.getFieldValue().isEmpty()) + continue; formFieldMap.put(applicationFormFieldRequestBean.getFieldId(),applicationFormFieldRequestBean.getFieldValue()); } @@ -208,19 +210,19 @@ public class FormDao { formResponseBean.getContent().forEach(contentResponseBean -> { String fieldId = contentResponseBean.getId(); String value = (String) formFieldMap.get(fieldId); + String fieldLabel=contentResponseBean.getLabel(); if(value == null && isApplicationFormExist) { return; } FieldValidatorBean fieldValidatorBean = Utils.convertSourceObjectToDestinationObject(contentResponseBean.getValidators(), FieldValidatorBean.class); validator - .isRequired(value,fieldValidatorBean.getIsRequired(),fieldId) - .minLength(value, fieldValidatorBean.getMinLength(), fieldId) // Only applies if minLength is not null - .maxLength(value, fieldValidatorBean.getMaxLength(), fieldId) // Only applies if maxLength is not null - .matchesPattern(value, fieldValidatorBean.getPattern(), fieldId) // Only applies if pattern is present - .validateCustom(value, fieldValidatorBean.getCustom(), fieldId); // Add the custom validation here + .minLength(value, fieldValidatorBean.getMinLength(), fieldLabel) // Only applies if minLength is not null + .maxLength(value, fieldValidatorBean.getMaxLength(), fieldLabel) // Only applies if maxLength is not null + .matchesPattern(value, fieldValidatorBean.getPattern(), fieldLabel) // Only applies if pattern is present + .validateCustom(value, fieldValidatorBean.getCustom(), fieldLabel); // Add the custom validation here if (fieldValidatorBean.getCustom() != null && fieldValidatorBean.getCustom().equals(GepafinConstant.IS_PIVA)) { - String error = validateVatNumber(value, fieldValidatorBean.getCustom(), fieldId); + String error = validateVatNumber(value, fieldValidatorBean.getCustom(), fieldLabel); if(error != null) { validator.addError(error); } @@ -251,4 +253,37 @@ public class FormDao { } return error; } + public Boolean validateCompletedSteps(List applicationFormFieldEntityList, ApplicationEntity applicationEntity, FormEntity formEntity) { + Map formFieldMap = new LinkedHashMap(); + for(ApplicationFormFieldEntity applicationFormFieldEntity:applicationFormFieldEntityList) { + formFieldMap.put(applicationFormFieldEntity.getFieldId(),applicationFormFieldEntity.getFieldValue()); + } + + FormResponseBean formResponseBean = convertFormEntityToFormResponseBean(formEntity); + ApplicationFormEntity applicationFormEntity=applicationFormRepository.findByApplicationIdAndFormId(applicationEntity.getId(),formEntity.getId()); + Boolean isApplicationFormExist= getApplicationFormExist(applicationFormEntity); + FieldValidator validator = FieldValidator.create(); + formResponseBean.getContent().forEach(contentResponseBean -> { + String fieldId = contentResponseBean.getId(); + String value = (String) formFieldMap.get(fieldId); + + if(value == null && isApplicationFormExist) { + return; + } + FieldValidatorBean fieldValidatorBean = Utils.convertSourceObjectToDestinationObject(contentResponseBean.getValidators(), FieldValidatorBean.class); + validator + .isRequired(value,fieldValidatorBean.getIsRequired(),fieldId); + if (fieldValidatorBean.getCustom() != null && fieldValidatorBean.getCustom().equals(GepafinConstant.IS_PIVA)) { + String error = validateVatNumber(value, fieldValidatorBean.getCustom(), fieldId); + if(error != null) { + validator.addError(error); + } + } + }); + if (validator.hasErrors()) { + return false; // Validation failed, return false + } + return true; + } + } diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/NextOrPreviousFormResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/NextOrPreviousFormResponse.java index 55ee34be..0c39d4a9 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/NextOrPreviousFormResponse.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/NextOrPreviousFormResponse.java @@ -1,6 +1,7 @@ package net.gepafin.tendermanagement.model.response; import lombok.Data; +import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum; @Data public class NextOrPreviousFormResponse { @@ -16,6 +17,8 @@ public class NextOrPreviousFormResponse { private Long completedSteps; private Long currentStep; + + private ApplicationStatusTypeEnum applicationStatus; private FormApplicationResponse applicationFormResponse; diff --git a/src/main/java/net/gepafin/tendermanagement/util/FieldValidator.java b/src/main/java/net/gepafin/tendermanagement/util/FieldValidator.java index 71c76f1a..26edffff 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/FieldValidator.java +++ b/src/main/java/net/gepafin/tendermanagement/util/FieldValidator.java @@ -27,16 +27,16 @@ public class FieldValidator { private VatCheckDao vatCheckDao; - public FieldValidator notNull(Object object, String fieldName) { + public FieldValidator notNull(Object object, String fieldLabel) { if (Objects.isNull(object)) { - errors.add(MessageFormat.format(Translator.toLocale(GepafinConstant.FIELD_NOT_NULL), fieldName)); + errors.add(MessageFormat.format(Translator.toLocale(GepafinConstant.FIELD_NOT_NULL), fieldLabel)); } return this; } - public FieldValidator notEmpty(List list, String fieldName) { + public FieldValidator notEmpty(List list, String fieldLabel) { if (list == null || list.isEmpty()) { - errors.add(MessageFormat.format(Translator.toLocale(GepafinConstant.FIELD_NOT_EMPTY), fieldName)); + errors.add(MessageFormat.format(Translator.toLocale(GepafinConstant.FIELD_NOT_EMPTY), fieldLabel)); } return this; } @@ -46,23 +46,23 @@ public class FieldValidator { throw new ValidationException(Status.VALIDATION_ERROR, errors, Translator.toLocale(GepafinConstant.VALIDATION_MESSAGE)); } } - public FieldValidator minLength(String value, Long minLength, String fieldName) { + public FieldValidator minLength(String value, Long minLength, String fieldLabel) { if (minLength != null && value != null && value.length() < minLength) { - errors.add(MessageFormat.format(Translator.toLocale(GepafinConstant.VALIDATION_FIELD_MIN_LENGTH), fieldName, minLength)); + errors.add(MessageFormat.format(Translator.toLocale(GepafinConstant.VALIDATION_FIELD_MIN_LENGTH), fieldLabel, minLength)); } return this; } - public FieldValidator maxLength(String value, Long maxLength, String fieldName) { + public FieldValidator maxLength(String value, Long maxLength, String fieldLabel) { if (maxLength != null && value != null && value.length() > maxLength) { - errors.add(MessageFormat.format(Translator.toLocale(GepafinConstant.VALIDATION_FIELD_MAX_LENGTH), fieldName, maxLength)); + errors.add(MessageFormat.format(Translator.toLocale(GepafinConstant.VALIDATION_FIELD_MAX_LENGTH), fieldLabel, maxLength)); } return this; } - public FieldValidator matchesPattern(String value, String pattern, String fieldName) { + public FieldValidator matchesPattern(String value, String pattern, String fieldLabel) { if (value != null && pattern != null && !value.matches(pattern)) { - errors.add(MessageFormat.format(Translator.toLocale(GepafinConstant.VALIDATION_FIELD_PATTERN), fieldName)); + errors.add(MessageFormat.format(Translator.toLocale(GepafinConstant.VALIDATION_FIELD_PATTERN), fieldLabel)); } return this; } @@ -147,4 +147,7 @@ public class FieldValidator { } return this; } + public boolean hasErrors() { + return !errors.isEmpty(); + } } From d45fce59ec04e972fca3ee3af5b86f685d3fc151 Mon Sep 17 00:00:00 2001 From: rajesh Date: Sat, 28 Sep 2024 21:40:14 +0530 Subject: [PATCH 45/58] Created crud opration for company api's --- .../constants/GepafinConstant.java | 12 +- .../tendermanagement/dao/CompanyDao.java | 156 ++++++++++++++++++ .../gepafin/tendermanagement/dao/UserDao.java | 14 +- .../tendermanagement/dao/VatCheckDao.java | 16 +- .../entities/BeneficiaryEntity.java | 2 +- .../entities/CompanyEntity.java | 53 ++++++ .../entities/UserWithCompanyEntity.java | 22 +++ .../model/request/CompanyRequest.java | 24 +++ .../model/response/CompanyResponse.java | 25 +++ .../repositories/CompanyRepository.java | 17 ++ .../UserWithCompanyRepository.java | 19 +++ .../service/CompanyService.java | 24 +++ .../service/feignClient/VatCheckService.java | 2 +- .../service/impl/CompanyServiceImpl.java | 72 ++++++++ .../service/impl/UserServiceImpl.java | 1 + .../gepafin/tendermanagement/util/Utils.java | 61 +++++-- .../web/rest/api/CompanyApi.java | 97 +++++++++++ .../errors/FeignClientForbiddenException.java | 22 +++ .../errors/FeignClientNotFoundException.java | 22 +++ .../FeignClientUnauthorizedException.java | 22 +++ .../FeignClientValidationException.java | 22 +++ .../api/errors/GlobalExceptionHandler.java | 55 ++++++ .../rest/api/impl/CompanyApiController.java | 89 ++++++++++ .../db/changelog/db.changelog-1.0.0.xml | 44 +++++ src/main/resources/message_en.properties | 10 ++ src/main/resources/message_it.properties | 10 ++ 26 files changed, 884 insertions(+), 29 deletions(-) create mode 100644 src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java create mode 100644 src/main/java/net/gepafin/tendermanagement/entities/CompanyEntity.java create mode 100644 src/main/java/net/gepafin/tendermanagement/entities/UserWithCompanyEntity.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/request/CompanyRequest.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/response/CompanyResponse.java create mode 100644 src/main/java/net/gepafin/tendermanagement/repositories/CompanyRepository.java create mode 100644 src/main/java/net/gepafin/tendermanagement/repositories/UserWithCompanyRepository.java create mode 100644 src/main/java/net/gepafin/tendermanagement/service/CompanyService.java create mode 100644 src/main/java/net/gepafin/tendermanagement/service/impl/CompanyServiceImpl.java create mode 100644 src/main/java/net/gepafin/tendermanagement/web/rest/api/CompanyApi.java create mode 100644 src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/FeignClientForbiddenException.java create mode 100644 src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/FeignClientNotFoundException.java create mode 100644 src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/FeignClientUnauthorizedException.java create mode 100644 src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/FeignClientValidationException.java create mode 100644 src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CompanyApiController.java diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index d79edb37..5f9ee8be 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -136,7 +136,6 @@ public class GepafinConstant { public static final String APPLICATION_IS_INCOMPLETE_MSG = "application.is.incomplete"; public static final String AUTHORIZATION = "Authorization"; public static final String CHECK_VATNUMBER_V2_NEW_URL = "https://imprese.openapi.it/advance"; - public static final String VATNUMBER_V2 = "https://imprese.openapi.it/advance"; public static final String VALIDATION_FIELD_CUSTOM="validation.field.custom"; public static final String VALIDATION_CODICE_FISCALE = "validation.codice.fiscale"; public static final String VALIDATION_CAP = "validation.cap"; @@ -167,4 +166,15 @@ public class GepafinConstant { public static final String ROLE_ID_MANDATORY = "role.id.mandatory"; public static final String VALIDATE_PASSWORD = "validate.password"; + public static final String COMPANY_CREATED_SUCCESS_MSG = "company.created.success"; + public static final String COMPANY_UPDATED_SUCCESS_MSG = "company.updated.success"; + public static final String COMPANY_DELETE_SUCCESS_MSG = "company.delete.success"; + public static final String COMPANY_GET_SUCCESS_MSG = "company.get.success"; + public static final String COMPANY_NOT_FOUND_MSG = "company.not.found"; + public static final String CHECK_VATNUMBER_SUCCESS_MSG = "check.vatnumber.success"; + public static final String INVALID_VATNUMBER = "invalid.vatnumber"; + public static final String VATNUMBER_MANDATORY = "vatnumber.mandatory"; + public static final String VATNUMBER_ALREADY_EXISTS = "vatnumber.already.exists"; + public static final String INVALID_EMAIL = "invalid.email"; + } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java b/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java new file mode 100644 index 00000000..6b0774aa --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java @@ -0,0 +1,156 @@ +package net.gepafin.tendermanagement.dao; + +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import net.gepafin.tendermanagement.config.Translator; +import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.entities.CompanyEntity; +import net.gepafin.tendermanagement.entities.UserEntity; +import net.gepafin.tendermanagement.entities.UserWithCompanyEntity; +import net.gepafin.tendermanagement.model.request.CompanyRequest; +import net.gepafin.tendermanagement.model.response.CompanyResponse; +import net.gepafin.tendermanagement.repositories.CompanyRepository; +import net.gepafin.tendermanagement.repositories.UserWithCompanyRepository; +import net.gepafin.tendermanagement.service.UserService; +import net.gepafin.tendermanagement.util.Utils; +import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; +import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException; +import net.gepafin.tendermanagement.web.rest.api.errors.Status; + +@Component +public class CompanyDao { + + @Autowired + private CompanyRepository companyRepository; + + @Autowired + private UserService userService; + + @Autowired + private UserWithCompanyRepository userWithCompanyRepository; + + public CompanyResponse createCompany(UserEntity userEntity, CompanyRequest companyRequest) { + validateCompany(companyRequest); + CompanyEntity companyEntity = convertCompanyRequestToCompanyEntity(companyRequest); + companyRepository.save(companyEntity); + createUserWithCompanyRelation(userEntity, companyEntity); + return convertCompanyEntityToCompanyResponse(companyEntity); + } + + private void validateCompany(CompanyRequest companyRequest) { + if (Boolean.FALSE.equals(StringUtils.isEmpty(companyRequest.getEmail())) + && Boolean.FALSE.equals(Utils.isValidEmail(companyRequest.getEmail()))) { + throw new CustomValidationException(Status.VALIDATION_ERROR, + Translator.toLocale(GepafinConstant.INVALID_EMAIL)); + } + if(StringUtils.isEmpty(companyRequest.getVatNumber())) { + throw new CustomValidationException(Status.VALIDATION_ERROR, + Translator.toLocale(GepafinConstant.VATNUMBER_MANDATORY)); + } + if(companyRepository.existsByVatNumber(companyRequest.getVatNumber())) { + throw new CustomValidationException(Status.VALIDATION_ERROR, + Translator.toLocale(GepafinConstant.VATNUMBER_ALREADY_EXISTS)); + } + + } + + private UserWithCompanyEntity createUserWithCompanyRelation(UserEntity userEntity, CompanyEntity companyEntity) { + UserWithCompanyEntity userWithCompanyEntity = new UserWithCompanyEntity(); + if (userEntity.getBeneficiary() != null) { + userWithCompanyEntity.setBeneficiaryId(userEntity.getBeneficiary().getId()); + } + userWithCompanyEntity.setCompanyId(companyEntity.getId()); + userWithCompanyEntity.setUserId(userEntity.getId()); + return userWithCompanyRepository.save(userWithCompanyEntity); + } + + private CompanyEntity convertCompanyRequestToCompanyEntity(CompanyRequest request) { + CompanyEntity entity = new CompanyEntity(); + entity.setCompanyName(request.getCompanyName()); + entity.setVatNumber(request.getVatNumber()); + entity.setCodiceFiscale(request.getCodiceFiscale()); + entity.setAddress(request.getAddress()); + entity.setPhoneNumber(request.getPhoneNumber()); + entity.setCity(request.getCity()); + entity.setProvince(request.getProvince()); + entity.setCap(request.getCap()); + entity.setCountry(request.getCountry()); + entity.setPec(request.getPec()); + entity.setEmail(request.getEmail()); + entity.setNumberOfEmployees(request.getNumberOfEmployees()); + entity.setAnnualRevenue(request.getAnnualRevenue()); + return entity; + } + + private CompanyResponse convertCompanyEntityToCompanyResponse(CompanyEntity entity) { + CompanyResponse response = new CompanyResponse(); + response.setId(entity.getId()); + response.setCompanyName(entity.getCompanyName()); + response.setVatNumber(entity.getVatNumber()); + response.setCodiceFiscale(entity.getCodiceFiscale()); + response.setAddress(entity.getAddress()); + response.setPhoneNumber(entity.getPhoneNumber()); + response.setCity(entity.getCity()); + response.setProvince(entity.getProvince()); + response.setCap(entity.getCap()); + response.setCountry(entity.getCountry()); + response.setPec(entity.getPec()); + response.setEmail(entity.getEmail()); + response.setNumberOfEmployees(entity.getNumberOfEmployees()); + response.setAnnualRevenue(entity.getAnnualRevenue()); + response.setCreatedDate(entity.getCreatedDate()); + response.setUpdatedDate(entity.getUpdatedDate()); + return response; + } + + public CompanyResponse updateCompany(UserEntity userEntity, Long companyId, CompanyRequest companyRequest) { + CompanyEntity companyEntity = validateCompany(companyId); + Utils.setIfUpdated(companyEntity::getCompanyName, companyEntity::setCompanyName, + companyRequest.getCompanyName()); + Utils.setIfUpdated(companyEntity::getVatNumber, companyEntity::setVatNumber, companyRequest.getVatNumber()); + Utils.setIfUpdated(companyEntity::getCodiceFiscale, companyEntity::setCodiceFiscale, + companyRequest.getCodiceFiscale()); + Utils.setIfUpdated(companyEntity::getAddress, companyEntity::setAddress, companyRequest.getAddress()); + Utils.setIfUpdated(companyEntity::getPhoneNumber, companyEntity::setPhoneNumber, + companyRequest.getPhoneNumber()); + Utils.setIfUpdated(companyEntity::getCity, companyEntity::setCity, companyRequest.getCity()); + Utils.setIfUpdated(companyEntity::getProvince, companyEntity::setProvince, companyRequest.getProvince()); + Utils.setIfUpdated(companyEntity::getCap, companyEntity::setCap, companyRequest.getCap()); + Utils.setIfUpdated(companyEntity::getCountry, companyEntity::setCountry, companyRequest.getCountry()); + Utils.setIfUpdated(companyEntity::getPec, companyEntity::setPec, companyRequest.getPec()); + Utils.setIfUpdated(companyEntity::getEmail, companyEntity::setEmail, companyRequest.getEmail()); + Utils.setIfUpdated(companyEntity::getNumberOfEmployees, companyEntity::setNumberOfEmployees, + companyRequest.getNumberOfEmployees()); + Utils.setIfUpdated(companyEntity::getAnnualRevenue, companyEntity::setAnnualRevenue, + companyRequest.getAnnualRevenue()); + companyRepository.save(companyEntity); + return convertCompanyEntityToCompanyResponse(companyEntity); + } + + public CompanyEntity validateCompany(Long companyId) { + return companyRepository.findById(companyId).orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, + Translator.toLocale(GepafinConstant.COMPANY_NOT_FOUND_MSG))); + } + + public CompanyResponse getCompany(UserEntity userEntity, Long companyId) { + return convertCompanyEntityToCompanyResponse(validateCompany(companyId)); + } + + public void deleteCompany(UserEntity userEntity, Long companyId) { + CompanyEntity companyEntity = validateCompany(companyId); + companyRepository.delete(companyEntity); + userWithCompanyRepository.deleteByCompanyId(companyId); + } + + public List getCompanyByUserId(Long userId) { + UserEntity userEntity = userService.validateUser(userId); + List companyIds = userWithCompanyRepository.findCompanyIdByUserId(userEntity.getId()); + List list = companyRepository.findByIdIn(companyIds); + return list.stream().map(this::convertCompanyEntityToCompanyResponse).toList(); + } + +} diff --git a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java index aa6e5cfc..8ce47e3b 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java @@ -31,8 +31,6 @@ import org.springframework.stereotype.Repository; import static net.gepafin.tendermanagement.util.Utils.setIfUpdated; -import java.util.regex.Pattern; - @Repository public class UserDao { @@ -84,7 +82,7 @@ public class UserDao { } private void validateUserRequest(String tempToken, UserReq userReq) { - if (Boolean.FALSE.equals(isValidEmail(userReq.getEmail()))) { + if (Boolean.FALSE.equals(Utils.isValidEmail(userReq.getEmail()))) { throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.VALIDATE_EMAIL)); } @@ -302,16 +300,6 @@ public class UserDao { authService.logout(request, response); log.info("User successfully logged out."); } - - - public static Boolean isValidEmail(String email) { - String EMAIL_REGEX = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$"; - if (email == null || email.isEmpty()) { - return false; - } - Pattern pattern = Pattern.compile(EMAIL_REGEX); - return pattern.matcher(email).matches(); - } public UserResponseBean updateUserStatus(Long userId, UserStatusEnum statusReq) { log.info("Updating status for user with ID: {}", userId); diff --git a/src/main/java/net/gepafin/tendermanagement/dao/VatCheckDao.java b/src/main/java/net/gepafin/tendermanagement/dao/VatCheckDao.java index 4d1d0f58..f4a07849 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/VatCheckDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/VatCheckDao.java @@ -1,8 +1,13 @@ package net.gepafin.tendermanagement.dao; import feign.FeignException; +import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.service.feignClient.VatCheckService; +import net.gepafin.tendermanagement.util.Utils; +import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; +import net.gepafin.tendermanagement.web.rest.api.errors.Status; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -67,8 +72,17 @@ public class VatCheckDao { } } catch (FeignException ex) { log.error("Exception occurred while checking vat number: {0}", ex); - throw ex; + Utils.callException(ex.status(), ex); } return responseBody; } + + public Map checkVatNumber(String vatNumber) { + try { + return checkVatNumberApi(vatNumber); + } catch (Exception e) { + throw new CustomValidationException(Status.VALIDATION_ERROR, + Translator.toLocale(GepafinConstant.INVALID_VATNUMBER)); + } + } } diff --git a/src/main/java/net/gepafin/tendermanagement/entities/BeneficiaryEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/BeneficiaryEntity.java index c0f31927..302f2af5 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/BeneficiaryEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/BeneficiaryEntity.java @@ -9,7 +9,7 @@ import jakarta.validation.constraints.Email; import lombok.Data; @Entity -@Table(name = "beneficiary") +@Table(name = "BENEFICIARY") @Data public class BeneficiaryEntity extends BaseEntity { diff --git a/src/main/java/net/gepafin/tendermanagement/entities/CompanyEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/CompanyEntity.java new file mode 100644 index 00000000..347e4db1 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/entities/CompanyEntity.java @@ -0,0 +1,53 @@ +package net.gepafin.tendermanagement.entities; + +import java.math.BigDecimal; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; +import lombok.Data; + +@Entity +@Table(name = "COMPANY") +@Data +public class CompanyEntity extends BaseEntity{ + + @Column(name = "COMPANY_NAME") + private String companyName; + + @Column(name = "VAT_NUMBER") + private String vatNumber; + + @Column(name = "CODICE_FISCALE") + private String codiceFiscale; + + @Column(name = "ADDRESS") + private String address; + + @Column(name = "PHONE_NUMBER") + private String phoneNumber; + + @Column(name = "CITY") + private String city; + + @Column(name = "PROVINCE") + private String province; + + @Column(name = "CAP") + private String cap; + + @Column(name = "COUNTRY") + private String country; + + @Column(name = "PEC") + private String pec; + + @Column(name = "EMAIL") + private String email; + + @Column(name = "NUMBER_OF_EMPLOYEES") + private String numberOfEmployees; + + @Column(name = "ANNUAL_REVENUE") + private BigDecimal annualRevenue; +} diff --git a/src/main/java/net/gepafin/tendermanagement/entities/UserWithCompanyEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/UserWithCompanyEntity.java new file mode 100644 index 00000000..fce47e66 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/entities/UserWithCompanyEntity.java @@ -0,0 +1,22 @@ +package net.gepafin.tendermanagement.entities; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; +import lombok.Data; + +@Entity +@Table(name = "USER_WITH_COMPANY") +@Data +public class UserWithCompanyEntity extends BaseEntity{ + + @Column(name = "USER_ID") + Long userId; + + @Column(name = "BENEFICIARY_ID") + Long beneficiaryId; + + @Column(name = "COMPANY_ID") + Long companyId; + +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/CompanyRequest.java b/src/main/java/net/gepafin/tendermanagement/model/request/CompanyRequest.java new file mode 100644 index 00000000..bfd6829d --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/CompanyRequest.java @@ -0,0 +1,24 @@ +package net.gepafin.tendermanagement.model.request; + +import java.math.BigDecimal; + +import lombok.Data; + +@Data +public class CompanyRequest { + + private String companyName; + private String vatNumber; + private String codiceFiscale; + private String address; + private String phoneNumber; + private String city; + private String province; + private String cap; + private String country; + private String pec; + private String email; + private String numberOfEmployees; + private BigDecimal annualRevenue; + +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/CompanyResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/CompanyResponse.java new file mode 100644 index 00000000..254d05a0 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/CompanyResponse.java @@ -0,0 +1,25 @@ +package net.gepafin.tendermanagement.model.response; + +import java.math.BigDecimal; + +import lombok.Data; +import net.gepafin.tendermanagement.model.BaseBean; + +@Data +public class CompanyResponse extends BaseBean{ + + private String companyName; + private String vatNumber; + private String codiceFiscale; + private String address; + private String phoneNumber; + private String city; + private String province; + private String cap; + private String country; + private String pec; + private String email; + private String numberOfEmployees; + private BigDecimal annualRevenue; + +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/CompanyRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/CompanyRepository.java new file mode 100644 index 00000000..9dc3a3a5 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/repositories/CompanyRepository.java @@ -0,0 +1,17 @@ +package net.gepafin.tendermanagement.repositories; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import net.gepafin.tendermanagement.entities.CompanyEntity; + +@Repository +public interface CompanyRepository extends JpaRepository { + + List findByIdIn(List companyIds); + + Boolean existsByVatNumber(String vatNumber); + +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/UserWithCompanyRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/UserWithCompanyRepository.java new file mode 100644 index 00000000..c026c801 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/repositories/UserWithCompanyRepository.java @@ -0,0 +1,19 @@ +package net.gepafin.tendermanagement.repositories; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import net.gepafin.tendermanagement.entities.UserWithCompanyEntity; + + +public interface UserWithCompanyRepository extends JpaRepository { + + void deleteByCompanyId(Long companyId); + + @Query("SELECT uwc.companyId FROM UserWithCompanyEntity uwc WHERE uwc.userId = :userId") + List findCompanyIdByUserId(@Param("userId") Long userId); + +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/CompanyService.java b/src/main/java/net/gepafin/tendermanagement/service/CompanyService.java new file mode 100644 index 00000000..e21c22c6 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/CompanyService.java @@ -0,0 +1,24 @@ +package net.gepafin.tendermanagement.service; + +import java.util.List; +import java.util.Map; + +import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.model.request.CompanyRequest; +import net.gepafin.tendermanagement.model.response.CompanyResponse; + +public interface CompanyService { + + CompanyResponse createCompany(HttpServletRequest request, CompanyRequest companyRequest); + + CompanyResponse updateCompany(HttpServletRequest request, Long companyId, CompanyRequest companyRequest); + + CompanyResponse getCompany(HttpServletRequest request, Long companyId); + + void deleteCompany(HttpServletRequest request, Long companyId); + + List getCompanyByUserId(HttpServletRequest request, Long userId); + + Map checkVatNumber(HttpServletRequest request, String vatNumber); + +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/feignClient/VatCheckService.java b/src/main/java/net/gepafin/tendermanagement/service/feignClient/VatCheckService.java index 6665690d..333ab3a1 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/feignClient/VatCheckService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/feignClient/VatCheckService.java @@ -11,7 +11,7 @@ import org.springframework.web.bind.annotation.RequestHeader; import java.net.URI; import java.util.Map; -@FeignClient(value = "vat-check-service", url = GepafinConstant.VATNUMBER_V2) +@FeignClient(value = "vat-check-service", url = GepafinConstant.CHECK_VATNUMBER_V2_NEW_URL) public interface VatCheckService { diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/CompanyServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/CompanyServiceImpl.java new file mode 100644 index 00000000..e54bf146 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/CompanyServiceImpl.java @@ -0,0 +1,72 @@ +package net.gepafin.tendermanagement.service.impl; + +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.dao.CompanyDao; +import net.gepafin.tendermanagement.dao.VatCheckDao; +import net.gepafin.tendermanagement.entities.UserEntity; +import net.gepafin.tendermanagement.model.request.CompanyRequest; +import net.gepafin.tendermanagement.model.response.CompanyResponse; +import net.gepafin.tendermanagement.service.CompanyService; +import net.gepafin.tendermanagement.util.Validator; + +@Service +public class CompanyServiceImpl implements CompanyService { + + @Autowired + private Validator validator; + + @Autowired + private CompanyDao companyDao; + + @Autowired + private VatCheckDao vatCheckDao; + + @Override + @Transactional(rollbackFor = Exception.class) + public CompanyResponse createCompany(HttpServletRequest request, CompanyRequest companyRequest) { + UserEntity userEntity =validator.validateUser(request); + return companyDao.createCompany(userEntity, companyRequest); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public CompanyResponse updateCompany(HttpServletRequest request, Long companyId, CompanyRequest companyRequest) { + UserEntity userEntity =validator.validateUser(request); + return companyDao.updateCompany(userEntity, companyId, companyRequest); + } + + @Override + @Transactional(readOnly = true) + public CompanyResponse getCompany(HttpServletRequest request, Long companyId) { + UserEntity userEntity =validator.validateUser(request); + return companyDao.getCompany(userEntity, companyId); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteCompany(HttpServletRequest request, Long companyId) { + UserEntity userEntity =validator.validateUser(request); + companyDao.deleteCompany(userEntity, companyId); + } + + @Override + @Transactional(readOnly = true) + public List getCompanyByUserId(HttpServletRequest request, Long userId) { + UserEntity userEntity = validator.validateUser(request); + return companyDao.getCompanyByUserId(userId); + } + + @Override + @Transactional(readOnly = true) + public Map checkVatNumber(HttpServletRequest request, String vatNumber) { + return vatCheckDao.checkVatNumber(vatNumber); + } + +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java index c109e6bb..74ceaf40 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java @@ -35,6 +35,7 @@ public class UserServiceImpl implements UserService { @Autowired private SamlSuccessHandler samlSuccessHandler; + @Override @Transactional(rollbackFor = Exception.class) public JWTToken createUser(HttpServletRequest request, String tempToken, UserReq userReq) { if (tempToken == null) { diff --git a/src/main/java/net/gepafin/tendermanagement/util/Utils.java b/src/main/java/net/gepafin/tendermanagement/util/Utils.java index 9de26d9c..af0bc684 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/Utils.java +++ b/src/main/java/net/gepafin/tendermanagement/util/Utils.java @@ -1,17 +1,5 @@ package net.gepafin.tendermanagement.util; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.json.JsonReadFeature; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.type.TypeFactory; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import io.micrometer.common.util.StringUtils; -import org.apache.commons.collections4.MapUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.lang.reflect.Field; import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; @@ -21,8 +9,29 @@ import java.util.List; import java.util.Map; import java.util.function.Consumer; import java.util.function.Supplier; +import java.util.regex.Pattern; import java.util.stream.Collectors; +import org.apache.commons.collections4.MapUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.json.JsonReadFeature; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.type.TypeFactory; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; + +import feign.FeignException; +import io.micrometer.common.util.StringUtils; +import net.gepafin.tendermanagement.web.rest.api.errors.FeignClientForbiddenException; +import net.gepafin.tendermanagement.web.rest.api.errors.FeignClientNotFoundException; +import net.gepafin.tendermanagement.web.rest.api.errors.FeignClientUnauthorizedException; +import net.gepafin.tendermanagement.web.rest.api.errors.FeignClientValidationException; + public class Utils { @@ -190,4 +199,32 @@ public class Utils { return null; } } + + public static void callException(Integer staus, FeignException ex) { + switch (staus) { + case 400: + throw new FeignClientValidationException(HttpStatus.valueOf(staus), ex.getMessage()); + + case 401: + throw new FeignClientUnauthorizedException(HttpStatus.valueOf(staus), ex.getMessage()); + + case 403: + throw new FeignClientForbiddenException(HttpStatus.valueOf(staus), ex.getMessage()); + + case 404: + throw new FeignClientNotFoundException(HttpStatus.valueOf(staus), ex.getMessage()); + default: + log.error("Exception occured :- {0}", ex); + throw ex; + } + } + + public static Boolean isValidEmail(String email) { + String EMAIL_REGEX = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$"; + if (email == null || email.isEmpty()) { + return false; + } + Pattern pattern = Pattern.compile(EMAIL_REGEX); + return pattern.matcher(email).matches(); + } } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/CompanyApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/CompanyApi.java new file mode 100644 index 00000000..53ff4102 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/CompanyApi.java @@ -0,0 +1,97 @@ +package net.gepafin.tendermanagement.web.rest.api; + +import java.util.List; +import java.util.Map; + +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.model.request.CompanyRequest; +import net.gepafin.tendermanagement.model.response.CompanyResponse; +import net.gepafin.tendermanagement.model.util.Response; +import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants; + +public interface CompanyApi { + + @Operation(summary = "Api to create company", responses = { @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @PostMapping(value = "", produces = { "application/json" }) + ResponseEntity> createCompany(HttpServletRequest request, + @Parameter(description = "Company request object", required = true) @RequestBody CompanyRequest companyRequest); + + @Operation(summary = "Api to update company", responses = { @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @PutMapping(value = "/{companyId}", produces = { "application/json" }) + ResponseEntity> updateCompany(HttpServletRequest request, + @Parameter(description = "The company id", required = true) @PathVariable("companyId") Long companyId, + @Parameter(description = "Company request object", required = true) @RequestBody CompanyRequest companyRequest); + + @Operation(summary = "Api to delete company", responses = { @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @DeleteMapping(value = "/{companyId}", produces = { "application/json" }) + ResponseEntity> deleteCompany(HttpServletRequest request, + @Parameter(description = "The company id", required = true) @PathVariable("companyId") Long companyId); + + @Operation(summary = "Api to get company", responses = { @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @GetMapping(value = "/{companyId}", produces = { "application/json" }) + ResponseEntity> getCompany(HttpServletRequest request, + @Parameter(description = "The company id", required = true) @PathVariable("companyId") Long companyId); + + @Operation(summary = "Api to get company by user Id", responses = { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @GetMapping(value = "/user/{userId}", produces = { "application/json" }) + ResponseEntity>> getCompanyByUserId(HttpServletRequest request, + @Parameter(description = "The company id", required = true) @PathVariable("userId") Long userId); + + @Operation(summary = "Api to check vatNumber", responses = { @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @GetMapping(value = "/vatNumber", produces = { "application/json" }) + ResponseEntity>> checkVatNumber(HttpServletRequest request, + @Parameter(description = "The vatNumber of company", required = true) @RequestParam("vatNumber") String vatNumber); + +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/FeignClientForbiddenException.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/FeignClientForbiddenException.java new file mode 100644 index 00000000..bfabad15 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/FeignClientForbiddenException.java @@ -0,0 +1,22 @@ +package net.gepafin.tendermanagement.web.rest.api.errors; + +import org.springframework.http.HttpStatus; + +import feign.FeignException; + +public class FeignClientForbiddenException extends FeignException{ + + private static final long serialVersionUID = 1L; + + private final HttpStatus status; + + public FeignClientForbiddenException(HttpStatus status,String message) { + super(403,message); + this.status = status; + } + + public HttpStatus getStatus() { + return status; + } + +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/FeignClientNotFoundException.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/FeignClientNotFoundException.java new file mode 100644 index 00000000..c5896f5e --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/FeignClientNotFoundException.java @@ -0,0 +1,22 @@ +package net.gepafin.tendermanagement.web.rest.api.errors; + +import org.springframework.http.HttpStatus; + +import feign.FeignException; + +public class FeignClientNotFoundException extends FeignException{ + + private static final long serialVersionUID = 1L; + + private final HttpStatus status; + + public FeignClientNotFoundException(HttpStatus status,String message) { + super(404,message); + this.status = status; + } + + public HttpStatus getStatus() { + return status; + } + +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/FeignClientUnauthorizedException.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/FeignClientUnauthorizedException.java new file mode 100644 index 00000000..9fe1092b --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/FeignClientUnauthorizedException.java @@ -0,0 +1,22 @@ +package net.gepafin.tendermanagement.web.rest.api.errors; + +import org.springframework.http.HttpStatus; + +import feign.FeignException; + +public class FeignClientUnauthorizedException extends FeignException{ + + private static final long serialVersionUID = 1L; + + private final HttpStatus status; + + public FeignClientUnauthorizedException(HttpStatus status,String message) { + super(401,message); + this.status = status; + } + + public HttpStatus getStatus() { + return status; + } + +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/FeignClientValidationException.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/FeignClientValidationException.java new file mode 100644 index 00000000..f623faab --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/FeignClientValidationException.java @@ -0,0 +1,22 @@ +package net.gepafin.tendermanagement.web.rest.api.errors; + +import org.springframework.http.HttpStatus; + +import feign.FeignException; + +public class FeignClientValidationException extends FeignException{ + + private static final long serialVersionUID = 1L; + + private final HttpStatus status; + + public FeignClientValidationException(HttpStatus status,String message) { + super(400,message); + this.status = status; + } + + public HttpStatus getStatus() { + return status; + } + +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/GlobalExceptionHandler.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/GlobalExceptionHandler.java index 1118da03..fd7ba455 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/GlobalExceptionHandler.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/GlobalExceptionHandler.java @@ -2,9 +2,11 @@ package net.gepafin.tendermanagement.web.rest.api.errors; import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.model.util.Response; +import net.gepafin.tendermanagement.util.Utils; import java.util.ArrayList; import java.util.List; +import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -14,6 +16,9 @@ import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; + +import feign.FeignException; + import org.springframework.http.ResponseEntity; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authorization.AuthorizationDeniedException; @@ -122,4 +127,54 @@ public class GlobalExceptionHandler { } + @ResponseStatus(value = HttpStatus.BAD_REQUEST) + @ExceptionHandler(FeignClientValidationException.class) + @ResponseBody + public Map handleFeignClientBadRequestException(final Throwable ex) { + log.error(ex.getMessage()); + log.error(ex.getLocalizedMessage(), ex); + String exceptionString = ex.getMessage().substring(ex.getMessage().indexOf("]: [") + 4, ex.getMessage().length() - 1); + return Utils.convertIntoJson(exceptionString); + } + + @ResponseStatus(value = HttpStatus.FORBIDDEN) + @ExceptionHandler(FeignClientForbiddenException.class) + @ResponseBody + public Map handleFeignClientForbiddenException(final Throwable ex) { + log.error(ex.getMessage()); + log.error(ex.getLocalizedMessage(), ex); + String exceptionString = ex.getMessage().substring(ex.getMessage().indexOf("]: [") + 4, ex.getMessage().length() - 1); + return Utils.convertIntoJson(exceptionString); + } + + @ResponseStatus(value = HttpStatus.UNAUTHORIZED) + @ExceptionHandler(FeignClientUnauthorizedException.class) + @ResponseBody + public Map handleFeignClientUnauthorizedException(final Throwable ex) { + log.error(ex.getMessage()); + log.error(ex.getLocalizedMessage(), ex); + String exceptionString = ex.getMessage().substring(ex.getMessage().indexOf("]: [") + 4, ex.getMessage().length() - 1); + return Utils.convertIntoJson(exceptionString); + } + + @ResponseStatus(value = HttpStatus.NOT_FOUND) + @ExceptionHandler(FeignClientNotFoundException.class) + @ResponseBody + public Map handleFeignClientNotFoundException(final Throwable ex) { + log.error(ex.getMessage()); + log.error(ex.getLocalizedMessage(), ex); + String exceptionString = ex.getMessage().substring(ex.getMessage().indexOf("]: [") + 4, ex.getMessage().length() - 1); + return Utils.convertIntoJson(exceptionString); + } + + @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR) + @ExceptionHandler(FeignException.class) + @ResponseBody + public Map handleFeignException(final Throwable ex) { + log.error(ex.getMessage()); + log.error(ex.getLocalizedMessage(), ex); + String exceptionString = ex.getMessage().substring(ex.getMessage().indexOf("]: [") + 4, ex.getMessage().length() - 1); + return Utils.convertIntoJson(exceptionString); + } + } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CompanyApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CompanyApiController.java new file mode 100644 index 00000000..c4428f04 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CompanyApiController.java @@ -0,0 +1,89 @@ +package net.gepafin.tendermanagement.web.rest.api.impl; + +import java.util.List; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.config.Translator; +import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.model.request.CompanyRequest; +import net.gepafin.tendermanagement.model.response.CompanyResponse; +import net.gepafin.tendermanagement.model.util.Response; +import net.gepafin.tendermanagement.service.CompanyService; +import net.gepafin.tendermanagement.web.rest.api.CompanyApi; +import net.gepafin.tendermanagement.web.rest.api.errors.Status; + +@RestController +@RequestMapping("${openapi.gepafin.base-path:/v1/company}") +public class CompanyApiController implements CompanyApi{ + + private final Logger log = LoggerFactory.getLogger(CompanyApiController.class); + + @Autowired + private CompanyService companyService; + + @Override + public ResponseEntity> createCompany(HttpServletRequest request, + CompanyRequest companyRequest) { + log.info("Create company with - Request Body: {}", companyRequest); + CompanyResponse data = companyService.createCompany(request, companyRequest); + return ResponseEntity.status(HttpStatus.CREATED) + .body(new Response<>(data, Status.SUCCESS, Translator.toLocale(GepafinConstant.COMPANY_CREATED_SUCCESS_MSG))); + } + + @Override + public ResponseEntity> updateCompany(HttpServletRequest request, Long companyId, + CompanyRequest companyRequest) { + log.info("Update company with - Request Body: {}", companyRequest); + CompanyResponse data = companyService.updateCompany(request, companyId, companyRequest); + + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(data, Status.SUCCESS, Translator.toLocale(GepafinConstant.COMPANY_UPDATED_SUCCESS_MSG))); + } + + @Override + public ResponseEntity> getCompany(HttpServletRequest request, Long companyId) { + + log.info("Get company with id: {}", companyId); + CompanyResponse data = companyService.getCompany(request, companyId); + + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(data, Status.SUCCESS, Translator.toLocale(GepafinConstant.COMPANY_GET_SUCCESS_MSG))); + } + + @Override + public ResponseEntity> deleteCompany(HttpServletRequest request, Long companyId) { + log.info("Delete company with id: {}", companyId); + companyService.deleteCompany(request, companyId); + + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(null, Status.SUCCESS, Translator.toLocale(GepafinConstant.COMPANY_DELETE_SUCCESS_MSG))); + } + + @Override + public ResponseEntity>> getCompanyByUserId(HttpServletRequest request, Long userId) { + + log.info("Get company with userId: {}", userId); + List data = companyService.getCompanyByUserId(request, userId); + + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(data, Status.SUCCESS, Translator.toLocale(GepafinConstant.COMPANY_GET_SUCCESS_MSG))); + } + + @Override + public ResponseEntity>> checkVatNumber(HttpServletRequest request, String vatNumber) { + log.info("check VatNumber with: {}", vatNumber); + Map data = companyService.checkVatNumber(request, vatNumber); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(data, Status.SUCCESS, Translator.toLocale(GepafinConstant.CHECK_VATNUMBER_SUCCESS_MSG))); + } + +} diff --git a/src/main/resources/db/changelog/db.changelog-1.0.0.xml b/src/main/resources/db/changelog/db.changelog-1.0.0.xml index 7f349fd8..d4da3d66 100644 --- a/src/main/resources/db/changelog/db.changelog-1.0.0.xml +++ b/src/main/resources/db/changelog/db.changelog-1.0.0.xml @@ -767,7 +767,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index cf80165c..96726470 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -194,3 +194,13 @@ codice.fiscale.exists=This codice fiscale is already associated with another use total.steps.not.zero=Total steps cannot be zero. completed.steps.not.valid=Completed steps should be between 0 and total steps. field.id.not.found=Field ID {0} does not exist in the form structure. +company.created.success=Company created successfully. +company.updated.success=Company updated successfully. +company.delete.success=Company deleted successfully. +company.get.success=Company retrieved successfully. +company.not.found=Company not found. +check.vatnumber.success=VAT number checked successfully. +invalid.vatnumber=Invalid VAT number. +vatnumber.mandatory=VatNumber is mandatory. +vatnumber.already.exists=VatNumber already exists. +invalid.email=Invalid email. diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index 9582a89d..324131cb 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -187,3 +187,13 @@ codice.fiscale.exists=Questo codice fiscale � gi� associato ad un altro uten total.steps.not.zero=Il totale dei passaggi non pu� essere zero. completed.steps.not.valid=I passaggi completati devono essere compresi tra 0 e il totale dei passaggi. field.id.not.found=L'ID campo {0} non esiste nella struttura del modulo. +company.created.success=Azienda creata con successo. +company.updated.success=Azienda aggiornata con successo. +company.delete.success=Azienda eliminata con successo. +company.get.success=Azienda recuperata con successo. +company.not.found=Azienda non trovata. +check.vatnumber.success=Numero di partita IVA verificato con successo. +invalid.vatnumber=Numero di partita IVA non valido. +vatnumber.mandatory=Il numero di partita IVA è obbligatorio. +vatnumber.already.exists=Il numero di partita IVA esiste già. +invalid.email=Email non valida. From c30106a63b3411561479840f67fee3c2fb466c8a Mon Sep 17 00:00:00 2001 From: rajesh Date: Sun, 29 Sep 2024 12:54:55 +0530 Subject: [PATCH 46/58] updated code --- .../gepafin/tendermanagement/dao/FormDao.java | 56 ++++++++----------- 1 file changed, 23 insertions(+), 33 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java b/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java index 318253d2..36ff8eb8 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java @@ -238,9 +238,31 @@ public class FormDao { return false; } + public Boolean validateCompletedSteps(List applicationFormFieldEntityList, ApplicationEntity applicationEntity, FormEntity formEntity) { + Map formFieldMap = new LinkedHashMap(); + for(ApplicationFormFieldEntity applicationFormFieldEntity:applicationFormFieldEntityList) { + formFieldMap.put(applicationFormFieldEntity.getFieldId(),applicationFormFieldEntity.getFieldValue()); + } + + FormResponseBean formResponseBean = convertFormEntityToFormResponseBean(formEntity); + FieldValidator validator = FieldValidator.create(); + formResponseBean.getContent().forEach(contentResponseBean -> { + String fieldId = contentResponseBean.getId(); + String value = (String) formFieldMap.get(fieldId); + + FieldValidatorBean fieldValidatorBean = Utils.convertSourceObjectToDestinationObject(contentResponseBean.getValidators(), FieldValidatorBean.class); + validator + .isRequired(value,fieldValidatorBean.getIsRequired(),fieldId); + }); + if (validator.hasErrors()) { + return false; // Validation failed, return false + } + return true; + } public String validateVatNumber(String value,String customRule,String fieldId){ String error=null; - if (value.matches("^\\d{1,11}$")) { + + if (value!=null && value.matches("^\\d{1,11}$")) { Map customData=null; try { Map vatCheckResponse = vatCheckDao.checkVatNumberApi(value); @@ -253,37 +275,5 @@ public class FormDao { } return error; } - public Boolean validateCompletedSteps(List applicationFormFieldEntityList, ApplicationEntity applicationEntity, FormEntity formEntity) { - Map formFieldMap = new LinkedHashMap(); - for(ApplicationFormFieldEntity applicationFormFieldEntity:applicationFormFieldEntityList) { - formFieldMap.put(applicationFormFieldEntity.getFieldId(),applicationFormFieldEntity.getFieldValue()); - } - - FormResponseBean formResponseBean = convertFormEntityToFormResponseBean(formEntity); - ApplicationFormEntity applicationFormEntity=applicationFormRepository.findByApplicationIdAndFormId(applicationEntity.getId(),formEntity.getId()); - Boolean isApplicationFormExist= getApplicationFormExist(applicationFormEntity); - FieldValidator validator = FieldValidator.create(); - formResponseBean.getContent().forEach(contentResponseBean -> { - String fieldId = contentResponseBean.getId(); - String value = (String) formFieldMap.get(fieldId); - - if(value == null && isApplicationFormExist) { - return; - } - FieldValidatorBean fieldValidatorBean = Utils.convertSourceObjectToDestinationObject(contentResponseBean.getValidators(), FieldValidatorBean.class); - validator - .isRequired(value,fieldValidatorBean.getIsRequired(),fieldId); - if (fieldValidatorBean.getCustom() != null && fieldValidatorBean.getCustom().equals(GepafinConstant.IS_PIVA)) { - String error = validateVatNumber(value, fieldValidatorBean.getCustom(), fieldId); - if(error != null) { - validator.addError(error); - } - } - }); - if (validator.hasErrors()) { - return false; // Validation failed, return false - } - return true; - } } From 9b3fd43bf9680024671f992cf5782aa3c92badd5 Mon Sep 17 00:00:00 2001 From: rajesh Date: Sun, 29 Sep 2024 19:59:10 +0530 Subject: [PATCH 47/58] Implemented company in application --- .../constants/GepafinConstant.java | 2 + .../tendermanagement/dao/ApplicationDao.java | 170 +++++++++++------- .../tendermanagement/dao/CompanyDao.java | 11 +- .../gepafin/tendermanagement/dao/FaqDao.java | 22 ++- .../gepafin/tendermanagement/dao/FlowDao.java | 5 - .../tendermanagement/dao/FlowFormDao.java | 4 +- .../entities/ApplicationEntity.java | 9 +- .../tendermanagement/entities/FaqEntity.java | 3 + .../response/ApplicationGetResponseBean.java | 4 + .../model/response/ApplicationResponse.java | 4 + .../response/NextOrPreviousFormResponse.java | 4 + .../repositories/ApplicationRepository.java | 10 +- .../UserWithCompanyRepository.java | 3 + .../service/ApplicationService.java | 5 +- .../service/CompanyService.java | 6 + .../tendermanagement/service/FaqService.java | 2 +- .../service/impl/ApplicationServiceImpl.java | 26 +-- .../service/impl/CompanyServiceImpl.java | 11 ++ .../service/impl/FaqServiceImpl.java | 4 +- .../tendermanagement/util/Validator.java | 35 +++- .../web/rest/api/ApplicationApi.java | 10 +- .../web/rest/api/DocumentApi.java | 10 +- .../tendermanagement/web/rest/api/FaqApi.java | 2 +- .../api/impl/ApplicationApiController.java | 8 +- .../web/rest/api/impl/FaqApiController.java | 4 +- .../db/changelog/db.changelog-1.0.0.xml | 11 ++ src/main/resources/message_en.properties | 1 + src/main/resources/message_it.properties | 1 + 28 files changed, 269 insertions(+), 118 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index 5f9ee8be..06e0927c 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -176,5 +176,7 @@ public class GepafinConstant { public static final String VATNUMBER_MANDATORY = "vatnumber.mandatory"; public static final String VATNUMBER_ALREADY_EXISTS = "vatnumber.already.exists"; public static final String INVALID_EMAIL = "invalid.email"; + public static final String UNAUTHORIZED = "UNAUTHORIZED"; + public static final String COMPANY_ID_MANDATORY = "company.id.mandatory"; } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java index c7ad96c5..8dd589e4 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java @@ -17,15 +17,18 @@ import net.gepafin.tendermanagement.service.FormService; import net.gepafin.tendermanagement.util.DateTimeUtil; import net.gepafin.tendermanagement.util.FieldValidator; import net.gepafin.tendermanagement.util.Utils; +import net.gepafin.tendermanagement.util.Validator; import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException; import net.gepafin.tendermanagement.web.rest.api.errors.Status; -import org.checkerframework.checker.units.qual.A; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Component; +import jakarta.persistence.criteria.Predicate; + import java.text.MessageFormat; import java.time.LocalDateTime; import java.util.*; @@ -65,14 +68,17 @@ public class ApplicationDao { @Autowired private FlowDataRepository flowDataRepository; + + @Autowired + private Validator validator; - public ApplicationResponseBean createApplication(ApplicationRequestBean applicationRequestBean, UserEntity userEntity, Long formId,Long applicationId) { + public ApplicationResponseBean createApplication(ApplicationRequestBean applicationRequestBean, UserEntity userEntity, Long formId, Long applicationId) { FormEntity formEntity = formService.validateForm(formId); - CallEntity call = callService.validatePublishedCall(formEntity.getCall().getId()); + callService.validatePublishedCall(formEntity.getCall().getId()); validateFormFields(applicationRequestBean,formEntity); ApplicationEntity applicationEntity = validateApplication(applicationId); - if(Boolean.TRUE.equals(applicationEntity.getStatus().equals(ApplicationStatusTypeEnum.SUBMIT.getValue()))){ + if(Boolean.TRUE.equals(applicationEntity.getStatus().equals(ApplicationStatusTypeEnum.SUBMIT.getValue()))) { throw new CustomValidationException(Status.BAD_REQUEST,Translator.toLocale(GepafinConstant.APPLICATION_ALREADY_SUBMITTED)); } formService.validateFormField(applicationRequestBean.getFormFields(),applicationEntity,formEntity); @@ -94,9 +100,10 @@ public class ApplicationDao { return applicationFormEntity; } - public ApplicationEntity createApplicationEntity(UserEntity user, CallEntity call) { + public ApplicationEntity createApplicationEntity(UserEntity user, CallEntity call, CompanyEntity companyEntity) { ApplicationEntity entity = new ApplicationEntity(); - entity.setUser(user); + entity.setUserId(user.getId()); + entity.setCompany(companyEntity); entity.setCall(call); entity.setIsDeleted(false); entity.setStatus(ApplicationStatusTypeEnum.DRAFT.getValue()); @@ -109,7 +116,6 @@ public class ApplicationDao { ApplicationEntity applicationEntity = validateApplication(id); ApplicationFormEntity applicationFormEntity = applicationFormRepository.findByApplicationIdAndFormId(applicationEntity.getId(),formId); List applicationFormFieldResponseBeans=new ArrayList<>(); - ApplicationFormFieldResponseBean applicationFormFieldResponseBeans1=null; List applicationFormFieldEntities = applicationFormFieldRepository.findByApplicationFormId(applicationFormEntity.getId()); applicationFormFieldResponseBeans=createApplicationFormFieldResponse(applicationFormFieldEntities, applicationFormEntity, applicationFormFieldResponseBeans); ApplicationResponseBean applicationResponseBean= convertApplicationEntityToApplicationResponseBean(applicationEntity); @@ -170,44 +176,74 @@ public class ApplicationDao { log.info("Application deleted with ID: {}", id); } - public List getAllApplications(UserEntity userEntity, Long callId) { - boolean isBeneficiary = isBeneficiary(userEntity); - +// public List getAllApplications(UserEntity userEntity, Long callId, CompanyEntity companyEntity) { +// boolean isBeneficiary = validator.checkIsBeneficiary(); +// +// log.info("Fetching applications for RoleType: {}", userEntity.getRoleEntity().getRoleType()); +// List applicationResponses = new ArrayList<>(); +// +// if (callId != null) { +// // Fetch based on callId and user if role is BENEFICIARY, otherwise fetch all for the call +// log.info("Fetching applications for callId: {}", callId); +// CallEntity call = callService.validateCall(callId); +// +// // Use a single method to handle both conditions for consistency +// List applicationEntities = isBeneficiary +// ? applicationRepository.findByUserIdAndCallIdAndIsDeletedFalse(userEntity.getId(), call.getId()) +// .map(List::of) // Convert Optional to a List of one element +// .orElse(List.of()) // If not present, return an empty list +// : applicationRepository.findByCallIdAndIsDeletedFalse(call.getId()); +// +// applicationResponses = applicationEntities.stream() +// .map(this::getApplicationResponse) +// .collect(Collectors.toList()); +// +// } else { +// // Fetch all applications for the user if BENEFICIARY, or fetch all applications in general +// List applicationEntities = isBeneficiary +// ? applicationRepository.findByUserIdAndIsDeletedFalse(companyEntity.getId()) +// : applicationRepository.findByIsDeletedFalse(); +// +// applicationResponses = applicationEntities.stream() +// .map(this::getApplicationResponse) +// .collect(Collectors.toList()); +// } +// +// return applicationResponses; +// } + + public List getAllApplications(UserEntity userEntity, Long callId, Long companyId) { + log.info("Fetching applications for RoleType: {}", userEntity.getRoleEntity().getRoleType()); - List applicationResponses = new ArrayList<>(); - if (callId != null) { - // Fetch based on callId and user if role is BENEFICIARY, otherwise fetch all for the call - log.info("Fetching applications for callId: {}", callId); - CallEntity call = callService.validateCall(callId); + Specification spec = search(userEntity.getId(), callId, companyId); - // Use a single method to handle both conditions for consistency - List applicationEntities = isBeneficiary - ? applicationRepository.findByUserIdAndCallIdAndIsDeletedFalse(userEntity.getId(), call.getId()) - .map(List::of) // Convert Optional to a List of one element - .orElse(List.of()) // If not present, return an empty list - : applicationRepository.findByCallIdAndIsDeletedFalse(call.getId()); + List applicationEntities = applicationRepository.findAll(spec); - applicationResponses = applicationEntities.stream() - .map(this::getApplicationResponse) - .collect(Collectors.toList()); - - } else { - // Fetch all applications for the user if BENEFICIARY, or fetch all applications in general - List applicationEntities = isBeneficiary - ? applicationRepository.findByUserIdAndIsDeletedFalse(userEntity.getId()) - : applicationRepository.findByIsDeletedFalse(); - - applicationResponses = applicationEntities.stream() - .map(this::getApplicationResponse) - .collect(Collectors.toList()); - } - - return applicationResponses; + return applicationEntities.stream() + .map(this::getApplicationResponse) + .collect(Collectors.toList()); } - private ApplicationResponse getApplicationResponse(ApplicationEntity applicationEntity) { + private Specification search(Long userId, Long callId, Long companyId) { + return (root, query, builder) -> { + Boolean isBeneficiary = validator.checkIsBeneficiary(); + Predicate predicate = builder.isFalse(root.get("isDeleted")); + if (isBeneficiary) { + predicate = builder.and(predicate, builder.equal(root.get("userId"), userId)); + } + if (callId != null) { + predicate = builder.and(predicate, builder.equal(root.get("call").get("id"), callId)); + } + if (companyId != null) { + predicate = builder.and(predicate, builder.equal(root.get("company").get("id"), companyId)); + } + return predicate; + }; + } + + private ApplicationResponse getApplicationResponse(ApplicationEntity applicationEntity) { ApplicationResponse responseBean = new ApplicationResponse(); List flowEdgesList = flowEdgesRepository.findByCallId(applicationEntity.getCall().getId()); Long totalFormSteps = flowFormDao.calculateTotalSteps(flowEdgesList); @@ -223,13 +259,17 @@ public class ApplicationDao { responseBean.setSubmissionDate(applicationEntity.getSubmissionDate()); responseBean.setStatus(applicationEntity.getStatus()); responseBean.setComments(applicationEntity.getComments()); + responseBean.setCompanyId(applicationEntity.getCompany().getId()); + responseBean.setCompanyName(applicationEntity.getCompany().getCompanyName()); return responseBean; } - public ApplicationEntity validateApplication(Long id) { - ApplicationEntity applicationEntity= applicationRepository.findById(id).orElseThrow(() ->new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.APPLICATION_NOT_FOUND_MSG))); - return applicationEntity; - } + public ApplicationEntity validateApplication(Long id) { + ApplicationEntity applicationEntity = applicationRepository.findById(id) + .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, + Translator.toLocale(GepafinConstant.APPLICATION_NOT_FOUND_MSG))); + return applicationEntity; + } private ApplicationResponseBean convertApplicationEntityToApplicationResponseBean(ApplicationEntity entity) { ApplicationResponseBean response = new ApplicationResponseBean(); @@ -349,20 +389,19 @@ public class ApplicationDao { return applicationEntity; } - public ApplicationGetResponseBean getApplicationByFormId( Long applicationId,Long formId, UserEntity userEntity) { + public ApplicationGetResponseBean getApplicationByFormId( Long applicationId, Long formId, UserEntity userEntity) { List formApplicationResponses = new ArrayList<>(); List formEntities = new ArrayList<>(); boolean isBeneficiary = isBeneficiary(userEntity); ApplicationEntity applicationEntity = isBeneficiary - ? applicationRepository.findByIdAndUserIdAndIsDeletedFalse(applicationId,userEntity.getId()) + ? applicationRepository.findByIdAndUserIdAndIsDeletedFalse(applicationId, userEntity.getId()) .orElseThrow(() -> new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPLICATION_NOT_FOUND_MSG))) : applicationRepository.findById(applicationId) .stream().findFirst() .orElseThrow(() -> new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPLICATION_NOT_FOUND_MSG))); - if (formId != null) { FormEntity formEntity = formService.validateForm(formId); - Optional application = applicationRepository.findByUserIdAndCallIdAndIsDeletedFalse(userEntity.getId(), + Optional application = applicationRepository.findByIdAndUserIdAndCallIdAndIsDeletedFalse(applicationId, userEntity.getId(), formEntity.getCall().getId()); applicationEntity=application.get(); formEntities.add(formEntity); @@ -422,6 +461,8 @@ public class ApplicationDao { applicationGetResponseBean.setSubmissionDate(applicationEntity.getSubmissionDate()); applicationGetResponseBean.setCallId(applicationEntity.getCall().getId()); applicationGetResponseBean.setCallTitle(applicationEntity.getCall().getName()); + applicationGetResponseBean.setCompanyId(applicationEntity.getCompany().getId()); + applicationGetResponseBean.setCompanyName(applicationEntity.getCompany().getCompanyName()); return applicationGetResponseBean; } @@ -434,36 +475,29 @@ public class ApplicationDao { return formApplicationResponse; } - public ApplicationResponse createApplicationByCallId(ApplicationRequest applicationRequest,Long callId,UserEntity userEntity){ - CallEntity call=callService.validateCall(callId); - call = callService.validatePublishedCall(call.getId()); - checkIfApplicationExists(call,userEntity); - ApplicationEntity applicationEntity=createApplicationEntity(userEntity,call); - applicationEntity.setComments(applicationRequest.getComments()); - applicationEntity=saveApplicationEntity(applicationEntity); - ApplicationResponse applicationResponse=getApplicationResponse(applicationEntity); - return applicationResponse; - } - public void checkIfApplicationExists(CallEntity call,UserEntity userEntity){ - Optional applicationEntity=applicationRepository.findByUserIdAndCallIdAndIsDeletedFalse(userEntity.getId(),call.getId()); + public ApplicationResponse createApplicationByCallId(CompanyEntity companyEntity, + ApplicationRequest applicationRequest, Long callId, UserEntity userEntity) { + CallEntity call = callService.validateCall(callId); + call = callService.validatePublishedCall(call.getId()); + checkIfApplicationExists(call, companyEntity); + ApplicationEntity applicationEntity = createApplicationEntity(userEntity, call, companyEntity); + applicationEntity.setComments(applicationRequest.getComments()); + applicationEntity = saveApplicationEntity(applicationEntity); + ApplicationResponse applicationResponse = getApplicationResponse(applicationEntity); + return applicationResponse; + } + public void checkIfApplicationExists(CallEntity call, CompanyEntity companyEntity){ + Optional applicationEntity=applicationRepository.findByCompanyIdAndCallIdAndIsDeletedFalse(companyEntity.getId(),call.getId()); if(applicationEntity.isPresent()){ throw new CustomValidationException(Status.BAD_REQUEST,Translator.toLocale(GepafinConstant.APPLICATION_ALREADY_EXISTS)); } } - - - public ApplicationEntity getApplicationByCallAndUser(CallEntity call, UserEntity userEntity) { - return applicationRepository.findByUserIdAndCallIdAndIsDeletedFalse(userEntity.getId(), call.getId()) - .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, - Translator.toLocale(GepafinConstant.APPLICATION_NOT_FOUND_MSG))); - - } public void updateApplicationStatus(Long applicationId, ApplicationStatusTypeEnum status) { ApplicationEntity applicationEntity = validateApplication(applicationId); if (status.equals(ApplicationStatusTypeEnum.SUBMIT)) { - CallEntity callEntity = applicationEntity.getCall(); +// CallEntity callEntity = applicationEntity.getCall(); // Long initialFormId = callEntity.getInitialForm(); // Long finalFormId = callEntity.getFinalForm(); //// if (initialFormId == null || finalFormId == null) { @@ -501,7 +535,7 @@ public class ApplicationDao { return (int) Math.round(progress); } public void validateFormFields(ApplicationRequestBean request, FormEntity formEntity) { - List errors=new ArrayList<>(); + List contentResponseBeans=Utils.convertJsonStringToList(formEntity.getContent(),ContentResponseBean.class); List requestFields = request.getFormFields(); diff --git a/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java b/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java index 6b0774aa..5aa03a64 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java @@ -42,20 +42,20 @@ public class CompanyDao { } private void validateCompany(CompanyRequest companyRequest) { + if (Boolean.FALSE.equals(StringUtils.isEmpty(companyRequest.getEmail())) && Boolean.FALSE.equals(Utils.isValidEmail(companyRequest.getEmail()))) { throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.INVALID_EMAIL)); } - if(StringUtils.isEmpty(companyRequest.getVatNumber())) { + if (StringUtils.isEmpty(companyRequest.getVatNumber())) { throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.VATNUMBER_MANDATORY)); } - if(companyRepository.existsByVatNumber(companyRequest.getVatNumber())) { + if (companyRepository.existsByVatNumber(companyRequest.getVatNumber())) { throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.VATNUMBER_ALREADY_EXISTS)); } - } private UserWithCompanyEntity createUserWithCompanyRelation(UserEntity userEntity, CompanyEntity companyEntity) { @@ -153,4 +153,9 @@ public class CompanyDao { return list.stream().map(this::convertCompanyEntityToCompanyResponse).toList(); } + public UserWithCompanyEntity validateUserWithCompny(Long userId, Long companyId) { + return userWithCompanyRepository.findByUserIdAndCompanyId(userId, companyId).orElseThrow(() -> new CustomValidationException(Status.UNAUTHORIZED, + Translator.toLocale(GepafinConstant.UNAUTHORIZED))); + } + } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/FaqDao.java b/src/main/java/net/gepafin/tendermanagement/dao/FaqDao.java index b8ebd278..cfec2fe2 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/FaqDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/FaqDao.java @@ -12,8 +12,11 @@ import net.gepafin.tendermanagement.model.request.FaqReq; import net.gepafin.tendermanagement.model.response.FaqResponseBean; import net.gepafin.tendermanagement.repositories.FaqRepository; import net.gepafin.tendermanagement.service.CallService; +import net.gepafin.tendermanagement.service.CompanyService; import net.gepafin.tendermanagement.service.LookUpDataService; import net.gepafin.tendermanagement.util.DateTimeUtil; +import net.gepafin.tendermanagement.util.Validator; +import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException; import net.gepafin.tendermanagement.web.rest.api.errors.Status; import org.springframework.beans.factory.annotation.Autowired; @@ -35,12 +38,25 @@ public class FaqDao { @Autowired private LookUpDataService lookUpDataService; + + @Autowired + private Validator validator; + + @Autowired + private CompanyService companyService; - public FaqResponseBean createFaq(FaqReq faqRequest, UserEntity userEntity, Long callId) { - FaqEntity entity = new FaqEntity(); + public FaqResponseBean createFaq(FaqReq faqRequest, UserEntity userEntity, Long callId, Long companyId) { CallEntity callEntity = callService.validateCall(callId); - entity = createOrUpdateFaqEntity(faqRequest, callEntity, userEntity, + FaqEntity entity = createOrUpdateFaqEntity(faqRequest, callEntity, userEntity, LookUpDataEntity.LookUpDataTypeEnum.FAQ); + if (validator.checkIsBeneficiary() && companyId == null) { + throw new CustomValidationException(Status.VALIDATION_ERROR, + Translator.toLocale(GepafinConstant.COMPANY_ID_MANDATORY)); + } + if(companyId!=null) { + companyService.validateCompany(companyId); + entity.setCompanyId(companyId); + } faqRepository.save(entity); return convertToFaqResponseBean(entity); } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/FlowDao.java b/src/main/java/net/gepafin/tendermanagement/dao/FlowDao.java index 6b4d34d5..2fbf0943 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/FlowDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/FlowDao.java @@ -4,20 +4,16 @@ import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.entities.CallEntity; import net.gepafin.tendermanagement.entities.FlowDataEntity; -import net.gepafin.tendermanagement.entities.FlowDataEntity; import net.gepafin.tendermanagement.entities.FlowEdgesEntity; import net.gepafin.tendermanagement.enums.CallStatusEnum; import net.gepafin.tendermanagement.model.request.FlowDataRequestBean; import net.gepafin.tendermanagement.model.request.FlowEdgesRequestBean; import net.gepafin.tendermanagement.model.request.FlowRequestBean; -import net.gepafin.tendermanagement.model.response.EvaluationCriteriaResponseBean; import net.gepafin.tendermanagement.model.response.FlowDataResponseBean; import net.gepafin.tendermanagement.model.response.FlowEdgesResponseBean; import net.gepafin.tendermanagement.model.response.FlowResponseBean; import net.gepafin.tendermanagement.repositories.CallRepository; import net.gepafin.tendermanagement.repositories.FlowDataRepository; -import net.gepafin.tendermanagement.repositories.FlowDataRepository; -import net.gepafin.tendermanagement.repositories.FlowEdgesRepository; import net.gepafin.tendermanagement.repositories.FlowEdgesRepository; import net.gepafin.tendermanagement.service.CallService; import net.gepafin.tendermanagement.service.FormService; @@ -29,7 +25,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.time.LocalDateTime; -import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; diff --git a/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java b/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java index 57f3c756..b99ba6c2 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java @@ -1,7 +1,6 @@ package net.gepafin.tendermanagement.dao; import java.util.*; -import java.util.stream.Collectors; import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum; import net.gepafin.tendermanagement.repositories.*; @@ -20,7 +19,6 @@ import net.gepafin.tendermanagement.enums.FormActionEnum; import net.gepafin.tendermanagement.model.response.NextOrPreviousFormResponse; import net.gepafin.tendermanagement.service.FormService; import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; -import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException; import net.gepafin.tendermanagement.web.rest.api.errors.Status; @Component @@ -296,6 +294,8 @@ public class FlowFormDao { applicationDao.processForm(formEntity, applicationEntity)); nextOrPreviousFormResponse.setCallId(applicationEntity.getCall().getId()); nextOrPreviousFormResponse.setCallTitle(applicationEntity.getCall().getName()); + nextOrPreviousFormResponse.setCompanyId(applicationEntity.getCompany().getId()); + nextOrPreviousFormResponse.setCompanyName(applicationEntity.getCompany().getCompanyName()); List flowEdgesList = flowEdgesRepository.findByCallId(applicationEntity.getCall().getId()); Long totalFormSteps = calculateTotalSteps(flowEdgesList); diff --git a/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEntity.java index 8c9156e3..01648c67 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEntity.java @@ -13,9 +13,12 @@ import java.time.LocalDateTime; @Builder public class ApplicationEntity extends BaseEntity { + @Column(name = "USER_ID") + private Long userId; + @ManyToOne - @JoinColumn(name = "USER_ID", nullable = false) - private UserEntity user; + @JoinColumn(name = "COMPANY_ID", nullable = false) + private CompanyEntity company; @Column(name = "SUBMISSION_DATE") private LocalDateTime submissionDate; @@ -29,7 +32,7 @@ public class ApplicationEntity extends BaseEntity { @ManyToOne @JoinColumn(name = "CALL_ID", nullable = false) private CallEntity call; - + @Column(name="IS_DELETED") private Boolean isDeleted; diff --git a/src/main/java/net/gepafin/tendermanagement/entities/FaqEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/FaqEntity.java index 38cd3b2b..a476f2c5 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/FaqEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/FaqEntity.java @@ -41,6 +41,9 @@ public class FaqEntity extends BaseEntity { @Column(name ="IS_DELETED", nullable = false) private Boolean isDeleted = false; + + @Column(name ="COMPANY_ID") + private Long companyId; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationGetResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationGetResponseBean.java index 50ce0c57..9078f3a2 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationGetResponseBean.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationGetResponseBean.java @@ -19,6 +19,10 @@ public class ApplicationGetResponseBean { private Long callId; private String callTitle; + + private Long companyId; + + private String companyName; private List form; diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationResponse.java index b5a0fbb2..4283637f 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationResponse.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationResponse.java @@ -26,5 +26,9 @@ public class ApplicationResponse{ private String status; private String comments; + + private Long companyId; + + private String companyName; } \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/NextOrPreviousFormResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/NextOrPreviousFormResponse.java index 0c39d4a9..7864e831 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/NextOrPreviousFormResponse.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/NextOrPreviousFormResponse.java @@ -17,6 +17,10 @@ public class NextOrPreviousFormResponse { private Long completedSteps; private Long currentStep; + + private Long companyId; + + private String companyName; private ApplicationStatusTypeEnum applicationStatus; diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java index ad9104a5..567c8198 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java @@ -3,6 +3,7 @@ package net.gepafin.tendermanagement.repositories; import net.gepafin.tendermanagement.entities.ApplicationEntity; import net.gepafin.tendermanagement.entities.FaqEntity; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; @@ -11,9 +12,7 @@ import java.util.List; import java.util.Optional; @Repository -public interface ApplicationRepository extends JpaRepository { - - public Optional findByUserIdAndCallIdAndIsDeletedFalse(Long userId,Long callId); +public interface ApplicationRepository extends JpaRepository, JpaSpecificationExecutor { public List findByUserIdAndIsDeletedFalse(Long userId); @@ -26,4 +25,9 @@ public interface ApplicationRepository extends JpaRepository findByIdAndUserIdAndIsDeletedFalse(Long id,Long userId); + Optional findByCompanyIdAndCallIdAndIsDeletedFalse(Long companyId, Long callId); + + public Optional findByIdAndUserIdAndCallIdAndIsDeletedFalse(Long applicationId, Long userId, + Long callId); + } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/UserWithCompanyRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/UserWithCompanyRepository.java index c026c801..89da2436 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/UserWithCompanyRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/UserWithCompanyRepository.java @@ -1,6 +1,7 @@ package net.gepafin.tendermanagement.repositories; import java.util.List; +import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; @@ -16,4 +17,6 @@ public interface UserWithCompanyRepository extends JpaRepository findCompanyIdByUserId(@Param("userId") Long userId); + Optional findByUserIdAndCompanyId(Long userId, Long companyId); + } diff --git a/src/main/java/net/gepafin/tendermanagement/service/ApplicationService.java b/src/main/java/net/gepafin/tendermanagement/service/ApplicationService.java index 152bc1b5..a8f6ad53 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/ApplicationService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/ApplicationService.java @@ -19,15 +19,16 @@ public interface ApplicationService { ApplicationGetResponseBean getApplicationByFormId(HttpServletRequest request, Long applicationId,Long formId); - List getAllApplications(HttpServletRequest request,Long callId); + List getAllApplications(HttpServletRequest request,Long callId, Long companyId); void deleteApplication(HttpServletRequest request, Long applicationId); public ApplicationEntity validateApplication(Long userId); - public ApplicationResponse createApplication(HttpServletRequest request, ApplicationRequest applicationRequest, Long callId); + public ApplicationResponse createApplication(HttpServletRequest request, Long companyId, ApplicationRequest applicationRequest, Long callId); public NextOrPreviousFormResponse getNextOrPreviousForm(HttpServletRequest request, Long applicationId, Long formId, FormActionEnum action); public void updateApplicationStatus(HttpServletRequest request, Long applicationId, ApplicationStatusTypeEnum status); + } diff --git a/src/main/java/net/gepafin/tendermanagement/service/CompanyService.java b/src/main/java/net/gepafin/tendermanagement/service/CompanyService.java index e21c22c6..d0d7ce20 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/CompanyService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/CompanyService.java @@ -4,6 +4,8 @@ import java.util.List; import java.util.Map; import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.entities.CompanyEntity; +import net.gepafin.tendermanagement.entities.UserWithCompanyEntity; import net.gepafin.tendermanagement.model.request.CompanyRequest; import net.gepafin.tendermanagement.model.response.CompanyResponse; @@ -21,4 +23,8 @@ public interface CompanyService { Map checkVatNumber(HttpServletRequest request, String vatNumber); + CompanyEntity validateCompany(Long companyId); + + UserWithCompanyEntity validateUserWithCompny(Long userId, Long companyId); + } diff --git a/src/main/java/net/gepafin/tendermanagement/service/FaqService.java b/src/main/java/net/gepafin/tendermanagement/service/FaqService.java index 55adc950..74fd414d 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/FaqService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/FaqService.java @@ -11,7 +11,7 @@ import net.gepafin.tendermanagement.model.response.FaqResponseBean; public interface FaqService { - FaqResponseBean createFaq(HttpServletRequest request,Long callId, FaqReq faqRequest); + FaqResponseBean createFaq(HttpServletRequest request,Long callId, Long companyId, FaqReq faqRequest); FaqResponseBean getFaqById(HttpServletRequest request, Long id); diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java index e2364698..a64afadf 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java @@ -4,6 +4,7 @@ import jakarta.servlet.http.HttpServletRequest; import net.gepafin.tendermanagement.dao.ApplicationDao; import net.gepafin.tendermanagement.dao.FlowFormDao; import net.gepafin.tendermanagement.entities.ApplicationEntity; +import net.gepafin.tendermanagement.entities.CompanyEntity; import net.gepafin.tendermanagement.entities.UserEntity; import net.gepafin.tendermanagement.model.request.ApplicationRequest; import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum; @@ -35,10 +36,11 @@ public class ApplicationServiceImpl implements ApplicationService { @Override @Transactional(rollbackFor = Exception.class) - public ApplicationResponseBean createApplication(HttpServletRequest request, ApplicationRequestBean applicationRequestBean,Long applicationId, Long formId) { - UserEntity userEntity = validator.validateUser(request); - return applicationDao.createApplication(applicationRequestBean,userEntity,formId,applicationId); - } + public ApplicationResponseBean createApplication(HttpServletRequest request, + ApplicationRequestBean applicationRequestBean, Long applicationId, Long formId) { + UserEntity userEntity = validator.validateUser(request); + return applicationDao.createApplication(applicationRequestBean, userEntity, formId, applicationId); + } @Override @Transactional(readOnly = true) @@ -60,9 +62,10 @@ public class ApplicationServiceImpl implements ApplicationService { @Override @Transactional(rollbackFor = Exception.class) - public ApplicationResponse createApplication(HttpServletRequest request, ApplicationRequest applicationRequest, Long callId) { + public ApplicationResponse createApplication(HttpServletRequest request, Long companyId, ApplicationRequest applicationRequest, Long callId) { UserEntity userEntity = validator.validateUser(request); - return applicationDao.createApplicationByCallId(applicationRequest,callId,userEntity); + CompanyEntity companyEntity = validator.validateUSerWithCompany(request, companyId); + return applicationDao.createApplicationByCallId(companyEntity, applicationRequest, callId, userEntity); } @Override @@ -80,8 +83,11 @@ public class ApplicationServiceImpl implements ApplicationService { @Override @Transactional(readOnly = true) - public List getAllApplications(HttpServletRequest request,Long callId) { - UserEntity userEntity = validator.validateUser(request); - return applicationDao.getAllApplications(userEntity,callId); - } + public List getAllApplications(HttpServletRequest request, Long callId, Long companyId) { + UserEntity userEntity = validator.validateUser(request); + if (companyId != null) { + validator.validateUSerWithCompany(request, companyId); + } + return applicationDao.getAllApplications(userEntity, callId, companyId); + } } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/CompanyServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/CompanyServiceImpl.java index e54bf146..6dfec87a 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/CompanyServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/CompanyServiceImpl.java @@ -10,7 +10,9 @@ import org.springframework.transaction.annotation.Transactional; import jakarta.servlet.http.HttpServletRequest; import net.gepafin.tendermanagement.dao.CompanyDao; import net.gepafin.tendermanagement.dao.VatCheckDao; +import net.gepafin.tendermanagement.entities.CompanyEntity; import net.gepafin.tendermanagement.entities.UserEntity; +import net.gepafin.tendermanagement.entities.UserWithCompanyEntity; import net.gepafin.tendermanagement.model.request.CompanyRequest; import net.gepafin.tendermanagement.model.response.CompanyResponse; import net.gepafin.tendermanagement.service.CompanyService; @@ -68,5 +70,14 @@ public class CompanyServiceImpl implements CompanyService { public Map checkVatNumber(HttpServletRequest request, String vatNumber) { return vatCheckDao.checkVatNumber(vatNumber); } + @Override + public CompanyEntity validateCompany(Long companyId) { + return companyDao.validateCompany(companyId); + } + + @Override + public UserWithCompanyEntity validateUserWithCompny(Long userId, Long companyId) { + return companyDao.validateUserWithCompny(userId, companyId); + } } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/FaqServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/FaqServiceImpl.java index 78a458f3..921b0ae7 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/FaqServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/FaqServiceImpl.java @@ -25,9 +25,9 @@ public class FaqServiceImpl implements FaqService { private Validator validator; @Override - public FaqResponseBean createFaq(HttpServletRequest request,Long callId, FaqReq faqRequest) { + public FaqResponseBean createFaq(HttpServletRequest request,Long callId, Long companyId, FaqReq faqRequest) { UserEntity userEntity = validator.validateUser(request); - return faqDao.createFaq(faqRequest, userEntity,callId); + return faqDao.createFaq(faqRequest, userEntity, callId, companyId); } @Override diff --git a/src/main/java/net/gepafin/tendermanagement/util/Validator.java b/src/main/java/net/gepafin/tendermanagement/util/Validator.java index 37c5c29f..44ba62af 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/Validator.java +++ b/src/main/java/net/gepafin/tendermanagement/util/Validator.java @@ -4,8 +4,10 @@ import jakarta.servlet.http.HttpServletRequest; import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.config.jwt.TokenProvider; import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.entities.CompanyEntity; import net.gepafin.tendermanagement.entities.UserEntity; import net.gepafin.tendermanagement.enums.RoleStatusEnum; +import net.gepafin.tendermanagement.service.CompanyService; import net.gepafin.tendermanagement.service.UserService; import net.gepafin.tendermanagement.web.rest.api.errors.Status; import net.gepafin.tendermanagement.web.rest.api.errors.UnauthorizedAccessException; @@ -26,6 +28,9 @@ public class Validator { @Autowired private UserService userService; + + @Autowired + private CompanyService companyService; public Map getUserInfoFromToken(HttpServletRequest request) { return tokenProvider.getUserInfoAndUserIdFromToken(request); @@ -36,7 +41,7 @@ public class Validator { return userService.validateUser(Long.parseLong(userInfo.get("userId").toString())); } - public Boolean checkIsSuperAdmin(HttpServletRequest request) { + public Boolean checkIsSuperAdmin() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication != null && authentication.isAuthenticated()) { @@ -51,9 +56,35 @@ public class Validator { } public void validateRequest(HttpServletRequest request,RoleStatusEnum role) { - if (RoleStatusEnum.ROLE_SUPER_ADMIN.equals(role) && Boolean.FALSE.equals(checkIsSuperAdmin(request))) { + if (RoleStatusEnum.ROLE_SUPER_ADMIN.equals(role) && Boolean.FALSE.equals(checkIsSuperAdmin())) { throw new UnauthorizedAccessException(Status.UNAUTHORIZED, Translator.toLocale(GepafinConstant.INVALID_REQUEST)); } } + + public CompanyEntity validateUSerWithCompany(HttpServletRequest request, Long companyId) { + if (checkIsSuperAdmin()) { + return companyService.validateCompany(companyId); + } + Map userInfo = tokenProvider.getUserInfoAndUserIdFromToken(request); + companyService.validateUserWithCompny(getUserId(userInfo), companyId); + return companyService.validateCompany(companyId); + } + + private Long getUserId(Map userInfo) { + return Long.parseLong(userInfo.get("userId").toString()); + } + + public Boolean checkIsBeneficiary() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + if (authentication != null && authentication.isAuthenticated()) { + // Check if the user has the ROLE_SUPER_ADMIN authority + for (GrantedAuthority authority : authentication.getAuthorities()) { + if (RoleStatusEnum.ROLE_BENEFICIARY.getValue().equals(authority.getAuthority())) { + return true; + } + } + } + return false; + } } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationApi.java index 9499bfe0..c56680ef 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationApi.java @@ -67,7 +67,8 @@ public interface ApplicationApi { @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) @GetMapping(value = "", produces = "application/json") ResponseEntity>> getAllApplications(HttpServletRequest request, - @Parameter(description = "The call id", required = false) @RequestParam(value = "callId", required = false) Long callId); + @Parameter(description = "The call id", required = false) @RequestParam(value = "callId", required = false) Long callId, + @Parameter(description = "The company id", required = false) @RequestParam(value = "companyId", required = false) Long companyId); @Operation(summary = "Api to delete application", responses = { @@ -93,9 +94,10 @@ public interface ApplicationApi { @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) @PostMapping(value = "/call/{callId}", produces = { "application/json" }) - ResponseEntity> createApplicationByCallId(HttpServletRequest request, - @Parameter(description = " Flow request object", required = true) @Valid @RequestBody ApplicationRequest applicationRequest, - @Parameter(description = "The call ID", required = true) @PathVariable("callId") Long callId); + ResponseEntity> createApplicationByCallId(HttpServletRequest request, + @Parameter(description = "The company ID", required = true) @RequestParam(value = "companyId", required = true) Long companyId, + @Parameter(description = " Flow request object", required = true) @Valid @RequestBody ApplicationRequest applicationRequest, + @Parameter(description = "The call ID", required = true) @PathVariable("callId") Long callId); diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/DocumentApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/DocumentApi.java index 9c2cedcc..45a16c8f 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/DocumentApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/DocumentApi.java @@ -31,9 +31,13 @@ public interface DocumentApi { @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) }))}) @PostMapping(value = "/uploadFile/source/{sourceId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) - default ResponseEntity>> uploadFile(HttpServletRequest httpServletRequest, @Parameter(description = "Source Id", required = true) @PathVariable("sourceId") Long sourceId, @RequestParam DocumentSourceTypeEnum sourceType, @RequestParam("file") List files, @RequestParam("documentType") DocumentTypeEnum documentTypeEnum) { - return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); - } + default ResponseEntity>> uploadFile(HttpServletRequest httpServletRequest, + @Parameter(description = "Source Id", required = true) @PathVariable("sourceId") Long sourceId, + @RequestParam("sourceType") DocumentSourceTypeEnum sourceType, + @RequestParam("file") List files, + @RequestParam("documentType") DocumentTypeEnum documentTypeEnum) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + } @Operation(summary = "API to delete a file by document id", responses = { diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/FaqApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/FaqApi.java index f44491a8..8fad8c06 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/FaqApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/FaqApi.java @@ -24,7 +24,7 @@ public interface FaqApi { }) @PostMapping(value = "/call/{callId}", consumes = "application/json", produces = "application/json") ResponseEntity> createFaq(HttpServletRequest request, @Parameter(description = "call id", required = true) - @PathVariable("callId") Long callId, @Valid @RequestBody FaqReq faqRequest); + @PathVariable("callId") Long callId, @RequestParam(value = "companyId", required = false) Long companyId, @Valid @RequestBody FaqReq faqRequest); @Operation(summary = "API to get FAQ by id", responses = { diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java index 1d8b205b..69f28492 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java @@ -60,14 +60,14 @@ public class ApplicationApiController implements ApplicationApi { } @Override - public ResponseEntity> createApplicationByCallId(HttpServletRequest request, ApplicationRequest applicationRequest, Long callId) { - ApplicationResponse applicationResponseBean=applicationService.createApplication(request,applicationRequest,callId); + public ResponseEntity> createApplicationByCallId(HttpServletRequest request, Long companyId, ApplicationRequest applicationRequest, Long callId) { + ApplicationResponse applicationResponseBean=applicationService.createApplication(request, companyId, applicationRequest, callId); return ResponseEntity.status(HttpStatus.CREATED) .body(new Response<>(applicationResponseBean, Status.SUCCESS, Translator.toLocale(GepafinConstant.APPLICATION_CREATED_SUCCESS_MSG))); } @Override - public ResponseEntity>> getAllApplications(HttpServletRequest request,Long callId) { - List applications = applicationService.getAllApplications(request,callId); + public ResponseEntity>> getAllApplications(HttpServletRequest request,Long callId,Long companyId) { + List applications = applicationService.getAllApplications(request,callId,companyId); log.info("Get All Applications"); return ResponseEntity.status(HttpStatus.OK) .body(new Response<>(applications, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_APPLICATION_SUCCESS_MSG))); diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/FaqApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/FaqApiController.java index 142e5614..d905e938 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/FaqApiController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/FaqApiController.java @@ -22,8 +22,8 @@ public class FaqApiController implements FaqApi { private FaqService faqService; @Override - public ResponseEntity> createFaq(HttpServletRequest request, Long callId,FaqReq faqRequest) { - FaqResponseBean response = faqService.createFaq(request,callId, faqRequest); + public ResponseEntity> createFaq(HttpServletRequest request, Long callId, Long companyId, FaqReq faqRequest) { + FaqResponseBean response = faqService.createFaq(request,callId, companyId, faqRequest); return ResponseEntity.status(HttpStatus.CREATED) .body(new Response<>(response, Status.SUCCESS, Translator.toLocale(GepafinConstant.FAQ_CREATED_SUCCESSFULLY))); } diff --git a/src/main/resources/db/changelog/db.changelog-1.0.0.xml b/src/main/resources/db/changelog/db.changelog-1.0.0.xml index d4da3d66..1fe6a617 100644 --- a/src/main/resources/db/changelog/db.changelog-1.0.0.xml +++ b/src/main/resources/db/changelog/db.changelog-1.0.0.xml @@ -813,5 +813,16 @@ + + + + + + + + + + + diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index 96726470..5ef423b2 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -204,3 +204,4 @@ invalid.vatnumber=Invalid VAT number. vatnumber.mandatory=VatNumber is mandatory. vatnumber.already.exists=VatNumber already exists. invalid.email=Invalid email. +company.id.mandatory=Company id is mandatory. diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index 324131cb..273cdef9 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -197,3 +197,4 @@ invalid.vatnumber=Numero di partita IVA non valido. vatnumber.mandatory=Il numero di partita IVA è obbligatorio. vatnumber.already.exists=Il numero di partita IVA esiste già. invalid.email=Email non valida. +company.id.mandatory=L'ID dell'azienda è obbligatorio. From 328726d12f311a580f14d4ee0d900095c316420a Mon Sep 17 00:00:00 2001 From: nishainnogent Date: Sun, 29 Sep 2024 21:33:23 +0530 Subject: [PATCH 48/58] Updated code --- .../java/net/gepafin/tendermanagement/dao/ApplicationDao.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java index c7ad96c5..e520a6ef 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java @@ -211,8 +211,7 @@ public class ApplicationDao { ApplicationResponse responseBean = new ApplicationResponse(); List flowEdgesList = flowEdgesRepository.findByCallId(applicationEntity.getCall().getId()); Long totalFormSteps = flowFormDao.calculateTotalSteps(flowEdgesList); - List applicationFormList = applicationFormRepository.findByApplicationId(applicationEntity.getId()); - Long completedSteps=(Long.valueOf(applicationFormList.size())); + Long completedSteps= Long.valueOf(flowFormDao.getCompletedSteps(applicationEntity)); Integer progress=calculateProgress(totalFormSteps,completedSteps); responseBean.setId(applicationEntity.getId()); responseBean.setProgress(progress); From a63cae25a4351901a4350ea288ccc1eaa56ce21f Mon Sep 17 00:00:00 2001 From: harish Date: Mon, 30 Sep 2024 14:39:54 +0530 Subject: [PATCH 49/58] updated FE base Url for prod --- src/main/resources/application-production.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/application-production.properties b/src/main/resources/application-production.properties index be371126..8de9367a 100644 --- a/src/main/resources/application-production.properties +++ b/src/main/resources/application-production.properties @@ -9,3 +9,4 @@ spring.h2.console.enabled=true base-url=http://bandi-api.gepafin.it isVatCheckGloballyDisabled = false +fe.base.url=http://bandi.gepafin.it \ No newline at end of file From cdaf79d0be44a3cd873ee46217aa133b6c2038aa Mon Sep 17 00:00:00 2001 From: nishainnogent Date: Mon, 30 Sep 2024 18:26:42 +0530 Subject: [PATCH 50/58] Updated code --- .../java/net/gepafin/tendermanagement/dao/FormDao.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java b/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java index 36ff8eb8..9cdf3fed 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/FormDao.java @@ -141,6 +141,13 @@ public class FormDao { ); } } + else { + Utils.setIfUpdated(formEntity::getLabel, formEntity::setLabel, formRequest.getLabel()); + Utils.setIfUpdated(formEntity::getContent, formEntity::setContent, setContentResponseBean(formRequest.getContent())); + formEntity.setUpdatedDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now())); + formEntity = saveFormEntity(formEntity); + return convertFormEntityToFormResponseBean(formEntity); + } } } } From 4e7ee29ea0854eaed12fc4d18703e932da85abe0 Mon Sep 17 00:00:00 2001 From: harish Date: Tue, 1 Oct 2024 14:57:08 +0530 Subject: [PATCH 51/58] Add company data to user response in API --- .../net/gepafin/tendermanagement/dao/UserDao.java | 15 ++++++++++++--- .../model/response/LoginResponse.java | 3 +++ .../model/response/UserResponseBean.java | 2 ++ .../service/impl/AuthenticationService.java | 10 ++++++++-- .../resources/application-production.properties | 2 +- 5 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java index 8ce47e3b..53825d01 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java @@ -10,12 +10,14 @@ import net.gepafin.tendermanagement.entities.UserEntity; import net.gepafin.tendermanagement.enums.RoleStatusEnum; import net.gepafin.tendermanagement.enums.UserStatusEnum; import net.gepafin.tendermanagement.model.request.*; +import net.gepafin.tendermanagement.model.response.CompanyResponse; import net.gepafin.tendermanagement.model.response.RoleResponseBean; import net.gepafin.tendermanagement.model.response.UserSamlResponse; import net.gepafin.tendermanagement.model.response.UserResponseBean; import net.gepafin.tendermanagement.model.util.JWTToken; import net.gepafin.tendermanagement.repositories.BeneficiaryRepository; import net.gepafin.tendermanagement.repositories.UserRepository; +import net.gepafin.tendermanagement.service.CompanyService; import net.gepafin.tendermanagement.service.impl.AuthenticationService; import net.gepafin.tendermanagement.util.Utils; import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; @@ -27,18 +29,22 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Component; import org.springframework.stereotype.Repository; +import java.util.List; + import static net.gepafin.tendermanagement.util.Utils.setIfUpdated; -@Repository +@Component public class UserDao { private final Logger log = LoggerFactory.getLogger(UserDao.class); @Autowired private UserRepository userRepository; - + @Autowired + private CompanyDao companyDao; @Autowired private AuthenticationService authService; @@ -77,8 +83,9 @@ public class UserDao { beneficiaryEntity.setLastName(userReq.getLastName()); beneficiaryEntity.setOrganization(userReq.getOrganization()); beneficiaryEntity.setPhoneNumber(userReq.getPhoneNumber()); + beneficiaryEntity =beneficiaryRepository.save(beneficiaryEntity); } - return beneficiaryRepository.save(beneficiaryEntity); + return beneficiaryEntity; } private void validateUserRequest(String tempToken, UserReq userReq) { @@ -188,6 +195,8 @@ public class UserDao { RoleResponseBean roleResponseBean = roleDao.convertRoleEntityToRoleResponse(userEntity.getRoleEntity()); userResponseBean.setRole(roleResponseBean); userResponseBean.setLastLogin(userEntity.getLastLogin()); + List companyResponseBeans = companyDao.getCompanyByUserId(userEntity.getId()); + userResponseBean.setCompanies(companyResponseBeans); if (userEntity.getBeneficiary() == null) { userResponseBean.setFirstName(userEntity.getFirstName()); userResponseBean.setLastName(userEntity.getLastName()); diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/LoginResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/LoginResponse.java index 6317724e..d9cf63e9 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/LoginResponse.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/LoginResponse.java @@ -6,6 +6,7 @@ import lombok.NoArgsConstructor; import lombok.Setter; import java.time.LocalDateTime; +import java.util.List; @Getter @Setter @@ -43,4 +44,6 @@ public class LoginResponse { private LocalDateTime createdDate; private LocalDateTime updatedDate; + + private List companies; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/UserResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/UserResponseBean.java index 565e2561..c0457120 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/UserResponseBean.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/UserResponseBean.java @@ -6,6 +6,7 @@ import net.gepafin.tendermanagement.enums.UserStatusEnum; import net.gepafin.tendermanagement.model.BaseBean; import java.time.LocalDateTime; +import java.util.List; @Getter @Setter @@ -37,4 +38,5 @@ public class UserResponseBean extends BaseBean { private LocalDateTime dateOfBirth; + private List companies; } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java b/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java index 96c0ce05..a84b325c 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java @@ -5,11 +5,13 @@ import jakarta.servlet.http.HttpServletResponse; import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.config.jwt.TokenProvider; import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.dao.CompanyDao; import net.gepafin.tendermanagement.dao.RoleDao; import net.gepafin.tendermanagement.entities.SamlResponseEntity; import net.gepafin.tendermanagement.entities.UserEntity; import net.gepafin.tendermanagement.enums.UserStatusEnum; import net.gepafin.tendermanagement.model.request.LoginReq; +import net.gepafin.tendermanagement.model.response.CompanyResponse; import net.gepafin.tendermanagement.model.response.LoginResponse; import net.gepafin.tendermanagement.model.response.RoleResponseBean; import net.gepafin.tendermanagement.model.response.UserSamlResponse; @@ -42,13 +44,15 @@ public class AuthenticationService { private final TokenProvider tokenProvider; private final AuthenticationManager authenticationManager; + @Autowired + private CompanyDao companyDao; @Autowired private UserRepository userRepository; @Autowired private RoleDao roleDao; - + @Autowired private SamlResponseRepository samlResponseLogRepository; @@ -90,10 +94,12 @@ public class AuthenticationService { return jwtToken; } - private static LoginResponse getLoginResponse(UserEntity user, RoleResponseBean roleResponseBean) { + private LoginResponse getLoginResponse(UserEntity user, RoleResponseBean roleResponseBean) { LoginResponse loginResponse = new LoginResponse(); loginResponse.setEmail(user.getEmail()); loginResponse.setId(user.getId()); + List companyResponseBeans = companyDao.getCompanyByUserId(user.getId()); + loginResponse.setCompanies(companyResponseBeans); loginResponse.setRole(roleResponseBean); loginResponse.setStatus(user.getStatus()); loginResponse.setLastLogin(user.getLastLogin()); diff --git a/src/main/resources/application-production.properties b/src/main/resources/application-production.properties index 8de9367a..8acc1e0c 100644 --- a/src/main/resources/application-production.properties +++ b/src/main/resources/application-production.properties @@ -9,4 +9,4 @@ spring.h2.console.enabled=true base-url=http://bandi-api.gepafin.it isVatCheckGloballyDisabled = false -fe.base.url=http://bandi.gepafin.it \ No newline at end of file +fe.base.url=http://gepafin-production-fe.s3-website.eu-central-1.amazonaws.com \ No newline at end of file From 6139faec24c56c72e4199bb7096874b9a90e3e88 Mon Sep 17 00:00:00 2001 From: harish Date: Tue, 1 Oct 2024 16:53:15 +0530 Subject: [PATCH 52/58] Added saml configation for production --- .../tendermanagement/config/SamlConfig.java | 20 ++++++++----- .../config/SamlSuccessHandler.java | 1 + .../application-production.properties | 6 +++- src/main/resources/application.properties | 4 +++ .../production/saml/idp-certificate.pem | 3 ++ .../resources/production/saml/private-key.pem | 28 +++++++++++++++++++ .../resources/production/saml/public-cert.pem | 24 ++++++++++++++++ 7 files changed, 78 insertions(+), 8 deletions(-) create mode 100644 src/main/resources/production/saml/idp-certificate.pem create mode 100644 src/main/resources/production/saml/private-key.pem create mode 100644 src/main/resources/production/saml/public-cert.pem diff --git a/src/main/java/net/gepafin/tendermanagement/config/SamlConfig.java b/src/main/java/net/gepafin/tendermanagement/config/SamlConfig.java index 67fd71e0..c66e26f1 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SamlConfig.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SamlConfig.java @@ -49,6 +49,12 @@ public class SamlConfig { @Value("${base-url}") String baseUrl; + + @Value("${spid.ipd.base.url}") + String ipdBaseUrl; + + @Value("${active.profile.folder}") + String activeProfileFolder; @Bean public RelyingPartyRegistrationRepository relyingPartyRegistrationRepository() { @@ -66,8 +72,8 @@ public class SamlConfig { } }) .assertionConsumerServiceLocation(acsUrl) - .assertingPartyDetails(details -> details.entityId("https://federatest.umbriadigitale.it/gw/metadata") - .singleSignOnServiceLocation("https://federatest.umbriadigitale.it/gw/SSOProxy/SAML2") + .assertingPartyDetails(details -> details.entityId(ipdBaseUrl + "/gw/metadata") + .singleSignOnServiceLocation(ipdBaseUrl + "/gw/SSOProxy/SAML2") .singleSignOnServiceBinding(Saml2MessageBinding.POST) .wantAuthnRequestsSigned(true) .verificationX509Credentials(credentials -> { @@ -133,8 +139,8 @@ public Saml2AuthenticationRequestResolver authenticationRequestResolver(RelyingP authnRequest.setRequestedAuthnContext(buildRequestedAuthnContext()); // Log the SAML AuthnRequest after setting context -// String samlRequest = SamlRequestLogger.convertSAMLObjectToString(authnRequest); - logger.info("SAML Authentication Request."); + String samlRequest = SamlRequestLogger.convertSAMLObjectToString(authnRequest); + logger.info("SAML AuthnRequest after setting context: " + samlRequest); }); return authenticationRequestResolver; @@ -158,7 +164,7 @@ private RequestedAuthnContext buildRequestedAuthnContext() { public PrivateKey readPrivateKey() throws Exception { // Path to your private key PEM file - try (PemReader pemReader = new PemReader(new InputStreamReader(readKey("dev/saml/private-key.pem")))) { + try (PemReader pemReader = new PemReader(new InputStreamReader(readKey(activeProfileFolder + "/saml/private-key.pem")))) { // Read the PEM content byte[] pemContent = pemReader.readPemObject().getContent(); // Decode the PEM content @@ -170,7 +176,7 @@ private RequestedAuthnContext buildRequestedAuthnContext() { } public X509Certificate readCertificate() throws Exception { // Path to your certificate PEM fileFile - try (InputStream inStream = readKey("dev/saml/public-cert.pem")) { + try (InputStream inStream = readKey(activeProfileFolder + "/saml/public-cert.pem")) { CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); return (X509Certificate) certFactory.generateCertificate(inStream); } @@ -178,7 +184,7 @@ private RequestedAuthnContext buildRequestedAuthnContext() { public X509Certificate readIdpCertificate() throws Exception { // Path to your IDP public certificate PEM file - try (InputStream inStream = readKey("dev/saml/idp-certificate.pem")) { + try (InputStream inStream = readKey(activeProfileFolder + "/saml/idp-certificate.pem")) { CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); return (X509Certificate) certFactory.generateCertificate(inStream); } diff --git a/src/main/java/net/gepafin/tendermanagement/config/SamlSuccessHandler.java b/src/main/java/net/gepafin/tendermanagement/config/SamlSuccessHandler.java index 37aec12f..868b0eae 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SamlSuccessHandler.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SamlSuccessHandler.java @@ -45,6 +45,7 @@ public class SamlSuccessHandler implements AuthenticationSuccessHandler { public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException { try { + logger.info("SAML login in Authentication Success Handler"); Saml2Authentication samlAuth = (Saml2Authentication) authentication; Saml2AuthenticatedPrincipal principal = (Saml2AuthenticatedPrincipal) samlAuth.getPrincipal(); diff --git a/src/main/resources/application-production.properties b/src/main/resources/application-production.properties index 8acc1e0c..f4ea18fa 100644 --- a/src/main/resources/application-production.properties +++ b/src/main/resources/application-production.properties @@ -9,4 +9,8 @@ spring.h2.console.enabled=true base-url=http://bandi-api.gepafin.it isVatCheckGloballyDisabled = false -fe.base.url=http://gepafin-production-fe.s3-website.eu-central-1.amazonaws.com \ No newline at end of file +fe.base.url=http://gepafin-production-fe.s3-website.eu-central-1.amazonaws.com + +#SPID configuration +spid.ipd.base.url=https://login.regione.umbria.it +active.profile.folder=production \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 1c16a251..3ce9ed17 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -44,3 +44,7 @@ isVatCheckGloballyDisabled = true vatCheckNewToken: 66026bd891a51044e90e08c4 fe.base.url=http://gepafin-staging-fe.s3-website.eu-central-1.amazonaws.com +#SPID configuration +spid.ipd.base.url=https://federatest.umbriadigitale.it +active.profile.folder=dev + diff --git a/src/main/resources/production/saml/idp-certificate.pem b/src/main/resources/production/saml/idp-certificate.pem new file mode 100644 index 00000000..dd9e7b96 --- /dev/null +++ b/src/main/resources/production/saml/idp-certificate.pem @@ -0,0 +1,3 @@ +-----BEGIN CERTIFICATE----- +MIIHBzCCBe+gAwIBAgIQBa/5uQoACfZc0a+0cFPKaDANBgkqhkiG9w0BAQsFADBwMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMS8w LQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNzdXJhbmNlIFNlcnZlciBDQTAeFw0xNDAyMDMw MDAwMDBaFw0xNzAyMDcxMjAwMDBaMIGRMQswCQYDVQQGEwJJVDEOMAwGA1UECBMFSXRhbHkxEDAO BgNVBAcTB1BlcnVnaWExFzAVBgNVBAoTDlJlZ2lvbmUgVW1icmlhMSkwJwYDVQQLEyBTZXJ2aXpp byBJbmZyYXN0cnV0dHVyZSBEaWdpdGFsaTEcMBoGA1UEAwwTKi5yZWdpb25lLnVtYnJpYS5pdDCC ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALx+hg0/SsF+kpakHw24sO8LFawtMiILsEKS jLbqU8LjUcvDj50CVDa/jz21OwdBfCEB6SBVEKp0a61x5RZFKBUnL795y7Na56VWzqA0kyLg7QNn 73Tu0SJPRF0Hm+2ePLLypU+TkIFfC85GO5iXn82E5rb6XRA8blLj/GauQ0DSHkY3ZTQGGzN3La9a ZJ1Tl80cIATY10iuwQdVkLXRx8VriVrS4jVJOOl8vGJ4VWLVwGYUkhmwvoR/zfeNkSQe7USjHmdf Zm4lLMYZjLM0S2wJMRQbj3MscVBKaXMHc6POqMlKrgO1nRK4/1dRYtnJeMCK/uK/ms/MYpxIX2ZG G/MCAwEAAaOCA3kwggN1MB8GA1UdIwQYMBaAFFFo/5CvAgd1PMzZZWRiohK4WXI7MB0GA1UdDgQW BBShweIeUSOk3EJgXqB9164xrkURDDAxBgNVHREEKjAoghMqLnJlZ2lvbmUudW1icmlhLml0ghFy ZWdpb25lLnVtYnJpYS5pdDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG AQUFBwMCMHUGA1UdHwRuMGwwNKAyoDCGLmh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9zaGEyLWhh LXNlcnZlci1nMS5jcmwwNKAyoDCGLmh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zaGEyLWhhLXNl cnZlci1nMS5jcmwwggHEBgNVHSAEggG7MIIBtzCCAbMGCWCGSAGG/WwBATCCAaQwOgYIKwYBBQUH AgEWLmh0dHA6Ly93d3cuZGlnaWNlcnQuY29tL3NzbC1jcHMtcmVwb3NpdG9yeS5odG0wggFkBggr BgEFBQcCAjCCAVYeggFSAEEAbgB5ACAAdQBzAGUAIABvAGYAIAB0AGgAaQBzACAAQwBlAHIAdABp AGYAaQBjAGEAdABlACAAYwBvAG4AcwB0AGkAdAB1AHQAZQBzACAAYQBjAGMAZQBwAHQAYQBuAGMA ZQAgAG8AZgAgAHQAaABlACAARABpAGcAaQBDAGUAcgB0ACAAQwBQAC8AQwBQAFMAIABhAG4AZAAg AHQAaABlACAAUgBlAGwAeQBpAG4AZwAgAFAAYQByAHQAeQAgAEEAZwByAGUAZQBtAGUAbgB0ACAA dwBoAGkAYwBoACAAbABpAG0AaQB0ACAAbABpAGEAYgBpAGwAaQB0AHkAIABhAG4AZAAgAGEAcgBl ACAAaQBuAGMAbwByAHAAbwByAGEAdABlAGQAIABoAGUAcgBlAGkAbgAgAGIAeQAgAHIAZQBmAGUA cgBlAG4AYwBlAC4wgYMGCCsGAQUFBwEBBHcwdTAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlM aWNlcnQuY29tME0GCCsGAQUFBzAChkFodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNl cnRTSEEySGlnaEFzc3VyYW5jZVNlcnZlckNBLmNydDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEB CwUAA4IBAQBPWrp7uoj9qX8h+7iGwyNOB7274/GDQZSqnk52FTQ3Qi8AzM7YV/tNDZG2j1Ran7vG /q214cqsv/gtyxSBfRR4/WgGCIylw5uZv35FsEC0lyAyPJGLKsZSMALqKkeBGQlzsmkNo7TyZgQV XMzoeuQz2mocC+ShpQjn4Uug/FptmbnYKCiKFShc0IAwAj5+U3kPmOhskml2tj+BTXDKpq4m9onY C8eN928I7tkJPvCYGDwdsBkf3EHyM/AUB4oZ/zcnT/8F7SoRfexmD9Eojslzs+hEMKkKg7M/UxJt ySAVQF/BznGvWiWfZtHrtvBCKgXsvUJ3h/7M/SqtRQnpNZ0C +-----END CERTIFICATE----- diff --git a/src/main/resources/production/saml/private-key.pem b/src/main/resources/production/saml/private-key.pem new file mode 100644 index 00000000..12869e56 --- /dev/null +++ b/src/main/resources/production/saml/private-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCKHE1L4E95N6jG +4bED1vd7c5ZMry6J0qIqojpHAzG1YIEtfL28twxBfN9voNhFL9TD6dGsfWDwYaa7 +LXyMAHLRi7pI+sH852d7sq3xRd1ynKDmt+cU+6kMlDtUPulkbzeU9Z0lGFuS9qJw +CdjYliCuwUxwJsU3tVHTHlV8nAz5RaXw31Gl6u11QpgxLPeFP5AUWHzfduTA2Wr0 +5ePtx5iuMj1oIMv0o50DJaqGmCKtQAtGZMGSKIrtXhLerUAfEteH6M+6POzoKg0F +ZyfLEiuqAE1Ymt16P5PLfTPjRHz4XRBCcd6a+iAAvIpG0yQE9dS7PfNtY1akk51J +La150Ef1AgMBAAECggEAIH3MCX+58rCPekp6VIbsLhThVSUZc78j+5ey0iYEOcF8 +YnEoSg9eSMHR5vcWKiC4k2act1G/zo2KphprZJxuZrHSn3yuyoq+I7HDjjF7iY0j +pWO6b4tNF/J/irBKRCCOGPM3hxSV5pszV9xZMYsQIUzEaNYWK6bymxJV1jz4KGRL +w3nPIpeu8MwMZwOzQwz980bZ2vbr67Ft3GmsflKzM5SesmsW8ZyaYbVfHExvfQxV +nsf9ya0PLQqE9Gi81xY1sVkL3V+niU+AXYZ3w/neuXPz6eaJrxlu4hFdJifWlrQV +vW7mgfOmUuR/bEXr/1c95nZQykobrMqHCRVPpfesQQKBgQDCBrlYKD1XJXfXENnG +32O3TksbxVtL0Eyw1lstp20j6txetHn3F/rx/SFy70J02r2jdFHeP/V1iLrEJ81/ +5QVpsA+Au5Oxwdfee/izUFqhXwSpgvtLoVypBUNcglw/qi2tCKrL10nb0i+bocoD +PGaTIECJ0MWUxTX3SrzqC8XX2QKBgQC2OWw7gGu12eutQBHujTbaZXhjwv2QEBup +UZcVYeVn8KrPrK5621aLgQXUq5Db7GoelB09SXOoqy04WZkYy5XeF+ULRtz0M5ZD +cNgAaQXuuZZdxKWFVXbK1iliGJjcMkd9PEpx5BjM49Gq2r5n3FS5KK9A44iSPMbB +IZoYWsIbfQKBgQCeME08itI4Etw6BAsKEWeDM9oYsjdVAGcGZj3AYxigiANTU2F9 +C5gVY4O56UgNbanfch6tTQga43ciJjFtbJOVL230TvqDmr8dLYX+7Cx4FLgAXEH1 +z4F0bE4XRlFftqe2w7I8rzIQfrVB9g51xPD8UvdLZWMxf/gXvl93klGjQQKBgQCw +JWv5TJdR73jBPZjX50up68JndRrUwq1qjAMm2T3/roX/QCZdfl73dV4kiT/7R1oB +ex2Um8cguW959Cpo7ItPZ/uxXevCZ4eOY6t5IgxpCp9OvwNdkxLE2iagu7Qvzq6K +Ydh4pYxPqr2HkfHSxgpj/e8DI69l5TgfgxLJDhpqpQKBgAgSgck834l8lNZwVPa8 ++Vi9nOtoWy7pyf8pv7sDEKcVkTmUU6+53eZoccW8AUu6ilL1PtrQ7cNPTJcUom80 +IVyJsVTQjDy17mj1DU8Fw15pjFWE4zRfQo9vondblJaxs9aIIG/6x9vDQVjN0hwe +jTOz1k3Du8fEEpKQMgn97J/+ +-----END PRIVATE KEY----- diff --git a/src/main/resources/production/saml/public-cert.pem b/src/main/resources/production/saml/public-cert.pem new file mode 100644 index 00000000..55254d2d --- /dev/null +++ b/src/main/resources/production/saml/public-cert.pem @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIID7TCCAtWgAwIBAgIUQ2G093CKO3nbHlyw68f5998BIjkwDQYJKoZIhvcNAQEL +BQAwgYUxCzAJBgNVBAYTAklUMQ4wDAYDVQQIDAVJdGFseTEQMA4GA1UEBwwHUGVy +dWdpYTEQMA4GA1UECgwHR2VwYWZpbjELMAkGA1UECwwCSVQxEDAOBgNVBAMMB0dl +cGFmaW4xIzAhBgkqhkiG9w0BCQEWFGMubW9yZXR0aUBnZXBhZmluLml0MB4XDTI0 +MTAwMTA5MjIwMloXDTI1MTAwMTA5MjIwMlowgYUxCzAJBgNVBAYTAklUMQ4wDAYD +VQQIDAVJdGFseTEQMA4GA1UEBwwHUGVydWdpYTEQMA4GA1UECgwHR2VwYWZpbjEL +MAkGA1UECwwCSVQxEDAOBgNVBAMMB0dlcGFmaW4xIzAhBgkqhkiG9w0BCQEWFGMu +bW9yZXR0aUBnZXBhZmluLml0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAihxNS+BPeTeoxuGxA9b3e3OWTK8uidKiKqI6RwMxtWCBLXy9vLcMQXzfb6DY +RS/Uw+nRrH1g8GGmuy18jABy0Yu6SPrB/Odne7Kt8UXdcpyg5rfnFPupDJQ7VD7p +ZG83lPWdJRhbkvaicAnY2JYgrsFMcCbFN7VR0x5VfJwM+UWl8N9RpertdUKYMSz3 +hT+QFFh833bkwNlq9OXj7ceYrjI9aCDL9KOdAyWqhpgirUALRmTBkiiK7V4S3q1A +HxLXh+jPujzs6CoNBWcnyxIrqgBNWJrdej+Ty30z40R8+F0QQnHemvogALyKRtMk +BPXUuz3zbWNWpJOdSS2tedBH9QIDAQABo1MwUTAdBgNVHQ4EFgQUQ+GP6sby5ZQX +KTgq0/MsCWfdcHcwHwYDVR0jBBgwFoAUQ+GP6sby5ZQXKTgq0/MsCWfdcHcwDwYD +VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAWnzvIOhK4Z/GQA2H0jb+ +tkpPiwXucybEEOwQyb6+ErNGLjM7aj/HXJv70zibchmuPN5yd6C9dmrlajf/qLFz +T+Dfy6zl3r0mNErcT/bgaJzVA87u0z2/DRP77XqwV23zDGK56bp8G2C1nZGq6x2k +zswESJYBquXtBWNEJnreDKOLic9AucSyf8T0C9aeWhC8L0Hz4Bd825J2n54L4YZD +ShkCDSdCOZVdaZNikRv+KyD1SI6HM3KeUNNknW6z7g2jb5PG4dn5U9+lpzOsfoYD +QEBrNG8qFZ7k9DYzh8l1dTo9izSNmudaiyjhgFw+5DZ0pcrhti6h3hnPPysSA8q/ +Mg== +-----END CERTIFICATE----- From 3fe00993c34ee926b72ca7991eb37ab330441db7 Mon Sep 17 00:00:00 2001 From: nisha Date: Tue, 1 Oct 2024 17:27:43 +0530 Subject: [PATCH 53/58] Added field required field in call --- .../gepafin/tendermanagement/dao/CallDao.java | 23 ++++++++++++ .../tendermanagement/entities/CallEntity.java | 16 +++++++++ .../model/request/CreateCallRequestStep1.java | 12 +++++++ .../response/CallDetailsResponseBean.java | 11 ++++++ .../model/response/CallResponse.java | 11 ++++++ .../impl/CallValidatorServiceImpl.java | 5 +++ .../tendermanagement/util/DateTimeUtil.java | 36 ++++++++++++++++++- .../db/changelog/db.changelog-1.0.0.xml | 9 +++++ 8 files changed, 122 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java index 1b3f60d0..a0a5a110 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java @@ -1,5 +1,6 @@ package net.gepafin.tendermanagement.dao; +import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.ArrayList; @@ -10,6 +11,7 @@ import java.util.stream.Collectors; import net.gepafin.tendermanagement.enums.DocumentSourceTypeEnum; import net.gepafin.tendermanagement.model.response.*; import net.gepafin.tendermanagement.service.*; +import net.gepafin.tendermanagement.util.DateTimeUtil; import net.gepafin.tendermanagement.util.Utils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -124,6 +126,17 @@ public class CallDao { callEntity.setConfidi(createCallRequest.getConfidi()); } callEntity.setDocumentationRequested(createCallRequest.getDocumentationRequested()); + if (createCallRequest.getAmountMin().compareTo(BigDecimal.ZERO) < 0) { + throw new CustomValidationException(Status.VALIDATION_ERROR,Translator.toLocale(GepafinConstant.AMOUNT_GREATER_THAN_ZERO_MSG)); + } + callEntity.setAmountMin(createCallRequest.getAmountMin()); + if(createCallRequest.getEmail()==null || Boolean.FALSE.equals(Utils.isValidEmail(createCallRequest.getEmail()))){ + throw new CustomValidationException(Status.VALIDATION_ERROR,Translator.toLocale(GepafinConstant.VALIDATION_EMAIL,createCallRequest.getEmail())); + } + callEntity.setEmail(createCallRequest.getEmail()); + callEntity.setPhoneNumber(createCallRequest.getPhoneNumber()); + callEntity.setStartTime(DateTimeUtil.parseTime(createCallRequest.getStartTime())); + callEntity.setEndTime(DateTimeUtil.parseTime(createCallRequest.getEndTime())); callEntity = callRepository.save(callEntity); return callEntity; } @@ -259,6 +272,11 @@ public class CallDao { createCallResponseBean.setDocumentationRequested(callEntity.getDocumentationRequested()); createCallResponseBean.setPriorityArea(callEntity.getPriorityArea()); createCallResponseBean.setConfidi(callEntity.getConfidi()); + createCallResponseBean.setAmountMin(callEntity.getAmountMin()); + createCallResponseBean.setPhoneNumber(callEntity.getPhoneNumber()); + createCallResponseBean.setEndTime(callEntity.getEndTime()); + createCallResponseBean.setStartTime(callEntity.getStartTime()); + createCallResponseBean.setEmail(callEntity.getEmail()); createCallResponseBean.setCreatedDate(callEntity.getCreatedDate()); createCallResponseBean.setUpdatedDate(callEntity.getUpdatedDate()); return createCallResponseBean; @@ -531,6 +549,11 @@ public class CallDao { callDetailsResponseBean.setThreshold(callEntity.getThreshold()); callDetailsResponseBean.setDocumentationRequested(callEntity.getDocumentationRequested()); callDetailsResponseBean.setPriorityArea(callEntity.getPriorityArea()); + callDetailsResponseBean.setAmountMin(callEntity.getAmountMin()); + callDetailsResponseBean.setEmail(callEntity.getEmail()); + callDetailsResponseBean.setEndTime(callEntity.getEndTime()); + callDetailsResponseBean.setStartTime(callEntity.getStartTime()); + callDetailsResponseBean.setPhoneNumber(callEntity.getPhoneNumber()); callDetailsResponseBean.setCreatedDate(callEntity.getCreatedDate()); callDetailsResponseBean.setUpdatedDate(callEntity.getUpdatedDate()); return callDetailsResponseBean; diff --git a/src/main/java/net/gepafin/tendermanagement/entities/CallEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/CallEntity.java index 02c53fca..f0bb3896 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/CallEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/CallEntity.java @@ -8,6 +8,7 @@ import lombok.Builder; import java.math.BigDecimal; import java.time.LocalDateTime; +import java.time.LocalTime; @Entity @Table(name = "CALL") @@ -68,5 +69,20 @@ public class CallEntity extends BaseEntity { @Column(name="FINAL_FORM") private Long finalForm; + + @Column(name = "AMOUNT_MIN") + private BigDecimal amountMin; + + @Column(name="EMAIL") + private String email; + + @Column(name = "PHONE_NUMBER") + private String phoneNumber; + + @Column(name = "START_TIME") + private LocalTime startTime; + + @Column(name = "END_TIME") + private LocalTime endTime; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/CreateCallRequestStep1.java b/src/main/java/net/gepafin/tendermanagement/model/request/CreateCallRequestStep1.java index bfa0e84d..bdc0d015 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/request/CreateCallRequestStep1.java +++ b/src/main/java/net/gepafin/tendermanagement/model/request/CreateCallRequestStep1.java @@ -2,7 +2,9 @@ package net.gepafin.tendermanagement.model.request; import java.math.BigDecimal; import java.time.LocalDateTime; +import java.time.LocalTime; import java.util.List; + import lombok.Data; @Data @@ -26,6 +28,16 @@ public class CreateCallRequestStep1 { private String documentationRequested; + private BigDecimal amountMin; + + private String email; + + private String phoneNumber; + + private String startTime; + + private String endTime; + private Boolean confidi; private List faq; diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/CallDetailsResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/CallDetailsResponseBean.java index a7bf60b7..51479254 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/CallDetailsResponseBean.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/CallDetailsResponseBean.java @@ -5,6 +5,7 @@ import net.gepafin.tendermanagement.enums.CallStatusEnum; import java.math.BigDecimal; import java.time.LocalDateTime; +import java.time.LocalTime; import java.util.List; @Data public class CallDetailsResponseBean { @@ -37,6 +38,16 @@ public class CallDetailsResponseBean { private String documentationRequested; + private BigDecimal amountMin; + + private String email; + + private String phoneNumber; + + private LocalTime startTime; + + private LocalTime endTime; + private LocalDateTime createdDate; private LocalDateTime updatedDate; diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/CallResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/CallResponse.java index f8fa4908..ed4a0206 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/CallResponse.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/CallResponse.java @@ -2,6 +2,7 @@ package net.gepafin.tendermanagement.model.response; import java.math.BigDecimal; import java.time.LocalDateTime; +import java.time.LocalTime; import java.util.List; import lombok.Data; @@ -40,6 +41,16 @@ public class CallResponse { private Boolean confidi; + private BigDecimal amountMin; + + private String email; + + private String phoneNumber; + + private LocalTime startTime; + + private LocalTime endTime; + private LocalDateTime createdDate; private LocalDateTime updatedDate; diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/CallValidatorServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/CallValidatorServiceImpl.java index 715242f5..aa2df691 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/CallValidatorServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/CallValidatorServiceImpl.java @@ -10,6 +10,7 @@ import net.gepafin.tendermanagement.model.response.CallResponse; import net.gepafin.tendermanagement.model.response.FlowResponseBean; import net.gepafin.tendermanagement.model.response.FormResponseBean; import net.gepafin.tendermanagement.util.FieldValidator; +import net.gepafin.tendermanagement.util.Utils; import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; import net.gepafin.tendermanagement.web.rest.api.errors.Status; @@ -28,6 +29,10 @@ public class CallValidatorServiceImpl { .notNull(response.getAmount(), "amount") .notNull(response.getAmountMax(), "amountMax") .notNull(response.getThreshold(), "threshold") + .notNull(response.getEmail(),"email") +// .notNull(response.getAmountMin(),"amountMin") +// .notNull(response.getStartTime(),"startTime") +// .notNull(response.getEndTime(),"endTime") .notNull(response.getDocumentationRequested(), "documentationRequested") .notEmpty(response.getAimedTo(), "aimedTo") .notEmpty(response.getCriteria(), "criteria") diff --git a/src/main/java/net/gepafin/tendermanagement/util/DateTimeUtil.java b/src/main/java/net/gepafin/tendermanagement/util/DateTimeUtil.java index ab67ccdd..4bfe0998 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/DateTimeUtil.java +++ b/src/main/java/net/gepafin/tendermanagement/util/DateTimeUtil.java @@ -1,16 +1,29 @@ package net.gepafin.tendermanagement.util; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; +import net.gepafin.tendermanagement.web.rest.api.errors.Status; import org.springframework.stereotype.Component; +import java.io.IOException; import java.time.LocalDateTime; +import java.time.LocalTime; import java.time.ZoneId; import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; import java.util.Calendar; import java.util.Date; +import java.util.regex.Pattern; @Component public class DateTimeUtil { - + + private static final Pattern TIME_PATTERN = Pattern.compile( + "^((([01]?\\d|2[0-3]):([0-5]\\d)(:[0-5]\\d)?(\\s?[AP]M)?)|((0?[1-9]|1[0-2]):([0-5]\\d)(:[0-5]\\d)?\\s?[AP]M))$"); + public static LocalDateTime DateServerToUTC(LocalDateTime systemDate) { @@ -50,4 +63,25 @@ public class DateTimeUtil { .from(localDateTime.atZone(ZoneId.systemDefault()) .toInstant()); } + + public static LocalTime parseTime(String timeString) throws DateTimeParseException { + DateTimeFormatter formatter; + + if (!TIME_PATTERN.matcher(timeString).matches()) { + throw new CustomValidationException(Status.BAD_REQUEST,"Invalid time format: " + timeString); + } + // Try to parse using default formats if no format is provided + String[] defaultFormats = {"HH:mm:ss", "HH:mm", "HH:mm:ss a", "hh:mm a"}; + for (String defaultFormat : defaultFormats) { + formatter = DateTimeFormatter.ofPattern(defaultFormat); + try { + return LocalTime.parse(timeString, formatter); + } catch (DateTimeParseException e) { + // Continue to the next format + } + } + + // If all parsing attempts fail, throw an exception + throw new CustomValidationException(Status.BAD_REQUEST,"Failed to parse time: " + timeString); + } } diff --git a/src/main/resources/db/changelog/db.changelog-1.0.0.xml b/src/main/resources/db/changelog/db.changelog-1.0.0.xml index 1fe6a617..449727ce 100644 --- a/src/main/resources/db/changelog/db.changelog-1.0.0.xml +++ b/src/main/resources/db/changelog/db.changelog-1.0.0.xml @@ -824,5 +824,14 @@ + + + + + + + + + From 7bde0e91e77a73595ee8c6743ff2286e8c8244bf Mon Sep 17 00:00:00 2001 From: nisha Date: Tue, 1 Oct 2024 18:05:35 +0530 Subject: [PATCH 54/58] Applied validation for few fields in call --- .../net/gepafin/tendermanagement/dao/CallDao.java | 14 +++++++++++++- .../model/request/UpdateCallRequestStep1.java | 11 +++++++++++ .../service/impl/CallValidatorServiceImpl.java | 6 +++--- .../tendermanagement/util/DateTimeUtil.java | 4 +++- 4 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java index a0a5a110..fca314ed 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java @@ -126,7 +126,7 @@ public class CallDao { callEntity.setConfidi(createCallRequest.getConfidi()); } callEntity.setDocumentationRequested(createCallRequest.getDocumentationRequested()); - if (createCallRequest.getAmountMin().compareTo(BigDecimal.ZERO) < 0) { + if (createCallRequest.getAmountMin() != null && createCallRequest.getAmountMin().compareTo(BigDecimal.ZERO) < 0) { throw new CustomValidationException(Status.VALIDATION_ERROR,Translator.toLocale(GepafinConstant.AMOUNT_GREATER_THAN_ZERO_MSG)); } callEntity.setAmountMin(createCallRequest.getAmountMin()); @@ -474,6 +474,18 @@ public class CallDao { setIfUpdated(callEntity::getAmountMax, callEntity::setAmountMax, updateCallRequest.getAmountMax()); setIfUpdated(callEntity::getDocumentationRequested, callEntity::setDocumentationRequested, updateCallRequest.getDocumentationRequested()); + + if (updateCallRequest.getAmountMin() != null && updateCallRequest.getAmountMin().compareTo(BigDecimal.ZERO) < 0) { + throw new CustomValidationException(Status.VALIDATION_ERROR,Translator.toLocale(GepafinConstant.AMOUNT_GREATER_THAN_ZERO_MSG)); + } + if(updateCallRequest.getEmail()==null || Boolean.FALSE.equals(Utils.isValidEmail(updateCallRequest.getEmail()))){ + throw new CustomValidationException(Status.VALIDATION_ERROR,Translator.toLocale(GepafinConstant.VALIDATION_EMAIL,updateCallRequest.getEmail())); + } + setIfUpdated(callEntity::getAmountMin, callEntity::setAmountMin, updateCallRequest.getAmountMin()); + setIfUpdated(callEntity::getEmail, callEntity::setEmail, updateCallRequest.getEmail()); + setIfUpdated(callEntity::getPhoneNumber, callEntity::setPhoneNumber, updateCallRequest.getPhoneNumber()); + setIfUpdated(callEntity::getStartTime, callEntity::setStartTime, DateTimeUtil.parseTime(updateCallRequest.getStartTime())); + setIfUpdated(callEntity::getEndTime, callEntity::setEndTime, DateTimeUtil.parseTime(updateCallRequest.getEndTime())); setIfUpdated(callEntity::getConfidi, callEntity::setConfidi, updateCallRequest.getConfidi()); updateLookUpData(callEntity, updateCallRequest.getAimedTo(), LookUpDataTypeEnum.AIMED_TO); updateFaq(updateCallRequest.getFaq(), callEntity, userEntity, LookUpDataTypeEnum.FAQ); diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/UpdateCallRequestStep1.java b/src/main/java/net/gepafin/tendermanagement/model/request/UpdateCallRequestStep1.java index 4d4de6e9..e57f8715 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/request/UpdateCallRequestStep1.java +++ b/src/main/java/net/gepafin/tendermanagement/model/request/UpdateCallRequestStep1.java @@ -2,6 +2,7 @@ package net.gepafin.tendermanagement.model.request; import java.math.BigDecimal; import java.time.LocalDateTime; +import java.time.LocalTime; import java.util.List; import lombok.Data; @@ -25,6 +26,16 @@ public class UpdateCallRequestStep1 { private String documentationRequested; + private BigDecimal amountMin; + + private String email; + + private String phoneNumber; + + private String startTime; + + private String endTime; + private Boolean confidi; private List faq; diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/CallValidatorServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/CallValidatorServiceImpl.java index aa2df691..3c7091cf 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/CallValidatorServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/CallValidatorServiceImpl.java @@ -30,9 +30,9 @@ public class CallValidatorServiceImpl { .notNull(response.getAmountMax(), "amountMax") .notNull(response.getThreshold(), "threshold") .notNull(response.getEmail(),"email") -// .notNull(response.getAmountMin(),"amountMin") -// .notNull(response.getStartTime(),"startTime") -// .notNull(response.getEndTime(),"endTime") + .notNull(response.getAmountMin(),"amountMin") + .notNull(response.getStartTime(),"startTime") + .notNull(response.getEndTime(),"endTime") .notNull(response.getDocumentationRequested(), "documentationRequested") .notEmpty(response.getAimedTo(), "aimedTo") .notEmpty(response.getCriteria(), "criteria") diff --git a/src/main/java/net/gepafin/tendermanagement/util/DateTimeUtil.java b/src/main/java/net/gepafin/tendermanagement/util/DateTimeUtil.java index 4bfe0998..63ed91a5 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/DateTimeUtil.java +++ b/src/main/java/net/gepafin/tendermanagement/util/DateTimeUtil.java @@ -66,7 +66,9 @@ public class DateTimeUtil { public static LocalTime parseTime(String timeString) throws DateTimeParseException { DateTimeFormatter formatter; - + if(timeString==null) { + return null; + } if (!TIME_PATTERN.matcher(timeString).matches()) { throw new CustomValidationException(Status.BAD_REQUEST,"Invalid time format: " + timeString); } From e335da322584e5b7ffe7c48d8587fb88ee5eb7b3 Mon Sep 17 00:00:00 2001 From: harish Date: Tue, 1 Oct 2024 19:15:22 +0530 Subject: [PATCH 55/58] Allowing company to connect to multiple users --- .../constants/GepafinConstant.java | 2 +- .../tendermanagement/dao/CompanyDao.java | 24 +++++++++++++++---- .../repositories/CompanyRepository.java | 1 + src/main/resources/message_en.properties | 1 + src/main/resources/message_it.properties | 1 + 5 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index 06e0927c..3ebf7e5f 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -178,5 +178,5 @@ public class GepafinConstant { public static final String INVALID_EMAIL = "invalid.email"; public static final String UNAUTHORIZED = "UNAUTHORIZED"; public static final String COMPANY_ID_MANDATORY = "company.id.mandatory"; - + public static final String USER_ALREADY_CONNECTED_TO_COMPANY = "user.already.connected.to.company"; } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java b/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java index 5aa03a64..219b1579 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java @@ -34,13 +34,27 @@ public class CompanyDao { private UserWithCompanyRepository userWithCompanyRepository; public CompanyResponse createCompany(UserEntity userEntity, CompanyRequest companyRequest) { - validateCompany(companyRequest); - CompanyEntity companyEntity = convertCompanyRequestToCompanyEntity(companyRequest); - companyRepository.save(companyEntity); - createUserWithCompanyRelation(userEntity, companyEntity); - return convertCompanyEntityToCompanyResponse(companyEntity); + CompanyEntity existingCompany = companyRepository.findByVatNumber(companyRequest.getVatNumber()); + if (existingCompany != null) { + UserWithCompanyEntity existingRelation = userWithCompanyRepository.findByUserIdAndCompanyId(userEntity.getId(), existingCompany.getId()) + .orElse(null); + if (existingRelation == null) { + createUserWithCompanyRelation(userEntity, existingCompany); + } else { + throw new CustomValidationException(Status.VALIDATION_ERROR, + Translator.toLocale(GepafinConstant.USER_ALREADY_CONNECTED_TO_COMPANY)); + } + return convertCompanyEntityToCompanyResponse(existingCompany); + } else { + validateCompany(companyRequest); + CompanyEntity companyEntity = convertCompanyRequestToCompanyEntity(companyRequest); + companyRepository.save(companyEntity); + createUserWithCompanyRelation(userEntity, companyEntity); + return convertCompanyEntityToCompanyResponse(companyEntity); + } } + private void validateCompany(CompanyRequest companyRequest) { if (Boolean.FALSE.equals(StringUtils.isEmpty(companyRequest.getEmail())) diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/CompanyRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/CompanyRepository.java index 9dc3a3a5..9206826f 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/CompanyRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/CompanyRepository.java @@ -13,5 +13,6 @@ public interface CompanyRepository extends JpaRepository { List findByIdIn(List companyIds); Boolean existsByVatNumber(String vatNumber); + CompanyEntity findByVatNumber(String vatNumber); } diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index 5ef423b2..d70c97f4 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -205,3 +205,4 @@ vatnumber.mandatory=VatNumber is mandatory. vatnumber.already.exists=VatNumber already exists. invalid.email=Invalid email. company.id.mandatory=Company id is mandatory. +user.already.connected.to.company=The user is already connected to this company. diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index 273cdef9..00e8dcfc 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -198,3 +198,4 @@ vatnumber.mandatory=Il numero di partita IVA vatnumber.already.exists=Il numero di partita IVA esiste già. invalid.email=Email non valida. company.id.mandatory=L'ID dell'azienda è obbligatorio. +user.already.connected.to.company=L'utente è già collegato a questa azienda. From aab64f45525d5326f2967599ed545840918a954f Mon Sep 17 00:00:00 2001 From: nishainnogent Date: Thu, 3 Oct 2024 14:40:51 +0530 Subject: [PATCH 56/58] fixed bug for update published call --- src/main/java/net/gepafin/tendermanagement/dao/CallDao.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java index fca314ed..97d0e4b4 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java @@ -478,7 +478,7 @@ public class CallDao { if (updateCallRequest.getAmountMin() != null && updateCallRequest.getAmountMin().compareTo(BigDecimal.ZERO) < 0) { throw new CustomValidationException(Status.VALIDATION_ERROR,Translator.toLocale(GepafinConstant.AMOUNT_GREATER_THAN_ZERO_MSG)); } - if(updateCallRequest.getEmail()==null || Boolean.FALSE.equals(Utils.isValidEmail(updateCallRequest.getEmail()))){ + if(updateCallRequest.getEmail()==null && Boolean.FALSE.equals(Utils.isValidEmail(updateCallRequest.getEmail()))){ throw new CustomValidationException(Status.VALIDATION_ERROR,Translator.toLocale(GepafinConstant.VALIDATION_EMAIL,updateCallRequest.getEmail())); } setIfUpdated(callEntity::getAmountMin, callEntity::setAmountMin, updateCallRequest.getAmountMin()); From f6beb55fc7c8c0480d26b5d7d1b590f49510713d Mon Sep 17 00:00:00 2001 From: nishainnogent Date: Thu, 3 Oct 2024 14:44:57 +0530 Subject: [PATCH 57/58] updated code --- src/main/java/net/gepafin/tendermanagement/dao/CallDao.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java index 97d0e4b4..e214e562 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java @@ -130,7 +130,7 @@ public class CallDao { throw new CustomValidationException(Status.VALIDATION_ERROR,Translator.toLocale(GepafinConstant.AMOUNT_GREATER_THAN_ZERO_MSG)); } callEntity.setAmountMin(createCallRequest.getAmountMin()); - if(createCallRequest.getEmail()==null || Boolean.FALSE.equals(Utils.isValidEmail(createCallRequest.getEmail()))){ + if(createCallRequest.getEmail()!=null && Boolean.FALSE.equals(Utils.isValidEmail(createCallRequest.getEmail()))){ throw new CustomValidationException(Status.VALIDATION_ERROR,Translator.toLocale(GepafinConstant.VALIDATION_EMAIL,createCallRequest.getEmail())); } callEntity.setEmail(createCallRequest.getEmail()); @@ -478,7 +478,7 @@ public class CallDao { if (updateCallRequest.getAmountMin() != null && updateCallRequest.getAmountMin().compareTo(BigDecimal.ZERO) < 0) { throw new CustomValidationException(Status.VALIDATION_ERROR,Translator.toLocale(GepafinConstant.AMOUNT_GREATER_THAN_ZERO_MSG)); } - if(updateCallRequest.getEmail()==null && Boolean.FALSE.equals(Utils.isValidEmail(updateCallRequest.getEmail()))){ + if(updateCallRequest.getEmail()!=null && Boolean.FALSE.equals(Utils.isValidEmail(updateCallRequest.getEmail()))){ throw new CustomValidationException(Status.VALIDATION_ERROR,Translator.toLocale(GepafinConstant.VALIDATION_EMAIL,updateCallRequest.getEmail())); } setIfUpdated(callEntity::getAmountMin, callEntity::setAmountMin, updateCallRequest.getAmountMin()); From a2055e4474bc80ba1995a1b9adb59e7cc580ad9c Mon Sep 17 00:00:00 2001 From: nisha Date: Thu, 3 Oct 2024 14:53:17 +0530 Subject: [PATCH 58/58] Done ticket --- .../db/changelog/db.changelog-1.0.0.xml | 10 +- .../updated_form_field_data_03-10-2024.sql | 99 +++++++++++++++++++ 2 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 src/main/resources/db/dump/updated_form_field_data_03-10-2024.sql diff --git a/src/main/resources/db/changelog/db.changelog-1.0.0.xml b/src/main/resources/db/changelog/db.changelog-1.0.0.xml index 449727ce..1575f0bb 100644 --- a/src/main/resources/db/changelog/db.changelog-1.0.0.xml +++ b/src/main/resources/db/changelog/db.changelog-1.0.0.xml @@ -833,5 +833,13 @@ - + + + TRUNCATE TABLE FORM_FIELD RESTART IDENTITY; + + + + + diff --git a/src/main/resources/db/dump/updated_form_field_data_03-10-2024.sql b/src/main/resources/db/dump/updated_form_field_data_03-10-2024.sql new file mode 100644 index 00000000..21a5d11f --- /dev/null +++ b/src/main/resources/db/dump/updated_form_field_data_03-10-2024.sql @@ -0,0 +1,99 @@ +INSERT INTO FORM_FIELD (SORT_ORDER, NAME, LABEL, DESCRIPTION, SETTINGS, VALIDATORS, CREATED_DATE, UPDATED_DATE) +VALUES +(1, 'textinput', 'Testo Breve', 'Per risposte concise (nomi, titoli, brevi descrizioni)', + '[{"name": "label", "value": "Testo Breve"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": false, "custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(2, 'textarea', 'Testo Lungo', 'Campo di testo esteso per paragrafi, descrizioni, proposte', + '[{"name": "label", "value": "Testo Lungo"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": false, "custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(3, 'wysiwyg', 'Campo di Testo Formattato', 'Editor avanzato per testo con formattazione', + '[{"name": "label", "value": "Testo Formattato"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": false, "custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(4, 'numberinput', 'Campo Numerico', 'Per l''inserimento di valori numerici (quantità, importi, percentuali)', + '[{"name": "label", "value": "Numero"}, {"name": "placeholder", "value": "0"}, {"name": "step", "value": "0"}]', + '{"isRequired": false, "custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(5, 'radio', 'Scelta Singola', 'Gruppo di opzioni per selezione singola', + '[{"name": "label", "value": "Scelta Singola"}, {"name": "options", "value": "[]"}]', + '{"isRequired": false, "custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(6, 'select', 'Menu a Tendina', 'Selezione da opzioni predefinite', + '[{"name": "label", "value": "Menu a Tendina"}, {"name": "options", "value": "[]"}]', + '{"isRequired": false,"custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(7, 'checkboxes', 'Scelta Multipla', 'Gruppo di opzioni per selezione singola o multipla', + '[{"name": "label", "value": "Scelta Multipla"}, {"name": "options", "value": "[]"}]', + '{"isRequired": false,"custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(8, 'switch', 'Casella di Spunta', 'Per selezioni binarie, accettazioni, conferme', + '[{"name": "label", "value": "Casella di Spunta"}]', + '{"isRequired": false, "custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(9, 'datepicker', 'Data', 'Selezione di data', + '[{"name": "label", "value": "Data"}]', + '{"isRequired": false, "custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(10, 'fileupload', 'Caricamento File', 'Per l''upload di documenti o immagini', + '[{"name": "label", "value": "Caricamento File"}, {"name": "mime", "value": "[]"}]', + '{"isRequired": false, "maxSize": 100000, "custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(11, 'textinput', 'Campo Partita IVA', 'Specifico per l''inserimento del numero di Partita IVA', + '[{"name": "label", "value": "Partita IVA"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": true,"custom": "isPIVA"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(12, 'textinput', 'Campo Codice Fiscale', 'Specifico per l''inserimento del Codice Fiscale italiano per persone fisiche e giuridiche', + '[{"name": "label", "value": "Codice Fiscale"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": true, "custom": "isCodiceFiscale"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(13, 'numberinput', 'Campo CAP', 'Per l''inserimento del Codice di Avviamento Postale', + '[{"name": "label", "value": "CAP"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": true,"custom": "isCAP"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(14, 'textinput', 'Campo IBAN', 'Per l''inserimento del codice IBAN', + '[{"name": "label", "value": "IBAN"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": true,"custom": "isIBAN"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(15, 'textinput', 'Campo Email', 'Per l''inserimento di indirizzi email standard (non PEC)', + '[{"name": "label", "value": "Campo Email"}, {"name": "placeholder", "value": "nome@esempio.it"}]', + '{"isRequired": false, "custom": "isEmail"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(16, 'textinput', 'Campo PEC', 'Specifico per l''inserimento di un indirizzo di Posta Elettronica Certificata', + '[{"name": "label", "value": "Campo PEC"}, {"name": "placeholder", "value": "nome@pec.it"}]', + '{"isRequired": false, "custom": "isEmailPEC"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(17, 'textinput', 'Campo URL', 'Per l''inserimento di indirizzi web', + '[{"name": "label", "value": "Indirizzo URL"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": false, "custom": "isUrl"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(18, 'textinput', 'Marca da bollo', 'Per inserire codice di marca da bollo', + '[{"name": "label", "value": "Marca da bollo"}, {"name": "placeholder", "value": "Numero identificativo"}]', + '{"isRequired": false, "custom": "isMarcaDaBollo"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(19, 'paragraph', 'Paragrafo', 'Semplice testo formattato', + '[{"name": "text", "value": ""}]', '{}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(20, 'table', 'Tabella', 'Tabella', + '[{"name": "label", "value": "Tabella"}, {"name": "table_columns", "value": {}}]', '{}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);