From e09f61f918680034f663f2c368ab1a7bc1a1558a Mon Sep 17 00:00:00 2001 From: harish Date: Wed, 14 Aug 2024 15:31:00 +0530 Subject: [PATCH 1/9] Done ticket GEPAFINBE-3 --- pom.xml | 80 ++++++++-- .../TendermanagementApplication.java | 9 ++ .../config/MessageSourceConfig.java | 17 +++ .../tendermanagement/config/SchemaInit.java | 70 +++++++++ .../tendermanagement/config/Translator.java | 25 ++++ .../constants/GepafinConstant.java | 27 ++++ .../tendermanagement/dao/RegionDao.java | 109 ++++++++++++++ .../gepafin/tendermanagement/dao/RoleDao.java | 80 ++++++++++ .../gepafin/tendermanagement/dao/UserDao.java | 99 +++++++++++++ .../tendermanagement/entities/BaseEntity.java | 35 +++++ .../entities/RegionEntity.java | 60 ++++++++ .../tendermanagement/entities/RoleEntity.java | 26 ++++ .../tendermanagement/entities/UserEntity.java | 77 ++++++++++ .../gepafin/tendermanagement/model/User.java | 38 ----- .../model/request/RegionReq.java | 39 +++++ .../model/request/RoleReq.java | 27 ++++ .../model/request/UpdateRegionReq.java | 35 +++++ .../model/request/UpdateUserReq.java | 21 +++ .../model/request/UserReq.java | 44 ++++++ .../model/response/RegionResponseBean.java | 28 ++++ .../model/response/RoleResponseBean.java | 19 +++ .../model/response/UserResponseBean.java | 41 ++++++ .../tendermanagement/model/util/Response.java | 29 ++++ .../repositories/RegionRepository.java | 9 ++ .../repositories/RoleRepository.java | 9 ++ .../repositories/UserRepository.java | 9 ++ .../service/RegionService.java | 22 +++ .../tendermanagement/service/RoleService.java | 19 +++ .../tendermanagement/service/UserService.java | 12 ++ .../service/impl/RegionServiceImpl.java | 43 ++++++ .../service/impl/RoleServiceImpl.java | 44 ++++++ .../service/impl/UserServiceImpl.java | 38 +++++ .../tendermanagement/util/DateTimeUtil.java | 53 +++++++ .../tendermanagement/util/ObjectUtils.java | 20 +++ .../gepafin/tendermanagement/util/Utils.java | 49 +++++++ .../web/rest/api/RegionApi.java | 91 ++++++++++++ .../web/rest/api/RoleApi.java | 93 ++++++++++++ .../web/rest/api/UserApi.java | 94 +++++++++++- .../api/errors/CustomValidationException.java | 16 ++ .../web/rest/api/errors/ErrorConstants.java | 28 ++++ .../api/errors/ResourceNotFoundException.java | 23 +++ .../web/rest/api/errors/Status.java | 16 ++ .../rest/api/impl/RegionApiController.java | 79 ++++++++++ .../web/rest/api/impl/RoleApiController.java | 75 ++++++++++ .../web/rest/api/impl/UserApiController.java | 70 ++++++++- src/main/resources/application.properties | 25 +++- .../db/changelog/db.changelog-1.0.0.xml | 137 ++++++++++++++++++ .../db/changelog/db.changelog-master.xml | 8 + src/main/resources/message_en.properties | 29 ++++ src/main/resources/message_it.properties | 28 ++++ target/classes/application.properties | 3 - 51 files changed, 2107 insertions(+), 70 deletions(-) create mode 100644 src/main/java/net/gepafin/tendermanagement/config/MessageSourceConfig.java create mode 100644 src/main/java/net/gepafin/tendermanagement/config/SchemaInit.java create mode 100644 src/main/java/net/gepafin/tendermanagement/config/Translator.java create mode 100644 src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java create mode 100644 src/main/java/net/gepafin/tendermanagement/dao/RegionDao.java create mode 100644 src/main/java/net/gepafin/tendermanagement/dao/RoleDao.java create mode 100644 src/main/java/net/gepafin/tendermanagement/dao/UserDao.java create mode 100644 src/main/java/net/gepafin/tendermanagement/entities/BaseEntity.java create mode 100644 src/main/java/net/gepafin/tendermanagement/entities/RegionEntity.java create mode 100644 src/main/java/net/gepafin/tendermanagement/entities/RoleEntity.java create mode 100644 src/main/java/net/gepafin/tendermanagement/entities/UserEntity.java delete mode 100644 src/main/java/net/gepafin/tendermanagement/model/User.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/request/RegionReq.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/request/RoleReq.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/request/UpdateRegionReq.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/request/UpdateUserReq.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/request/UserReq.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/response/RegionResponseBean.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/response/RoleResponseBean.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/response/UserResponseBean.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/util/Response.java create mode 100644 src/main/java/net/gepafin/tendermanagement/repositories/RegionRepository.java create mode 100644 src/main/java/net/gepafin/tendermanagement/repositories/RoleRepository.java create mode 100644 src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java create mode 100644 src/main/java/net/gepafin/tendermanagement/service/RegionService.java create mode 100644 src/main/java/net/gepafin/tendermanagement/service/RoleService.java create mode 100644 src/main/java/net/gepafin/tendermanagement/service/UserService.java create mode 100644 src/main/java/net/gepafin/tendermanagement/service/impl/RegionServiceImpl.java create mode 100644 src/main/java/net/gepafin/tendermanagement/service/impl/RoleServiceImpl.java create mode 100644 src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java create mode 100644 src/main/java/net/gepafin/tendermanagement/util/DateTimeUtil.java create mode 100644 src/main/java/net/gepafin/tendermanagement/util/ObjectUtils.java create mode 100644 src/main/java/net/gepafin/tendermanagement/util/Utils.java create mode 100644 src/main/java/net/gepafin/tendermanagement/web/rest/api/RegionApi.java create mode 100644 src/main/java/net/gepafin/tendermanagement/web/rest/api/RoleApi.java create mode 100644 src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/CustomValidationException.java create mode 100644 src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/ErrorConstants.java create mode 100644 src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/ResourceNotFoundException.java create mode 100644 src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/Status.java create mode 100644 src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/RegionApiController.java create mode 100644 src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/RoleApiController.java create mode 100644 src/main/resources/db/changelog/db.changelog-1.0.0.xml create mode 100644 src/main/resources/db/changelog/db.changelog-master.xml create mode 100644 src/main/resources/message_en.properties create mode 100644 src/main/resources/message_it.properties delete mode 100644 target/classes/application.properties diff --git a/pom.xml b/pom.xml index 6142921d..1572627b 100644 --- a/pom.xml +++ b/pom.xml @@ -1,6 +1,5 @@ - + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 org.springframework.boot @@ -13,28 +12,69 @@ 0.0.1-SNAPSHOT tendermanagement Tender Management project - - - - - - - - - - - - - 17 + 1.5.5.Final + org.springframework.boot spring-boot-starter-web + + + org.projectlombok + lombok + 1.18.24 + + + + + com.h2database + h2 + 1.4.200 + + + + + org.postgresql + postgresql + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + + org.springdoc + springdoc-openapi-starter-webmvc-ui + 2.2.0 + + + + + org.mapstruct + mapstruct + ${mapstruct.version} + + + org.mapstruct + mapstruct-processor + ${mapstruct.version} + provided + + + + org.liquibase + liquibase-core + + + org.springframework.boot spring-boot-starter-test @@ -42,13 +82,21 @@ + org.springframework.boot spring-boot-maven-plugin + + org.liquibase + liquibase-maven-plugin + 4.20.0 + + src/main/resources/application.properties + + - diff --git a/src/main/java/net/gepafin/tendermanagement/TendermanagementApplication.java b/src/main/java/net/gepafin/tendermanagement/TendermanagementApplication.java index f63a972f..07a51505 100644 --- a/src/main/java/net/gepafin/tendermanagement/TendermanagementApplication.java +++ b/src/main/java/net/gepafin/tendermanagement/TendermanagementApplication.java @@ -2,12 +2,21 @@ package net.gepafin.tendermanagement; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.scheduling.annotation.EnableScheduling; +@EnableScheduling +@ComponentScan(basePackages = {"net.gepafin.tendermanagement"}) +@EnableJpaRepositories(basePackages = {"net.gepafin.tendermanagement"}) +@EntityScan(basePackages = {"net.gepafin.tendermanagement"}) @SpringBootApplication public class TendermanagementApplication { public static void main(String[] args) { SpringApplication.run(TendermanagementApplication.class, args); + System.out.println("Spring Boot started"); } } diff --git a/src/main/java/net/gepafin/tendermanagement/config/MessageSourceConfig.java b/src/main/java/net/gepafin/tendermanagement/config/MessageSourceConfig.java new file mode 100644 index 00000000..6f9767c6 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/config/MessageSourceConfig.java @@ -0,0 +1,17 @@ +package net.gepafin.tendermanagement.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.ResourceBundleMessageSource; + +@Configuration +public class MessageSourceConfig { + @Bean(name = "defaultMessageSource") + public ResourceBundleMessageSource messageSource() { + ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); + messageSource.setBasenames("message"); + messageSource.setDefaultEncoding("UTF-8"); + messageSource.setUseCodeAsDefaultMessage(true); + return messageSource; + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/config/SchemaInit.java b/src/main/java/net/gepafin/tendermanagement/config/SchemaInit.java new file mode 100644 index 00000000..6d57f81f --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/config/SchemaInit.java @@ -0,0 +1,70 @@ +package net.gepafin.tendermanagement.config; + +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; + +import javax.sql.DataSource; + +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.AbstractDependsOnBeanFactoryPostProcessor; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.stereotype.Component; + +import liquibase.change.DatabaseChange; +import liquibase.integration.spring.SpringLiquibase; +import org.springframework.beans.factory.annotation.Value; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Configuration +@ConditionalOnClass({ SpringLiquibase.class, DatabaseChange.class }) +@ConditionalOnProperty(prefix = "spring.liquibase", name = "enabled", matchIfMissing = true) +@AutoConfigureAfter({ DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class }) +@Import({SchemaInit.SpringLiquibaseDependsOnPostProcessor.class}) +public class SchemaInit { + + @Component + @ConditionalOnProperty(prefix = "spring.liquibase", name = "enabled", matchIfMissing = true) + public static class SchemaInitBean implements InitializingBean { + + private final DataSource dataSource; + private final String schemaName; + + @Autowired + public SchemaInitBean(DataSource dataSource, @Value("${spring.liquibase.default-schema}") String schemaName) { + this.dataSource = dataSource; + this.schemaName = schemaName; + } + + @Override + public void afterPropertiesSet() { + try (Connection conn = dataSource.getConnection(); + Statement statement = conn.createStatement()) { + log.info("Going to create DB schema '{}' if not exists.", schemaName); + String query = "create schema if not exists " + schemaName; + statement.execute(query); + } catch (SQLException e) { + throw new RuntimeException("Failed to create schema '" + schemaName + "'", e); + } + } + } + + + @ConditionalOnBean(SchemaInitBean.class) + static class SpringLiquibaseDependsOnPostProcessor extends AbstractDependsOnBeanFactoryPostProcessor { + + SpringLiquibaseDependsOnPostProcessor() { + // Configure the 3rd party SpringLiquibase bean to depend on our SchemaInitBean + super(SpringLiquibase.class, SchemaInitBean.class); + } + } +} \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/config/Translator.java b/src/main/java/net/gepafin/tendermanagement/config/Translator.java new file mode 100644 index 00000000..b3c02401 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/config/Translator.java @@ -0,0 +1,25 @@ +package net.gepafin.tendermanagement.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.context.support.ResourceBundleMessageSource; +import org.springframework.stereotype.Component; + +import java.util.Locale; + +@Component +public class Translator { + + private static ResourceBundleMessageSource messageSource; + + @Autowired + Translator(ResourceBundleMessageSource messageSource) { + Translator.messageSource = messageSource; + } + + public static String toLocale(String msgCode) { +// LocaleContextHolder.setDefaultLocale(Locale.ITALIAN); + Locale locale = LocaleContextHolder.getLocale(); + return messageSource.getMessage(msgCode, null, locale); + } +} \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java new file mode 100644 index 00000000..7d00913f --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -0,0 +1,27 @@ +package net.gepafin.tendermanagement.constants; + +public class GepafinConstant { + + public static final String USER_CREATED_SUCCESS_MSG = "user.created.success"; + public static final String USER_UPDATED_SUCCESS_MSG = "user.updated.success"; + public static final String USER_DELETED_SUCCESS_MSG = "user.deleted.success"; + public static final String USER_NOT_FOUND_MSG = "user.not.found"; + public static final String CREATE_USER_ERROR_MSG = "create_user_error_msg"; + public static final String UPDATE_USER_ERROR_MSG = "update_user_error_msg"; + public static final String DELETE_USER_ERROR_MSG = "delete_user_error_msg"; + public static final String GET_USER_SUCCESS_MSG = "get_user_success_msg"; + + public static final String ROLE_CREATED_SUCCESS_MSG = "role.created.success"; + public static final String ROLE_UPDATED_SUCCESS_MSG = "role.updated.success"; + public static final String ROLE_DELETED_SUCCESS_MSG = "role.deleted.success"; + public static final String ROLE_FETCH_SUCCESS_MSG = "role.fetch.success"; + public static final String ROLE_NOT_FOUND = "role.not.found"; + + + public static final String REGION_CREATED_SUCCESS_MSG = "region.created.success"; + public static final String REGION_UPDATED_SUCCESS_MSG = "region.updated.success"; + public static final String GET_REGION_SUCCESS_MSG = "get.region.success"; + public static final String DELETE_REGION_SUCCESS_MSG = "delete.region.success"; + public static final String REGION_NOT_FOUND_MSG = "user.region.not.found"; + public static final String PASSWORD_DOESNT_MATCH ="password.doesnt.match"; +} diff --git a/src/main/java/net/gepafin/tendermanagement/dao/RegionDao.java b/src/main/java/net/gepafin/tendermanagement/dao/RegionDao.java new file mode 100644 index 00000000..27f7f250 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/dao/RegionDao.java @@ -0,0 +1,109 @@ +package net.gepafin.tendermanagement.dao; + +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.model.request.RegionReq; +import net.gepafin.tendermanagement.model.request.RoleReq; +import net.gepafin.tendermanagement.model.response.RegionResponseBean; +import net.gepafin.tendermanagement.model.request.UpdateRegionReq; +import net.gepafin.tendermanagement.model.response.RoleResponseBean; +import net.gepafin.tendermanagement.repositories.RegionRepository; +import net.gepafin.tendermanagement.util.Utils; +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; +import org.springframework.stereotype.Repository; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +import static net.gepafin.tendermanagement.util.ObjectUtils.setIfUpdated; + +@Repository +public class RegionDao { + @Autowired + private RegionRepository regionRepository; + + public RegionResponseBean createRegion(RegionReq regionReq) { + RegionEntity regionEntity = convertRegionRequestToRegionEntity(regionReq); + regionRepository.save(regionEntity); + return convertRegionEntityToRegionResponse(regionEntity); + } + private RegionEntity convertRegionRequestToRegionEntity(RegionReq regionReq) { + RegionEntity regionEntity = new RegionEntity(); + regionEntity.setCountry(regionReq.getCountry()); + regionEntity.setDescription(regionReq.getDescription()); + regionEntity.setGdp(regionReq.getGdp()); + regionEntity.setRegionName(regionReq.getRegionName()); + regionEntity.setAreaSize(regionReq.getAreaSize()); + regionEntity.setPopulation(regionReq.getPopulation()); + regionEntity.setEnvironmentalScore(regionReq.getEnvironmentalScore()); + regionEntity.setStatus(regionReq.getStatus()); + regionEntity.setHealthcareAccess(regionReq.getHealthcareAccess()); + regionEntity.setInfrastructureScore(regionReq.getInfrastructureScore()); + regionEntity.setPriorityArea(regionReq.getPriorityArea()); + regionEntity.setUnemploymentRate(regionReq.getUnemploymentRate()); + regionEntity.setEducationLevel(regionReq.getEducationLevel()); + return regionEntity; + } + private RegionResponseBean convertRegionEntityToRegionResponse(RegionEntity regionEntity) { + RegionResponseBean regionResponseBean = new RegionResponseBean(); + regionResponseBean.setId(regionEntity.getId()); + regionResponseBean.setCreatedDate(regionEntity.getCreatedDate()); + regionResponseBean.setUpdatedDate(regionEntity.getUpdatedDate()); + regionResponseBean.setCountry(regionEntity.getCountry()); + regionResponseBean.setDescription(regionEntity.getDescription()); + regionResponseBean.setGdp(regionEntity.getGdp()); + regionResponseBean.setRegionName(regionEntity.getRegionName()); + regionResponseBean.setAreaSize(regionEntity.getAreaSize()); + regionResponseBean.setPopulation(regionEntity.getPopulation()); + regionResponseBean.setEnvironmentalScore(regionEntity.getEnvironmentalScore()); + regionResponseBean.setStatus(regionEntity.getStatus()); + regionResponseBean.setHealthcareAccess(regionEntity.getHealthcareAccess()); + regionResponseBean.setInfrastructureScore(regionEntity.getInfrastructureScore()); + regionResponseBean.setPriorityArea(regionEntity.getPriorityArea()); + regionResponseBean.setUnemploymentRate(regionEntity.getUnemploymentRate()); + regionResponseBean.setEducationLevel(regionEntity.getEducationLevel()); + return regionResponseBean; + } + + public RegionResponseBean updateRegion(Long id, RegionReq regionReq) { + RegionEntity existingRegion = getRegionById(id); + setIfUpdated(existingRegion::getRegionName, existingRegion::setRegionName, regionReq.getRegionName()); + setIfUpdated(existingRegion::getDescription, existingRegion::setDescription, regionReq.getDescription()); + setIfUpdated(existingRegion::getCountry, existingRegion::setCountry, regionReq.getCountry()); + setIfUpdated(existingRegion::getStatus, existingRegion::setStatus, regionReq.getStatus()); + setIfUpdated(existingRegion::getPriorityArea, existingRegion::setPriorityArea, regionReq.getPriorityArea()); + setIfUpdated(existingRegion::getPopulation, existingRegion::setPopulation, regionReq.getPopulation()); + setIfUpdated(existingRegion::getAreaSize, existingRegion::setAreaSize, regionReq.getAreaSize()); + setIfUpdated(existingRegion::getGdp, existingRegion::setGdp, regionReq.getGdp()); + setIfUpdated(existingRegion::getUnemploymentRate, existingRegion::setUnemploymentRate, regionReq.getUnemploymentRate()); + setIfUpdated(existingRegion::getInfrastructureScore, existingRegion::setInfrastructureScore, regionReq.getInfrastructureScore() ); + setIfUpdated(existingRegion::getEducationLevel, existingRegion::setEducationLevel, regionReq.getEducationLevel()); + setIfUpdated(existingRegion::getHealthcareAccess, existingRegion::setHealthcareAccess, regionReq.getHealthcareAccess()); + setIfUpdated(existingRegion::getEnvironmentalScore, existingRegion::setEnvironmentalScore, regionReq.getEnvironmentalScore()); + regionRepository.save(existingRegion); + return Utils.convertObject(existingRegion, RegionResponseBean.class); + } + public RegionEntity getRegionById(Long id) { + return regionRepository.findById(id) + .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.REGION_NOT_FOUND_MSG))); + } + public void deleteById(Long id) { + + regionRepository.findById(id) + .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.REGION_NOT_FOUND_MSG))); + regionRepository.deleteById(id); + } + public List getAllRegions() + { + return regionRepository.findAll() + .stream() + .map(regionEntity -> Utils.convertObject(regionEntity, RegionResponseBean.class)) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/dao/RoleDao.java b/src/main/java/net/gepafin/tendermanagement/dao/RoleDao.java new file mode 100644 index 00000000..08c1a40f --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/dao/RoleDao.java @@ -0,0 +1,80 @@ +package net.gepafin.tendermanagement.dao; + +import net.gepafin.tendermanagement.config.Translator; +import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.entities.RoleEntity; +import net.gepafin.tendermanagement.model.request.RoleReq; +import net.gepafin.tendermanagement.model.response.RoleResponseBean; +import net.gepafin.tendermanagement.repositories.RoleRepository; +import net.gepafin.tendermanagement.service.RegionService; +import net.gepafin.tendermanagement.util.Utils; +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; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +import static net.gepafin.tendermanagement.util.ObjectUtils.setIfUpdated; + +@Component +public class RoleDao { + + @Autowired + private RoleRepository roleRepository; + @Autowired + private RegionService regionService; + + public RoleResponseBean createRole(RoleReq roleReq) { + RoleEntity roleEntity = convertRoleRequestToRoleEntity(roleReq); + roleEntity = roleRepository.save(roleEntity); + return convertRoleEntityToRoleResponse(roleEntity); + } + private RoleEntity convertRoleRequestToRoleEntity(RoleReq roleReq) { + RoleEntity roleEntity = new RoleEntity(); + roleEntity.setRoleName(roleReq.getRoleName()); + roleEntity.setPermissions(roleReq.getPermissions()); + roleEntity.setDescription(roleEntity.getDescription()); + roleEntity.setRegion(regionService.getRegionById(roleReq.getRegionId())); + return roleEntity; + } + private RoleResponseBean convertRoleEntityToRoleResponse(RoleEntity roleEntity) { + RoleResponseBean roleResponseBean=new RoleResponseBean(); + roleResponseBean.setId(roleEntity.getId()); + roleResponseBean.setCreatedDate(roleEntity.getCreatedDate()); + roleResponseBean.setUpdatedDate(roleEntity.getUpdatedDate()); + roleResponseBean.setRoleName(roleEntity.getRoleName()); + roleResponseBean.setDescription(roleEntity.getDescription()); + roleResponseBean.setPermissions(roleEntity.getPermissions()); + roleResponseBean.setRegion(roleEntity.getRegion()); + return roleResponseBean; + } + public RoleResponseBean updateRole(Long id, RoleReq roleReq) { + + RoleEntity existingUserRole = getRoleById(id); + setIfUpdated(existingUserRole::getRoleName, existingUserRole::setRoleName, roleReq.getRoleName()); + setIfUpdated(existingUserRole::getDescription, existingUserRole::setDescription, roleReq.getDescription()); + setIfUpdated(existingUserRole::getPermissions, existingUserRole::setPermissions, roleReq.getPermissions()); + roleRepository.save(existingUserRole); + return Utils.convertObject(existingUserRole, RoleResponseBean.class); + } + + public RoleEntity getRoleById(Long id) { + return roleRepository.findById(id) + .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.ROLE_NOT_FOUND))); + } + + public void deleteById(Long id) { + roleRepository.findById(id) + .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND,Translator.toLocale(GepafinConstant.ROLE_NOT_FOUND))); + roleRepository.deleteById(id); + } + + public List getAllRoles() { + return roleRepository.findAll() + .stream() + .map(roleEntity -> Utils.convertObject(roleEntity, RoleResponseBean.class)) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java new file mode 100644 index 00000000..63a7c353 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java @@ -0,0 +1,99 @@ +package net.gepafin.tendermanagement.dao; + +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.model.request.UpdateUserReq; +import net.gepafin.tendermanagement.model.request.UserReq; +import net.gepafin.tendermanagement.model.response.UserResponseBean; +import net.gepafin.tendermanagement.repositories.UserRepository; +import net.gepafin.tendermanagement.service.RoleService; +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; +import org.springframework.stereotype.Repository; + +import static net.gepafin.tendermanagement.util.ObjectUtils.setIfUpdated; + +@Repository +public class UserDao { + @Autowired + private UserRepository userRepository; + + @Autowired + private RoleService roleService; + + public UserResponseBean createUser(UserReq userReq) { + if (!userReq.getPassword().equals(userReq.getConfPassword())) { + throw new CustomValidationException(Status.VALIDATION_ERROR,Translator.toLocale(GepafinConstant.PASSWORD_DOESNT_MATCH)); + } + UserEntity userEntity = convertUserRequestToUserEntity(userReq); + userEntity = userRepository.save(userEntity); + return convertUserEntityToUserResponse(userEntity); + } + + public UserResponseBean updateUser(Long userId, UpdateUserReq userReq) { + UserEntity userEntity = userRepository.findById(userId) + .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.REGION_NOT_FOUND_MSG))); + setIfUpdated(userEntity::getStatus, userEntity::setStatus, userReq.getStatus()); + setIfUpdated(userEntity::getFirstName, userEntity::setFirstName, userReq.getFirstName()); + setIfUpdated(userEntity::getLastName, userEntity::setLastName, userReq.getLastName()); + setIfUpdated(userEntity::getOrganization, userEntity::setOrganization, userReq.getOrganization()); + setIfUpdated(userEntity::getAddress, userEntity::setAddress, userReq.getAddress()); + setIfUpdated(userEntity::getPhoneNumber, userEntity::setPhoneNumber, userReq.getPhoneNumber()); + if (userReq.getRoleId() != null) { + RoleEntity roleEntity = roleService.getRoleById(userReq.getRoleId()); + setIfUpdated(userEntity::getRoleEntity, userEntity::setRoleEntity, roleEntity); + } + userEntity = userRepository.save(userEntity); + return convertUserEntityToUserResponse(userEntity); + } + + private UserEntity convertUserRequestToUserEntity(UserReq userReq) { + UserEntity userEntity = new UserEntity(); + userEntity.setPassword(userReq.getPassword()); + userEntity.setEmail(userReq.getEmail()); + userEntity.setFirstName(userReq.getFirstName()); + userEntity.setStatus(userReq.getStatus()); + userEntity.setLastName(userReq.getLastName()); + userEntity.setOrganization(userReq.getOrganization()); + userEntity.setAddress(userReq.getAddress()); + userEntity.setPhoneNumber(userReq.getPhoneNumber()); + userEntity.setRoleEntity(roleService.getRoleById(userReq.getRoleId())); + return userEntity; + } + + private UserResponseBean convertUserEntityToUserResponse(UserEntity userEntity) { + UserResponseBean userResponseBean = new UserResponseBean(); + userResponseBean.setId(userEntity.getId()); + userResponseBean.setCreatedDate(userEntity.getCreatedDate()); + userResponseBean.setUpdatedDate(userEntity.getUpdatedDate()); + userResponseBean.setId(userEntity.getId()); + 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(userEntity.getStatus()); + userResponseBean.setRole(userEntity.getRoleEntity()); + userResponseBean.setLastLogin(userEntity.getLastLogin()); + return userResponseBean; + } + + public UserResponseBean getUserById(Long id) { + UserEntity userEntity = userRepository.findById(id) + .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND,Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG))); + return convertUserEntityToUserResponse(userEntity); + } + + public void deleteUser(Long id) { + userRepository.findById(id) + .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND,Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG))); + userRepository.deleteById(id); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/entities/BaseEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/BaseEntity.java new file mode 100644 index 00000000..f8427719 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/entities/BaseEntity.java @@ -0,0 +1,35 @@ +package net.gepafin.tendermanagement.entities; + +import jakarta.persistence.*; +import lombok.Data; +import net.gepafin.tendermanagement.util.DateTimeUtil; + + +import java.time.LocalDateTime; + +@MappedSuperclass +@Data +public class BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "ID", unique = true) + private Long id; + + + @Column(name = "CREATED_DATE", updatable = false) + LocalDateTime createdDate; + + @Column(name = "UPDATED_DATE") + LocalDateTime updatedDate; + + @PrePersist + public void setCreatedDate() { + this.createdDate = DateTimeUtil.DateServerToUTC(LocalDateTime.now()); + this.updatedDate = DateTimeUtil.DateServerToUTC(LocalDateTime.now()); + } + @PreUpdate + public void setUpdatedDate() { + this.updatedDate = DateTimeUtil.DateServerToUTC(LocalDateTime.now()); + } + +} diff --git a/src/main/java/net/gepafin/tendermanagement/entities/RegionEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/RegionEntity.java new file mode 100644 index 00000000..d9687dd1 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/entities/RegionEntity.java @@ -0,0 +1,60 @@ +package net.gepafin.tendermanagement.entities; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; + +import lombok.Getter; +import lombok.Setter; +import net.gepafin.tendermanagement.entities.BaseEntity; + +import java.math.BigDecimal; + +@Entity +@Table(name = "\"REGION\"") +@Getter +@Setter +public class RegionEntity extends BaseEntity { + + @Column(name = "REGION_NAME", length = 255, nullable = true) + private String regionName; + + @Column(name = "DESCRIPTION", length = 255, nullable = true) + private String description; + + @Column(name = "COUNTRY", length = 50, nullable = true) + private String country; + + @Column(name = "STATUS", length = 30, nullable = true) + private String status; + + @Column(name = "PRIORITY_AREA", length = 255, nullable = true) + private String priorityArea; + + @Column(name = "POPULATION", nullable = true) + private Long population; + + @Column(name = "AREA_SIZE", nullable = true) + private BigDecimal areaSize; + + @Column(name = "GDP", nullable = true) + private BigDecimal gdp; + + @Column(name = "UNEMPLOYMENT_RATE", nullable = true) + private BigDecimal unemploymentRate; + + @Column(name = "INFRASTRUCTURE_SCORE", nullable = true) + private BigDecimal infrastructureScore; + + @Column(name = "EDUCATION_LEVEL", nullable = true) + private BigDecimal educationLevel; + + @Column(name = "HEALTHCARE_ACCESS", nullable = true) + private BigDecimal healthcareAccess; + + @Column(name = "ENVIRONMENTAL_SCORE", nullable = true) + private BigDecimal environmentalScore; +} diff --git a/src/main/java/net/gepafin/tendermanagement/entities/RoleEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/RoleEntity.java new file mode 100644 index 00000000..25693802 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/entities/RoleEntity.java @@ -0,0 +1,26 @@ +package net.gepafin.tendermanagement.entities; + +import jakarta.persistence.*; + +import lombok.Getter; +import lombok.Setter; + +@Entity +@Table(name = "\"ROLE\"") +@Getter +@Setter +public class RoleEntity extends BaseEntity { + + @Column(name = "ROLE_NAME", length = 50, nullable = true) + private String roleName; + + @Column(name = "DESCRIPTION", length = 255, nullable = true) + private String description; + + @Column(name = "PERMISSIONS", length = 255, nullable = true) + private String permissions; + @ManyToOne + @JoinColumn(name = "REGION_ID", nullable = true) + private RegionEntity region; + +} diff --git a/src/main/java/net/gepafin/tendermanagement/entities/UserEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/UserEntity.java new file mode 100644 index 00000000..890fdc32 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/entities/UserEntity.java @@ -0,0 +1,77 @@ +package net.gepafin.tendermanagement.entities; + +import com.fasterxml.jackson.annotation.JsonValue; +import jakarta.persistence.*; +import jakarta.validation.constraints.Email; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +import lombok.Getter; +import lombok.Setter; +import net.gepafin.tendermanagement.entities.BaseEntity; + +import java.time.LocalDateTime; + +@Entity +@Table(name = "\"USER\"") +@Getter +@Setter +public class UserEntity extends BaseEntity { + + @Column(name = "PASSWORD", columnDefinition = "TEXT",nullable = false) + @JsonIgnore + private String password; + + @Email + @Column(name = "EMAIL", length = 255, unique = true, nullable = false) + private String email; + + @ManyToOne + @JoinColumn(name = "ROLE_ID") + @JsonIgnore + private RoleEntity roleEntity; + + + @Column(name = "LAST_LOGIN") + private LocalDateTime lastLogin; + + @Column(name = "STATUS", length = 30, nullable = true) + private String status; + + @Column(name = "FIRST_NAME", length = 50, nullable = true) + private String firstName; + + @Column(name = "LAST_NAME", length = 50, nullable = true) + private String lastName; + + @Column(name = "PHONE_NUMBER", length = 15, nullable = true) + private String phoneNumber; + + @Column(name = "ORGANIZATION", length = 255, nullable = true) + private String organization; + + @Column(name = "ADDRESS", length = 255, nullable = true) + private String address; + + @Column(name = "CITY", length = 50, nullable = true) + private String city; + + @Column(name = "COUNTRY", length = 50, nullable = true) + private String country; + + public enum UserStatusEnum { + ACTIVE("ACTIVE"), + INACTIVE("INACTIVE"); + + private String value; + + UserStatusEnum(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/User.java b/src/main/java/net/gepafin/tendermanagement/model/User.java deleted file mode 100644 index 8b3fe662..00000000 --- a/src/main/java/net/gepafin/tendermanagement/model/User.java +++ /dev/null @@ -1,38 +0,0 @@ -package net.gepafin.tendermanagement.model; - -public class User { - private Long id; - private String name; - private String email; - - public User() {} - - public User(Long id, String name, String email) { - this.id = id; - this.name = name; - this.email = email; - } - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } -} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/RegionReq.java b/src/main/java/net/gepafin/tendermanagement/model/request/RegionReq.java new file mode 100644 index 00000000..fae42f3c --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/RegionReq.java @@ -0,0 +1,39 @@ +package net.gepafin.tendermanagement.model.request; + +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Getter; +import lombok.Setter; + +import java.math.BigDecimal; + +@Getter +@Setter +public class RegionReq { + + private String regionName; + + private String description; + + private String country; + + private String status; + + private String priorityArea; + + private Long population; + + private BigDecimal areaSize; + + private BigDecimal gdp; + + private BigDecimal unemploymentRate; + + private BigDecimal infrastructureScore; + + private BigDecimal educationLevel; + + private BigDecimal healthcareAccess; + + private BigDecimal environmentalScore; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/RoleReq.java b/src/main/java/net/gepafin/tendermanagement/model/request/RoleReq.java new file mode 100644 index 00000000..1e4ec6f4 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/RoleReq.java @@ -0,0 +1,27 @@ +package net.gepafin.tendermanagement.model.request; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class RoleReq { + + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + private Long id; + + private String roleName; + + private String description; + + private String permissions; + + private String status; + + private Long regionId; + +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/UpdateRegionReq.java b/src/main/java/net/gepafin/tendermanagement/model/request/UpdateRegionReq.java new file mode 100644 index 00000000..8d32dc83 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/UpdateRegionReq.java @@ -0,0 +1,35 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class UpdateRegionReq { + private String regionName; + + private String description; + + private String country; + + private String status; + + private String priorityArea; + + private Long population; + + private Double areaSize; + + private Double gdp; + + private Double unemploymentRate; + + private Double infrastructureScore; + + private Double educationLevel; + + private Double healthcareAccess; + + private Double environmentalScore; + +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/UpdateUserReq.java b/src/main/java/net/gepafin/tendermanagement/model/request/UpdateUserReq.java new file mode 100644 index 00000000..63eb2b89 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/UpdateUserReq.java @@ -0,0 +1,21 @@ +package net.gepafin.tendermanagement.model.request; + +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class UpdateUserReq { + + private String firstName; + private String lastName; + private String phoneNumber; + private Long roleId; + private String organization; + private String address; + private String city; + private String status; + private String country; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/UserReq.java b/src/main/java/net/gepafin/tendermanagement/model/request/UserReq.java new file mode 100644 index 00000000..f866ac99 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/UserReq.java @@ -0,0 +1,44 @@ +package net.gepafin.tendermanagement.model.request; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonValue; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Getter; +import lombok.Setter; + +import java.time.LocalDateTime; + +@Getter +@Setter +public class UserReq { + + + private String password; + + private String confPassword; + + private String email; + + private String firstName; + + private String lastName; + + private String phoneNumber; + + private Long roleId; + + private String organization; + + private String address; + + private String city; + + private String country; + + private String status; + + private LocalDateTime lastLogin; + +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/RegionResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/RegionResponseBean.java new file mode 100644 index 00000000..c16d4c94 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/RegionResponseBean.java @@ -0,0 +1,28 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Getter; +import lombok.Setter; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Getter +@Setter +public class RegionResponseBean { + private Long id; + private String regionName; + private String description; + private String country; + private String status; + private String priorityArea; + private Long population; + private BigDecimal areaSize; + private BigDecimal gdp; + private BigDecimal unemploymentRate; + private BigDecimal infrastructureScore; + private BigDecimal educationLevel; + private BigDecimal healthcareAccess; + private BigDecimal environmentalScore; + private LocalDateTime createdDate; + private LocalDateTime updatedDate; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/RoleResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/RoleResponseBean.java new file mode 100644 index 00000000..1e708b58 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/RoleResponseBean.java @@ -0,0 +1,19 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import net.gepafin.tendermanagement.entities.RegionEntity; + +import java.time.LocalDateTime; + +@Data +public class RoleResponseBean { + private Long id; + private String roleName; + private String description; + private LocalDateTime createdDate; + private LocalDateTime updatedDate; + private String permissions; + private RegionEntity region; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/UserResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/UserResponseBean.java new file mode 100644 index 00000000..2c036804 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/UserResponseBean.java @@ -0,0 +1,41 @@ +package net.gepafin.tendermanagement.model.response; + +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Getter; +import lombok.Setter; +import net.gepafin.tendermanagement.entities.RoleEntity; + +import java.time.LocalDateTime; + +@Getter +@Setter +public class UserResponseBean { + private Long id; + private String email; + + private String firstName; + + private String lastName; + + private String phoneNumber; + + private RoleEntity role; + + private String organization; + + private String address; + + private String city; + + private String country; + + private String status; + + private LocalDateTime lastLogin; + + private LocalDateTime createdDate; + + private LocalDateTime updatedDate; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/util/Response.java b/src/main/java/net/gepafin/tendermanagement/model/util/Response.java new file mode 100644 index 00000000..7d0c768d --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/util/Response.java @@ -0,0 +1,29 @@ +package net.gepafin.tendermanagement.model.util; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.gepafin.tendermanagement.web.rest.api.errors.Status; + +import java.io.Serializable; + +/** + * A generic response class used for API responses. + * + * @param the type of the response data + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +public class Response implements Serializable { + + private static final long serialVersionUID = 1L; + + private T data; // The response data + private Status status; // The status of the response + private String message; // Additional message or error description +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/RegionRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/RegionRepository.java new file mode 100644 index 00000000..87dfdfa0 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/repositories/RegionRepository.java @@ -0,0 +1,9 @@ +package net.gepafin.tendermanagement.repositories; + +import net.gepafin.tendermanagement.entities.RegionEntity; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface RegionRepository extends JpaRepository { +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/RoleRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/RoleRepository.java new file mode 100644 index 00000000..e009e6a3 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/repositories/RoleRepository.java @@ -0,0 +1,9 @@ +package net.gepafin.tendermanagement.repositories; + +import net.gepafin.tendermanagement.entities.RoleEntity; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface RoleRepository extends JpaRepository { +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java new file mode 100644 index 00000000..2fdee718 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java @@ -0,0 +1,9 @@ +package net.gepafin.tendermanagement.repositories; + +import net.gepafin.tendermanagement.entities.UserEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface UserRepository extends JpaRepository { +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/RegionService.java b/src/main/java/net/gepafin/tendermanagement/service/RegionService.java new file mode 100644 index 00000000..2288fa17 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/RegionService.java @@ -0,0 +1,22 @@ +package net.gepafin.tendermanagement.service; + +import net.gepafin.tendermanagement.entities.RegionEntity; +import net.gepafin.tendermanagement.model.request.RegionReq; +import net.gepafin.tendermanagement.model.response.RegionResponseBean; +import net.gepafin.tendermanagement.model.request.UpdateRegionReq; + +import java.util.List; + + +public interface RegionService { + + RegionResponseBean createRegion(RegionReq regionReq); + + RegionResponseBean updateRegion(Long regionId, RegionReq regionReq); + + RegionEntity getRegionById(Long regionId); + + void deleteRegion(Long regionId); + + List getAllRegions(); +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/RoleService.java b/src/main/java/net/gepafin/tendermanagement/service/RoleService.java new file mode 100644 index 00000000..448197b4 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/RoleService.java @@ -0,0 +1,19 @@ +package net.gepafin.tendermanagement.service; + +import net.gepafin.tendermanagement.entities.RoleEntity; +import net.gepafin.tendermanagement.model.request.RoleReq; +import net.gepafin.tendermanagement.model.response.RoleResponseBean; + +import java.util.List; + +public interface RoleService { + RoleResponseBean createRole(RoleReq roleReq); + + RoleResponseBean updateRole(Long roleId, RoleReq roleReq); + + RoleEntity getRoleById(Long roleId); + + void deleteRole(Long roleId); + + List getAllRoles(); +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/UserService.java b/src/main/java/net/gepafin/tendermanagement/service/UserService.java new file mode 100644 index 00000000..71faf129 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/UserService.java @@ -0,0 +1,12 @@ +package net.gepafin.tendermanagement.service; + +import net.gepafin.tendermanagement.model.request.UpdateUserReq; +import net.gepafin.tendermanagement.model.request.UserReq; +import net.gepafin.tendermanagement.model.response.UserResponseBean; + +public interface UserService { + UserResponseBean createUser(UserReq userReq); + UserResponseBean updateUser(Long userId, UpdateUserReq userReq); + UserResponseBean getUserById(Long userId); + void deleteUser(Long userId); +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/RegionServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/RegionServiceImpl.java new file mode 100644 index 00000000..63921ef1 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/RegionServiceImpl.java @@ -0,0 +1,43 @@ +package net.gepafin.tendermanagement.service.impl; + +import java.util.List; + +import net.gepafin.tendermanagement.dao.RegionDao; +import net.gepafin.tendermanagement.entities.RegionEntity; +import net.gepafin.tendermanagement.model.request.RegionReq; +import net.gepafin.tendermanagement.model.response.RegionResponseBean; +import net.gepafin.tendermanagement.model.request.UpdateRegionReq; +import net.gepafin.tendermanagement.service.RegionService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +@Service +public class RegionServiceImpl implements RegionService { + + @Autowired + private RegionDao regionDao; + + @Override + public RegionResponseBean createRegion(RegionReq regionReq) { + return regionDao.createRegion(regionReq); + } + + @Override + public RegionResponseBean updateRegion(Long regionId, RegionReq regionReq) { + return regionDao.updateRegion(regionId,regionReq); + } + + @Override + public RegionEntity getRegionById(Long regionId) { + return regionDao.getRegionById(regionId); + } + + @Override + public void deleteRegion(Long regionId) { + regionDao.deleteById(regionId); + } + + @Override + public List getAllRegions() { + return regionDao.getAllRegions(); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/RoleServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/RoleServiceImpl.java new file mode 100644 index 00000000..41f3f6ba --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/RoleServiceImpl.java @@ -0,0 +1,44 @@ +package net.gepafin.tendermanagement.service.impl; + +import java.util.List; + +import net.gepafin.tendermanagement.dao.RoleDao; +import net.gepafin.tendermanagement.entities.RoleEntity; +import net.gepafin.tendermanagement.model.request.RoleReq; +import net.gepafin.tendermanagement.model.response.RoleResponseBean; +import net.gepafin.tendermanagement.service.RoleService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + + +@Service +public class RoleServiceImpl implements RoleService { + + @Autowired + private RoleDao roleDao; + + @Override + public RoleResponseBean createRole(RoleReq roleReq) { + return roleDao.createRole(roleReq); + } + @Override + public RoleResponseBean updateRole(Long roleId, RoleReq roleReq) { + return roleDao.updateRole(roleId,roleReq); + } + + @Override + public RoleEntity getRoleById(Long roleId) { + return roleDao.getRoleById(roleId); + } + + @Override + public void deleteRole(Long roleId) { + roleDao.deleteById(roleId); + } + + @Override + public List getAllRoles() { + return roleDao.getAllRoles(); + + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java new file mode 100644 index 00000000..4d39ffc5 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java @@ -0,0 +1,38 @@ +package net.gepafin.tendermanagement.service.impl; + +import net.gepafin.tendermanagement.dao.UserDao; +import net.gepafin.tendermanagement.model.request.UpdateUserReq; +import net.gepafin.tendermanagement.model.request.UserReq; +import net.gepafin.tendermanagement.model.response.UserResponseBean; +import net.gepafin.tendermanagement.service.UserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.format.DateTimeFormatter; + +@Service +public class UserServiceImpl implements UserService { + + @Autowired + private UserDao userDao; + public UserResponseBean createUser(UserReq userReq) { + return userDao.createUser(userReq); + } + + + @Override + public UserResponseBean updateUser(Long userId, UpdateUserReq userReq) { + return userDao.updateUser(userId, userReq); + } + + @Override + public UserResponseBean getUserById(Long userId) { + return userDao.getUserById(userId); + } + + @Override + public void deleteUser(Long userId) { + userDao.deleteUser(userId); + } + +} diff --git a/src/main/java/net/gepafin/tendermanagement/util/DateTimeUtil.java b/src/main/java/net/gepafin/tendermanagement/util/DateTimeUtil.java new file mode 100644 index 00000000..ab67ccdd --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/util/DateTimeUtil.java @@ -0,0 +1,53 @@ +package net.gepafin.tendermanagement.util; + +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.Calendar; +import java.util.Date; + +@Component +public class DateTimeUtil { + + + public static LocalDateTime DateServerToUTC(LocalDateTime systemDate) { + + ZonedDateTime ldtZoned = systemDate.atZone(ZoneId.systemDefault()); + LocalDateTime localDatetime = ldtZoned.withZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime(); + return localDatetime; + } + + public static LocalDateTime getPreviousMonthDate(int month) { + Calendar c = Calendar.getInstance(); + c.add(Calendar.MONTH, -month); + LocalDateTime conv = LocalDateTime.ofInstant(c.getTime().toInstant(), ZoneId.systemDefault()); + return conv; + } + + public static Date getDateWithoutTime(LocalDateTime systemDate) { + ZonedDateTime zdt = systemDate.atZone(ZoneId.systemDefault()); + Date date = Date.from(zdt.toInstant()); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + calendar.set(Calendar.HOUR_OF_DAY, 0); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + calendar.set(Calendar.MILLISECOND, 0); + return calendar.getTime(); + } + + public static LocalDateTime convertDateToLocalDateTime(Date date) { + LocalDateTime ldt = LocalDateTime.ofInstant(date.toInstant(), + ZoneId.systemDefault()); + return ldt; + } + + + public static Date convertLocalDateTimeToDateUsingInstant(LocalDateTime localDateTime) { + return Date + .from(localDateTime.atZone(ZoneId.systemDefault()) + .toInstant()); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/util/ObjectUtils.java b/src/main/java/net/gepafin/tendermanagement/util/ObjectUtils.java new file mode 100644 index 00000000..1f7d1215 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/util/ObjectUtils.java @@ -0,0 +1,20 @@ +package net.gepafin.tendermanagement.util; + +import java.util.function.Consumer; +import java.util.function.Supplier; + +public class ObjectUtils { + + public static void setIfNotNull(Consumer setter, T value) { + if (value != null) { + setter.accept(value); + } + } + public static void setIfUpdated(Supplier getter, Consumer setter, T newValue) { + T currentValue = getter.get(); + if (newValue != null && !newValue.equals(currentValue)) { + setter.accept(newValue); + } + } + +} diff --git a/src/main/java/net/gepafin/tendermanagement/util/Utils.java b/src/main/java/net/gepafin/tendermanagement/util/Utils.java new file mode 100644 index 00000000..aa1fe35b --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/util/Utils.java @@ -0,0 +1,49 @@ +package net.gepafin.tendermanagement.util; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.stream.Collectors; + +public class Utils { + + public static final Logger log = LoggerFactory.getLogger(Utils.class); + + private static final ObjectMapper mapper = new ObjectMapper() + .registerModule(new JavaTimeModule()) + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + + public static U convertObject(T source, Class destinationClass) { + try { + return mapper.convertValue(source, destinationClass); + } catch (Exception e) { + log.error("Error converting object: " + e.getMessage(), e); + } + return null; + } + + public static List convertSourceListToDestinationList(List sourceList, Class destinationClass) { + try { + return sourceList.stream() + .map(source -> mapper.convertValue(source, destinationClass)) + .collect(Collectors.toList()); + } catch (Exception e) { + log.error("Error converting list: " + e.getMessage(), e); + } + return null; + } + + public static List convertSourceToList(T source, Class destinationClass) { + try { + // Convert single source object to a single-element list of destination type + return List.of(mapper.convertValue(source, destinationClass)); + } catch (Exception e) { + log.error("Error converting single object to list: " + e.getMessage(), e); + } + return null; + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/RegionApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/RegionApi.java new file mode 100644 index 00000000..3c9237a6 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/RegionApi.java @@ -0,0 +1,91 @@ +package net.gepafin.tendermanagement.web.rest.api; + +import net.gepafin.tendermanagement.entities.RegionEntity; +import net.gepafin.tendermanagement.model.request.RegionReq; +import net.gepafin.tendermanagement.model.response.RegionResponseBean; +import net.gepafin.tendermanagement.model.request.UpdateRegionReq; +import net.gepafin.tendermanagement.model.response.RoleResponseBean; +import net.gepafin.tendermanagement.model.util.Response; +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 io.swagger.v3.oas.annotations.Parameter; +import jakarta.validation.Valid; +import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@Validated +@RequestMapping("/region") +public interface RegionApi { + + @Operation(summary = "Api to create region", + 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> createRegion( + @Parameter(description = "Region request object", required = true) @Valid @RequestBody RegionReq regionReq); + + @Operation(summary = "Api to update region", + 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 = "/{regionId}", produces = "application/json") + ResponseEntity> updateRegion( + @Parameter(description = "The region id", required = true) @PathVariable("regionId") Long regionId, + @Parameter(description = "Region request object", required = true) @Valid @RequestBody RegionReq regionReq); + + @Operation(summary = "Api to get a region by 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 = "/{regionId}", produces = "application/json") + ResponseEntity> getRegionById( + @Parameter(description = "The region id", required = true) @PathVariable("regionId") Long regionId); + + @Operation(summary = "Api to get all regions", + 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 = "", + produces = { "application/json" }) + ResponseEntity>> getAllRegions(); + @Operation(summary = "Api to delete region", + 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 = "/{regionId}") + ResponseEntity> deleteRegion( + @Parameter(description = "The region id", required = true) @PathVariable("regionId") Long regionId); +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/RoleApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/RoleApi.java new file mode 100644 index 00000000..2f94be9e --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/RoleApi.java @@ -0,0 +1,93 @@ +package net.gepafin.tendermanagement.web.rest.api; + +import net.gepafin.tendermanagement.entities.RoleEntity; +import net.gepafin.tendermanagement.model.request.RoleReq; +import net.gepafin.tendermanagement.model.response.RoleResponseBean; +import net.gepafin.tendermanagement.model.util.Response; +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 io.swagger.v3.oas.annotations.Parameter; +import jakarta.validation.Valid; +import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@Validated +public interface RoleApi { + + @Operation(summary = "API to create role", + 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> createRole( + @Parameter(description = " Role request object", required = true) @Valid @RequestBody RoleReq roleReq); + + + @Operation(summary = "API to update role", + 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 = "/{roleId}", + produces = { "application/json" }) + ResponseEntity> updateRole( + @Parameter(description = "The role ID", required = true) @PathVariable("roleId") Long roleId, + @Parameter(description = "Role request object", required = true) @Valid @RequestBody RoleReq roleReq); + + @Operation(summary = "API to get role by 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 = "/{roleId}", + produces = { "application/json" }) + ResponseEntity> getRoleById( + @Parameter(description = "The role ID", required = true) @PathVariable("roleId") Long roleId); + + @Operation(summary = "API to get all roles", + 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 = "", + produces = { "application/json" }) + ResponseEntity>> getAllRoles(); + + @Operation(summary = "API to delete role", + 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 = "/{roleId}") + ResponseEntity> deleteRole( + @Parameter(description = "The role ID", required = true) @PathVariable("roleId") Long roleId); +} 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 e1e0f29a..3c9eadc6 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 @@ -1,8 +1,94 @@ package net.gepafin.tendermanagement.web.rest.api; -import net.gepafin.tendermanagement.model.User; -import org.springframework.web.bind.annotation.GetMapping; +import io.swagger.v3.oas.annotations.Parameter; +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.validation.Valid; +import net.gepafin.tendermanagement.model.request.UpdateUserReq; +import net.gepafin.tendermanagement.model.request.UserReq; +import net.gepafin.tendermanagement.model.response.UserResponseBean; +import net.gepafin.tendermanagement.model.util.Response; +import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +@Validated +//@RequestMapping("/user") public interface UserApi { - @GetMapping("") - User getUser(); + + @Operation(summary = "Api to create user", + 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) })) }) + @RequestMapping(value = "", + produces = { "application/json" }, + method = RequestMethod.POST) + default ResponseEntity> createUser( + @Parameter(description = "User request object", required = true) @Valid @RequestBody UserReq userReq) { + return new ResponseEntity>(HttpStatus.NOT_IMPLEMENTED); + } + + @Operation(summary = "Api to update user", + 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) })) }) + @RequestMapping(value = "/{userId}", + produces = { "application/json" }, + method = RequestMethod.PUT) + default ResponseEntity> updateUser( + @Parameter(description = "The user id", required = true) @PathVariable("userId") Long userId, + @Parameter(description = "User request object", required = true) @Valid @RequestBody UpdateUserReq userReq) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + } + + @Operation(summary = "Api to get user by 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) })) }) + @RequestMapping(value = "/{userId}", + produces = { "application/json" }, + method = RequestMethod.GET) + default ResponseEntity> getUserById( + @Parameter(description = "The user id", required = true) @PathVariable("userId") Long userId) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + } + + @Operation(summary = "Api to delete user", + 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) })) }) + @RequestMapping(value = "/{userId}", + method = RequestMethod.DELETE) + default ResponseEntity> deleteUser( + @Parameter(description = "The user id", required = true) @PathVariable("userId") Long userId) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + } } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/CustomValidationException.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/CustomValidationException.java new file mode 100644 index 00000000..197a4e2b --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/CustomValidationException.java @@ -0,0 +1,16 @@ +package net.gepafin.tendermanagement.web.rest.api.errors; + +public class CustomValidationException extends RuntimeException { + + private final Status status; + private static final long serialVersionUID = 1L; + + public Status getStatus() { + return status; + } + + public CustomValidationException(Status status, String message) { + super(message); + this.status = status; + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/ErrorConstants.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/ErrorConstants.java new file mode 100644 index 00000000..d48defba --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/ErrorConstants.java @@ -0,0 +1,28 @@ +package net.gepafin.tendermanagement.web.rest.api.errors; + +import java.net.URI; + +public final class ErrorConstants { + + public static final String ERR_CONCURRENCY_FAILURE = "error.concurrencyFailure"; + public static final String ERR_VALIDATION = "error.validation"; + public static final String PROBLEM_BASE_URL = "https://www.jhipster.tech/problem"; + public static final URI DEFAULT_TYPE = URI.create(PROBLEM_BASE_URL + "/problem-with-message"); + public static final URI CONSTRAINT_VIOLATION_TYPE = URI.create(PROBLEM_BASE_URL + "/constraint-violation"); + public static final URI INVALID_PASSWORD_TYPE = URI.create(PROBLEM_BASE_URL + "/invalid-password"); + public static final URI EMAIL_ALREADY_USED_TYPE = URI.create(PROBLEM_BASE_URL + "/email-already-used"); + public static final URI LOGIN_ALREADY_USED_TYPE = URI.create(PROBLEM_BASE_URL + "/login-already-used"); + + public static final String BADREQUEST_ERROR_EXAMPLE="{\"data\": null," + +"\"status\": \"VALIDATION_ERROR\",\"message\": \"string\"" + + "}"; + public static final String NOTFOUND_ERROR_EXAMPLE="{\"data\": null," + +"\"status\": \"NOT_FOUND\",\"message\": \"string\"" + + "}"; + public static final String UNAUTHORIZED_ERROR_EXAMPLE="{\"data\": null," + +"\"status\": \"UNAUTHORIZED\",\"message\": \"string\"" + + "}"; + + private ErrorConstants() { + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/ResourceNotFoundException.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/ResourceNotFoundException.java new file mode 100644 index 00000000..bdc1bcc0 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/ResourceNotFoundException.java @@ -0,0 +1,23 @@ +package net.gepafin.tendermanagement.web.rest.api.errors; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(value = HttpStatus.NOT_FOUND) +public class ResourceNotFoundException extends RuntimeException { + + /** + * + */ + private static final long serialVersionUID = 1L; +private final Status status; + + public ResourceNotFoundException(Status status, String message) { + super(message); + this.status = status; + } + + public Status getStatus() { + return status; + } +} \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/Status.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/Status.java new file mode 100644 index 00000000..dc713f3e --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/Status.java @@ -0,0 +1,16 @@ +package net.gepafin.tendermanagement.web.rest.api.errors; + +public enum Status { + SUCCESS("1"), VALIDATION_ERROR("2"), EXCEPTION_ERROR("3") , NOT_FOUND("4") , BAD_REQUEST("5") , UNAUTHORIZED("6") , + FORBIDDEN("7"), VALIDATION_COMPLETED("8"); + + private String action; + + public String getAction() { + return this.action; + } + + private Status(String action) { + this.action = action; + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/RegionApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/RegionApiController.java new file mode 100644 index 00000000..e7387562 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/RegionApiController.java @@ -0,0 +1,79 @@ +package net.gepafin.tendermanagement.web.rest.api.impl; + +import jakarta.validation.Valid; +import net.gepafin.tendermanagement.config.Translator; +import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.entities.RegionEntity; +import net.gepafin.tendermanagement.model.request.RegionReq; +import net.gepafin.tendermanagement.model.response.RegionResponseBean; +import net.gepafin.tendermanagement.model.request.UpdateRegionReq; +import net.gepafin.tendermanagement.model.util.Response; +import net.gepafin.tendermanagement.service.RegionService; +import net.gepafin.tendermanagement.web.rest.api.RegionApi; +import net.gepafin.tendermanagement.web.rest.api.errors.Status; +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.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +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/region}") +public class RegionApiController implements RegionApi { + + private final Logger log = LoggerFactory.getLogger(RegionApiController.class); + + @Autowired + private RegionService regionService; + + @Override + public ResponseEntity> createRegion( + @Valid @RequestBody RegionReq regionReq) { + log.info("Create Region - Request Body: {}", regionReq); + RegionResponseBean createdRegion = regionService.createRegion(regionReq); + return ResponseEntity.status(HttpStatus.CREATED) + .body(new Response<>(createdRegion, Status.SUCCESS, Translator.toLocale(GepafinConstant.REGION_CREATED_SUCCESS_MSG))); + } + + @Override + public ResponseEntity> updateRegion( + @PathVariable("regionId") Long regionId, + @Valid @RequestBody RegionReq regionReq) { + log.info("Update Region - Region ID: {}, Request Body: {}", regionId, regionReq); + RegionResponseBean updatedRegion = regionService.updateRegion(regionId, regionReq); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(updatedRegion, Status.SUCCESS, Translator.toLocale(GepafinConstant.REGION_UPDATED_SUCCESS_MSG))); + } + + @Override + public ResponseEntity> getRegionById( + @PathVariable("regionId") Long regionId) { + log.info("Get Region by ID - Region ID: {}", regionId); + RegionEntity region = regionService.getRegionById(regionId); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(region, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_REGION_SUCCESS_MSG))); + } + + @Override + public ResponseEntity> deleteRegion( + @PathVariable("regionId") Long regionId) { + log.info("Delete Region - Region ID: {}", regionId); + regionService.deleteRegion(regionId); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(null, Status.SUCCESS, Translator.toLocale(GepafinConstant.DELETE_REGION_SUCCESS_MSG))); + } + @Override + public ResponseEntity>> getAllRegions() { + List regions = regionService.getAllRegions(); + log.info("Get All Region"); + regionService.getAllRegions(); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(regions, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_REGION_SUCCESS_MSG))); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/RoleApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/RoleApiController.java new file mode 100644 index 00000000..a720bf3c --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/RoleApiController.java @@ -0,0 +1,75 @@ +package net.gepafin.tendermanagement.web.rest.api.impl; + +import java.util.List; + +import net.gepafin.tendermanagement.config.Translator; +import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.entities.RoleEntity; +import net.gepafin.tendermanagement.model.request.RoleReq; +import net.gepafin.tendermanagement.model.response.RoleResponseBean; +import net.gepafin.tendermanagement.model.util.Response; +import net.gepafin.tendermanagement.service.RoleService; +import net.gepafin.tendermanagement.web.rest.api.RoleApi; +import net.gepafin.tendermanagement.web.rest.api.errors.Status; +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; + +@RestController +@RequestMapping("${openapi.gepafin.base-path:/v1/role}") +public class RoleApiController implements RoleApi { + + private static final Logger log = LoggerFactory.getLogger(RoleApiController.class); + + @Autowired + private RoleService roleService; + @Override + public ResponseEntity> createRole(RoleReq body) { + log.info("Create Role - Request Body: {}", body); + RoleResponseBean roleReq = roleService.createRole(body); + + return ResponseEntity.status(HttpStatus.CREATED) + .body(new Response<>(roleReq, Status.SUCCESS, Translator.toLocale(GepafinConstant.ROLE_CREATED_SUCCESS_MSG))); + + } + + @Override + public ResponseEntity> updateRole(Long roleId, RoleReq body) { + log.info("Update Role - Role ID: {}, Request Body: {}", roleId, body); + RoleResponseBean updatedUserRole = roleService.updateRole(roleId, body); + + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(updatedUserRole, Status.SUCCESS, Translator.toLocale(GepafinConstant.ROLE_UPDATED_SUCCESS_MSG))); + } + + @Override + public ResponseEntity>> getAllRoles() { + log.info("Get All Roles"); + List roles = roleService.getAllRoles(); + + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(roles, Status.SUCCESS, Translator.toLocale(GepafinConstant.ROLE_FETCH_SUCCESS_MSG))); + + } + + @Override + public ResponseEntity> getRoleById(Long roleId) { + log.info("Get Role by ID - Role ID: {}", roleId); + RoleEntity roleEntity = roleService.getRoleById(roleId); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(roleEntity, Status.SUCCESS, Translator.toLocale(GepafinConstant.ROLE_FETCH_SUCCESS_MSG))); + } + + @Override + public ResponseEntity> deleteRole(Long roleId) { + log.info("Delete Role - Role ID: {}", roleId); + roleService.deleteRole(roleId); + + return ResponseEntity.status(HttpStatus.NO_CONTENT) + .body(new Response<>(null, Status.SUCCESS, Translator.toLocale(GepafinConstant.ROLE_DELETED_SUCCESS_MSG))); + } +} 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 4dbd4107..ad169e42 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 @@ -1,18 +1,72 @@ package net.gepafin.tendermanagement.web.rest.api.impl; -import net.gepafin.tendermanagement.model.User; +import jakarta.validation.Valid; +import net.gepafin.tendermanagement.config.Translator; +import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.model.request.UpdateUserReq; +import net.gepafin.tendermanagement.model.request.UserReq; +import net.gepafin.tendermanagement.model.response.UserResponseBean; +import net.gepafin.tendermanagement.model.util.Response; +import net.gepafin.tendermanagement.service.UserService; import net.gepafin.tendermanagement.web.rest.api.UserApi; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import net.gepafin.tendermanagement.web.rest.api.errors.Status; +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.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; @RestController -@RequestMapping("/v1/user") -public class UserApiController implements UserApi -{ +@RequestMapping("${openapi.gepafin.base-path:/v1/user}") +public class UserApiController implements UserApi { + + private final Logger log = LoggerFactory.getLogger(UserApiController.class); + + @Autowired + private UserService userService; @Override - public User getUser() { - return new User(1L, "John Doe", "john.doe@test.test"); + public ResponseEntity> createUser( + @Valid @RequestBody UserReq userReq) { + log.info("Create User with - Request Body: {}", userReq); + UserResponseBean createdUser = userService.createUser(userReq); + return ResponseEntity.status(HttpStatus.CREATED) + .body(new Response<>(createdUser, Status.SUCCESS, Translator.toLocale(GepafinConstant.USER_CREATED_SUCCESS_MSG))); + } + + @Override + public ResponseEntity> updateUser( + @PathVariable("userId") Long userId, + @Valid @RequestBody UpdateUserReq userReq) { + log.info("Update User - User ID: {}, Request Body: {}", userId, userReq); + UserResponseBean updatedUser = userService.updateUser(userId, userReq); + + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(updatedUser, Status.SUCCESS, Translator.toLocale(GepafinConstant.USER_UPDATED_SUCCESS_MSG))); + + } + + @Override + public ResponseEntity> getUserById( + @PathVariable("userId") Long userId) { + log.info("Get User by ID - User ID: {}", userId); + UserResponseBean user = userService.getUserById(userId); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(user, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_USER_SUCCESS_MSG))); + + } + + @Override + public ResponseEntity> deleteUser( + @PathVariable("userId") Long userId) { + log.info("Delete User By- User ID: {}", userId); + userService.deleteUser(userId); + + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(null, Status.SUCCESS, Translator.toLocale(GepafinConstant.USER_DELETED_SUCCESS_MSG))); + } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 9aa841e8..9126bd0a 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,3 +1,26 @@ spring.application.name=tendermanagement -server.port=8080 +springdoc.api-docs.path=/v1/api-docs +springdoc.swagger-ui.configUrl=/v1/api-docs +springfox.documentation.swagger-ui.path=/v1/api-docs +springdoc.swagger-ui.disable-swagger-default-url=true +springdoc.swagger-ui.path=/swagger-ui.html +# DataSource Configuration +spring.datasource.url=jdbc:postgresql://localhost:5432/gepafin_local +spring.datasource.username=postgres +spring.datasource.password=root +spring.datasource.driver-class-name=org.postgresql.Driver + +# JPA Configuration +spring.jpa.properties.hibernate.default_schema=gepafin_schema +spring.jpa.hibernate.ddl-auto=none + + +# Liquibase Configuration +spring.liquibase.change-log=classpath:db/changelog/db.changelog-master.xml +spring.liquibase.default-schema=gepafin_schema +spring.liquibase.enabled=true + +# Debugging and SQL Output +logging.level.org.springframework.boot.autoconfigure.liquibase=ERROR +logging.level.liquibase=ERROR \ No newline at end of file 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 new file mode 100644 index 00000000..20506096 --- /dev/null +++ b/src/main/resources/db/changelog/db.changelog-1.0.0.xml @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/db/changelog/db.changelog-master.xml b/src/main/resources/db/changelog/db.changelog-master.xml new file mode 100644 index 00000000..f44695c7 --- /dev/null +++ b/src/main/resources/db/changelog/db.changelog-master.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties new file mode 100644 index 00000000..bdbcf92b --- /dev/null +++ b/src/main/resources/message_en.properties @@ -0,0 +1,29 @@ +user.created.success=User created successfully. +user.updated.success=User updated successfully. +user.deleted.success=User deleted successfully. +user.not.found=User not found. +create_user_error_msg=An error occurred while creating the user. +update_user_error_msg=An error occurred while updating the user. +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. +# Role-related messages +role.created.success=Role created successfully. +role.updated.success=Role updated successfully. +role.deleted.success=Role deleted successfully. +role.not.found=Role not found. +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. + +# Region-related messages +region.created.success=Region created successfully. +region.updated.success=Region updated successfully. +get.region.success=Region fetched successfully. +delete.region.success=Region deleted successfully. +user.region.not.found=Region not found. +create.regiom.error=Error occurred while creating the region. +update.region.error=Error occurred while updating the region. +password.doesnt.match=Password and confirm password do not match. + diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties new file mode 100644 index 00000000..bfd0d8f3 --- /dev/null +++ b/src/main/resources/message_it.properties @@ -0,0 +1,28 @@ +user.created.success=Utente creato con successo. +user.updated.success=Utente aggiornato con successo. +user.deleted.success=Utente eliminato con successo. +user.not.found=Utente non trovato. +create_user_error_msg=Si è verificato un errore durante la creazione dell'utente. +update_user_error_msg=Si è verificato un errore durante l'aggiornamento dell'utente. +delete_user_error_msg=Si è verificato un errore durante l'eliminazione dell'utente. +get_user_success_msg=Utente recuperato con successo. +get_user_error_msg=Si è verificato un errore durante il recupero dell'utente. +# Role-related messages +role.created.success=Ruolo creato con successo. +role.updated.success=Ruolo aggiornato con successo. +role.deleted.success=Ruolo eliminato con successo. +role.not.found=Ruolo non trovato. +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. + +# Region-related messages +region.created.success=Regione creata con successo. +region.updated.success=Regione aggiornata con successo. +get.region.success=Regione recuperata con successo. +delete.region.success=Regione eliminata con successo. +user.region.not.found=Regione non trovata. +create.regiom.error=Errore durante la creazione della regione. +update.region.error=Errore durante l'aggiornamento della regione. +password.doesnt.match=La password e la conferma della password non corrispondono. diff --git a/target/classes/application.properties b/target/classes/application.properties deleted file mode 100644 index 9aa841e8..00000000 --- a/target/classes/application.properties +++ /dev/null @@ -1,3 +0,0 @@ -spring.application.name=tendermanagement -server.port=8080 - From 324490da698fc4f19f41f191eadb34e4e2894415 Mon Sep 17 00:00:00 2001 From: harish Date: Wed, 14 Aug 2024 15:34:46 +0530 Subject: [PATCH 2/9] Updated code --- .gitignore | 56 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/.gitignore b/.gitignore index 524f0963..219512a8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,24 +1,42 @@ -# Compiled class file -*.class +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ +### DS_Store ### +.DS_Store +/bin/ + -# Log file -*.log -# BlueJ files -*.ctxt -# Mobile Tools for Java (J2ME) -.mtj.tmp/ -# Package Files # -*.jar -*.war -*.nar -*.ear -*.zip -*.tar.gz -*.rar -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* -replay_pid* From 7a080504aaf238e4b06c6154966856c8278ce728 Mon Sep 17 00:00:00 2001 From: harish Date: Wed, 21 Aug 2024 18:21:20 +0530 Subject: [PATCH 3/9] Security implementation --- pom.xml | 24 ++++ .../config/SecurityConfig.java | 111 ++++++++++++++++++ .../config/jwt/JWTConfigurer.java | 23 ++++ .../config/jwt/JWTFilter.java | 43 +++++++ .../config/jwt/TokenProvider.java | 93 +++++++++++++++ .../constants/GepafinConstant.java | 4 + .../tendermanagement/dao/RegionDao.java | 2 +- .../gepafin/tendermanagement/dao/RoleDao.java | 10 +- .../gepafin/tendermanagement/dao/UserDao.java | 52 ++++++-- .../tendermanagement/model/BaseBean.java | 16 +++ .../model/request/LoginReq.java | 18 +++ .../model/request/UserReq.java | 16 +-- .../model/response/LoginResponse.java | 42 +++++++ .../model/response/RegionResponseBean.java | 6 +- .../model/response/RoleResponseBean.java | 8 +- .../model/response/UserResponseBean.java | 12 +- .../tendermanagement/model/util/JWTToken.java | 26 ++++ .../repositories/UserRepository.java | 2 + .../tendermanagement/service/UserService.java | 7 ++ .../service/impl/AuthenticationService.java | 60 ++++++++++ .../service/impl/RegionServiceImpl.java | 7 ++ .../service/impl/RoleServiceImpl.java | 6 + .../service/impl/UserServiceImpl.java | 17 ++- .../web/rest/api/UserApi.java | 43 ++++--- .../api/errors/GlobalExceptionHandler.java | 23 ++++ .../api/impl/CustomUserDetailsService.java | 55 +++++++++ .../web/rest/api/impl/UserApiController.java | 48 ++++---- src/main/resources/application.properties | 11 +- src/main/resources/message_en.properties | 7 ++ src/main/resources/message_it.properties | 7 ++ 30 files changed, 721 insertions(+), 78 deletions(-) create mode 100644 src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java create mode 100644 src/main/java/net/gepafin/tendermanagement/config/jwt/JWTConfigurer.java create mode 100644 src/main/java/net/gepafin/tendermanagement/config/jwt/JWTFilter.java create mode 100644 src/main/java/net/gepafin/tendermanagement/config/jwt/TokenProvider.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/BaseBean.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/request/LoginReq.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/response/LoginResponse.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/util/JWTToken.java create mode 100644 src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java create mode 100644 src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/GlobalExceptionHandler.java create mode 100644 src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CustomUserDetailsService.java diff --git a/pom.xml b/pom.xml index 1572627b..d2022b37 100644 --- a/pom.xml +++ b/pom.xml @@ -80,6 +80,30 @@ spring-boot-starter-test test + + org.springframework.boot + spring-boot-starter-security + + + io.jsonwebtoken + jjwt-api + 0.11.5 + + + io.jsonwebtoken + jjwt-impl + 0.11.5 + + + io.jsonwebtoken + jjwt-jackson + 0.11.5 + + + org.springframework.boot + spring-boot-starter-web + + diff --git a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java new file mode 100644 index 00000000..1c97a2de --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java @@ -0,0 +1,111 @@ +package net.gepafin.tendermanagement.config; + +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 net.gepafin.tendermanagement.config.jwt.JWTConfigurer; +import net.gepafin.tendermanagement.config.jwt.JWTFilter; +import net.gepafin.tendermanagement.config.jwt.TokenProvider; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; +import org.springframework.web.servlet.handler.HandlerMappingIntrospector; + +@Configuration +@EnableWebSecurity +public class SecurityConfig { + + private final TokenProvider tokenProvider; + + @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(); + } + + @Bean + MvcRequestMatcher.Builder mvc(HandlerMappingIntrospector introspector) { + return new MvcRequestMatcher.Builder(introspector); + } + + @Bean + public WebSecurityCustomizer webSecurityCustomizer(MvcRequestMatcher.Builder mvc) { + return (web) -> web.ignoring() + .requestMatchers(mvc.pattern(HttpMethod.OPTIONS, "/**")) + .requestMatchers(new AntPathRequestMatcher("/i18n/**")) + .requestMatchers(new AntPathRequestMatcher("/content/**")) + .requestMatchers(new AntPathRequestMatcher("/swagger-ui/index.html")) + .requestMatchers(new AntPathRequestMatcher("/swagger-ui/**")); + } + + @Bean + public CorsFilter corsFilter() { + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + CorsConfiguration config = new CorsConfiguration(); + config.setAllowCredentials(true); + config.addAllowedOrigin("*"); + config.addAllowedHeader("*"); + config.addAllowedMethod("*"); + source.registerCorsConfiguration("/**", config); + 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(mvc.pattern(HttpMethod.POST, "/v1/user")).permitAll() + .requestMatchers("/swagger-ui/**").permitAll() + .requestMatchers("/v1/api-docs/**").permitAll() + .anyRequest().authenticated() + ) + .sessionManagement(session -> session + .sessionCreationPolicy(SessionCreationPolicy.STATELESS) + ) + .apply(new JWTConfigurer(tokenProvider)) + .and() + .addFilterBefore(new JWTFilter(tokenProvider), UsernamePasswordAuthenticationFilter.class); + + return http.build(); + } + + @Bean + public OpenAPI customOpenAPI() { + return new OpenAPI() + .addServersItem(new Server().url("/")) + .addSecurityItem(new SecurityRequirement().addList("bearer-key")) + .components(new Components().addSecuritySchemes("bearer-key", + new SecurityScheme().type(SecurityScheme.Type.HTTP) + .scheme("bearer").bearerFormat("JWT"))); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/config/jwt/JWTConfigurer.java b/src/main/java/net/gepafin/tendermanagement/config/jwt/JWTConfigurer.java new file mode 100644 index 00000000..1ee7efe6 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/config/jwt/JWTConfigurer.java @@ -0,0 +1,23 @@ +package net.gepafin.tendermanagement.config.jwt; + +import org.springframework.security.config.annotation.SecurityConfigurerAdapter; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.web.DefaultSecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +public class JWTConfigurer extends SecurityConfigurerAdapter { + + public static final String AUTHORIZATION_HEADER = "Authorization"; + + private TokenProvider tokenProvider; + + public JWTConfigurer(TokenProvider tokenProvider) { + this.tokenProvider = tokenProvider; + } + + @Override + public void configure(HttpSecurity http) throws Exception { + JWTFilter customFilter = new JWTFilter(tokenProvider); + http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/config/jwt/JWTFilter.java b/src/main/java/net/gepafin/tendermanagement/config/jwt/JWTFilter.java new file mode 100644 index 00000000..4d8d5948 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/config/jwt/JWTFilter.java @@ -0,0 +1,43 @@ +package net.gepafin.tendermanagement.config.jwt; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.util.StringUtils; +import org.springframework.web.filter.GenericFilterBean; + +import java.io.IOException; + +public class JWTFilter extends GenericFilterBean { + + private final TokenProvider tokenProvider; + + public JWTFilter(TokenProvider tokenProvider) { + this.tokenProvider = tokenProvider; + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) + throws IOException, ServletException { + HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; + String token = resolveToken(httpServletRequest); + + if (StringUtils.hasText(token) && tokenProvider.validateToken(token)) { + Authentication authentication = tokenProvider.getAuthentication(token); + if (authentication != null) { + SecurityContextHolder.getContext().setAuthentication(authentication); + } + } + + filterChain.doFilter(servletRequest, servletResponse); + } + + private String resolveToken(HttpServletRequest request) { + String bearerToken = request.getHeader("Authorization"); + return StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ") ? bearerToken.substring(7) : null; + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/config/jwt/TokenProvider.java b/src/main/java/net/gepafin/tendermanagement/config/jwt/TokenProvider.java new file mode 100644 index 00000000..7ac7948e --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/config/jwt/TokenProvider.java @@ -0,0 +1,93 @@ +package net.gepafin.tendermanagement.config.jwt; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.security.Keys; +import jakarta.annotation.PostConstruct; +import org.apache.commons.lang3.time.DateUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.stereotype.Component; + +import javax.crypto.SecretKey; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.stream.Collectors; +@Component +public class TokenProvider { + private final Logger log = LoggerFactory.getLogger(TokenProvider.class); + + @Value("${security.authentication.jwt.secret}") + private String secretKey; + + @Value("${security.authentication.jwt.token-validity-in-seconds}") + private long tokenValidityInSeconds; + + private SecretKey key; + + @PostConstruct + public void init() { + this.key = Keys.hmacShaKeyFor(secretKey.getBytes(StandardCharsets.UTF_8)); + } + public String createToken(Authentication authentication,Boolean rememberMe) { + String authorities = authentication.getAuthorities().stream() + .map(GrantedAuthority::getAuthority) + .collect(Collectors.joining(",")); + Long now = null; + Date validity=null; + if(Boolean.TRUE.equals(rememberMe)) { + now= DateUtils.addMonths(new Date(), 2).getTime(); + validity = new Date(now); + }else { + now=(new Date()).getTime(); + validity = new Date(now + (this.tokenValidityInSeconds * 1000)); + } + return Jwts.builder() + .setSubject(authentication.getName()) + .claim("auth", authorities) + .signWith(key, SignatureAlgorithm.HS512) + .setExpiration(validity) + .compact(); + } + + public Authentication getAuthentication(String token) { + Claims claims = Jwts.parserBuilder() + .setSigningKey(key) + .build() + .parseClaimsJws(token) + .getBody(); + UserDetails principal = new User(claims.getSubject(), "", Collections.emptyList()); + + return new UsernamePasswordAuthenticationToken(principal, token, principal.getAuthorities()); + } + + + private Collection ClaimsToAuthorities(Object authClaim) { + return authClaim == null || ((String) authClaim).isEmpty() ? + Collections.emptyList() : + Arrays.stream(((String) authClaim).split(",")) + .map(SimpleGrantedAuthority::new) + .collect(Collectors.toList()); + } + + public boolean validateToken(String authToken) { + try { + Jwts.parserBuilder() + .setSigningKey(key) + .build() + .parseClaimsJws(authToken); + return true; + } catch (Exception e) { + log.info("Token validation failed: " + e.getMessage()); + return false; + } + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index 7d00913f..af5b5475 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -24,4 +24,8 @@ public class GepafinConstant { public static final String DELETE_REGION_SUCCESS_MSG = "delete.region.success"; public static final String REGION_NOT_FOUND_MSG = "user.region.not.found"; public static final String PASSWORD_DOESNT_MATCH ="password.doesnt.match"; + public static final String LOGIN_SUCCESS_MSG="login.successfully"; + public static final String PASSWORD_MIN_LEN ="pass.min.len.msg"; + public static final String EMAIL_ALREADY_EXISTS = "email.already.exists"; + } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/RegionDao.java b/src/main/java/net/gepafin/tendermanagement/dao/RegionDao.java index 27f7f250..3cc3d997 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/RegionDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/RegionDao.java @@ -50,7 +50,7 @@ public class RegionDao { regionEntity.setEducationLevel(regionReq.getEducationLevel()); return regionEntity; } - private RegionResponseBean convertRegionEntityToRegionResponse(RegionEntity regionEntity) { + public RegionResponseBean convertRegionEntityToRegionResponse(RegionEntity regionEntity) { RegionResponseBean regionResponseBean = new RegionResponseBean(); regionResponseBean.setId(regionEntity.getId()); regionResponseBean.setCreatedDate(regionEntity.getCreatedDate()); diff --git a/src/main/java/net/gepafin/tendermanagement/dao/RoleDao.java b/src/main/java/net/gepafin/tendermanagement/dao/RoleDao.java index 08c1a40f..fe25a923 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.RoleEntity; import net.gepafin.tendermanagement.model.request.RoleReq; +import net.gepafin.tendermanagement.model.response.RegionResponseBean; import net.gepafin.tendermanagement.model.response.RoleResponseBean; import net.gepafin.tendermanagement.repositories.RoleRepository; import net.gepafin.tendermanagement.service.RegionService; @@ -23,9 +24,13 @@ public class RoleDao { @Autowired private RoleRepository roleRepository; + @Autowired private RegionService regionService; + @Autowired + private RegionDao regionDao; + public RoleResponseBean createRole(RoleReq roleReq) { RoleEntity roleEntity = convertRoleRequestToRoleEntity(roleReq); roleEntity = roleRepository.save(roleEntity); @@ -39,7 +44,7 @@ public class RoleDao { roleEntity.setRegion(regionService.getRegionById(roleReq.getRegionId())); return roleEntity; } - private RoleResponseBean convertRoleEntityToRoleResponse(RoleEntity roleEntity) { + public RoleResponseBean convertRoleEntityToRoleResponse(RoleEntity roleEntity) { RoleResponseBean roleResponseBean=new RoleResponseBean(); roleResponseBean.setId(roleEntity.getId()); roleResponseBean.setCreatedDate(roleEntity.getCreatedDate()); @@ -47,7 +52,8 @@ public class RoleDao { roleResponseBean.setRoleName(roleEntity.getRoleName()); roleResponseBean.setDescription(roleEntity.getDescription()); roleResponseBean.setPermissions(roleEntity.getPermissions()); - roleResponseBean.setRegion(roleEntity.getRegion()); + RegionResponseBean regionResponseBean = regionDao.convertRegionEntityToRegionResponse(roleEntity.getRegion()); + roleResponseBean.setRegion(regionResponseBean); return roleResponseBean; } public RoleResponseBean updateRole(Long id, RoleReq roleReq) { diff --git a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java index 63a7c353..eecdd4e0 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java @@ -1,33 +1,53 @@ package net.gepafin.tendermanagement.dao; import net.gepafin.tendermanagement.config.Translator; +import net.gepafin.tendermanagement.config.jwt.TokenProvider; import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.entities.RoleEntity; 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.model.response.LoginResponse; +import net.gepafin.tendermanagement.model.response.RoleResponseBean; 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.RoleService; +import net.gepafin.tendermanagement.service.impl.AuthenticationService; 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; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Repository; import static net.gepafin.tendermanagement.util.ObjectUtils.setIfUpdated; - @Repository public class UserDao { + @Autowired private UserRepository userRepository; - + @Autowired + private AuthenticationService authService; @Autowired private RoleService roleService; + @Autowired + private PasswordEncoder passwordEncoder; + + @Autowired + private RoleDao roleDao; + public UserResponseBean createUser(UserReq userReq) { + if (userRepository.existsByEmail(userReq.getEmail())) { + throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.EMAIL_ALREADY_EXISTS)); + } if (!userReq.getPassword().equals(userReq.getConfPassword())) { - throw new CustomValidationException(Status.VALIDATION_ERROR,Translator.toLocale(GepafinConstant.PASSWORD_DOESNT_MATCH)); + throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.PASSWORD_DOESNT_MATCH)); + } + if (userReq.getPassword().length() < 8) { + throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.PASSWORD_MIN_LEN)); } UserEntity userEntity = convertUserRequestToUserEntity(userReq); userEntity = userRepository.save(userEntity); @@ -53,15 +73,15 @@ public class UserDao { private UserEntity convertUserRequestToUserEntity(UserReq userReq) { UserEntity userEntity = new UserEntity(); - userEntity.setPassword(userReq.getPassword()); - userEntity.setEmail(userReq.getEmail()); - userEntity.setFirstName(userReq.getFirstName()); - userEntity.setStatus(userReq.getStatus()); - userEntity.setLastName(userReq.getLastName()); - userEntity.setOrganization(userReq.getOrganization()); - userEntity.setAddress(userReq.getAddress()); - userEntity.setPhoneNumber(userReq.getPhoneNumber()); - userEntity.setRoleEntity(roleService.getRoleById(userReq.getRoleId())); + userEntity.setPassword(passwordEncoder.encode(userReq.getPassword())); + userEntity.setEmail(userReq.getEmail()); + userEntity.setFirstName(userReq.getFirstName()); + userEntity.setStatus(userReq.getStatus()); + userEntity.setLastName(userReq.getLastName()); + userEntity.setOrganization(userReq.getOrganization()); + userEntity.setAddress(userReq.getAddress()); + userEntity.setPhoneNumber(userReq.getPhoneNumber()); + userEntity.setRoleEntity(roleService.getRoleById(userReq.getRoleId())); return userEntity; } @@ -80,7 +100,8 @@ public class UserDao { userResponseBean.setCity(userEntity.getCity()); userResponseBean.setCountry(userEntity.getCountry()); userResponseBean.setStatus(userEntity.getStatus()); - userResponseBean.setRole(userEntity.getRoleEntity()); + RoleResponseBean roleResponseBean = roleDao.convertRoleEntityToRoleResponse(userEntity.getRoleEntity()); + userResponseBean.setRole(roleResponseBean); userResponseBean.setLastLogin(userEntity.getLastLogin()); return userResponseBean; } @@ -96,4 +117,9 @@ public class UserDao { .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND,Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG))); userRepository.deleteById(id); } + + + public JWTToken login(LoginReq loginReq) { + return authService.login(loginReq); + } } diff --git a/src/main/java/net/gepafin/tendermanagement/model/BaseBean.java b/src/main/java/net/gepafin/tendermanagement/model/BaseBean.java new file mode 100644 index 00000000..49eb0d41 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/BaseBean.java @@ -0,0 +1,16 @@ +package net.gepafin.tendermanagement.model; + +import java.time.LocalDateTime; + +import lombok.Data; + +@Data +public class BaseBean { + + private Long id; + + private LocalDateTime createdDate; + + private LocalDateTime updatedDate; + +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/LoginReq.java b/src/main/java/net/gepafin/tendermanagement/model/request/LoginReq.java new file mode 100644 index 00000000..d337d231 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/LoginReq.java @@ -0,0 +1,18 @@ +package net.gepafin.tendermanagement.model.request; + +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class LoginReq { + @NotBlank(message = "{email.not.blank}") + @Email(message = "{email.invalid}") + private String email; + @NotEmpty + private String password; + private Boolean rememberMe; +} 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 f866ac99..d7d7041b 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/request/UserReq.java +++ b/src/main/java/net/gepafin/tendermanagement/model/request/UserReq.java @@ -3,6 +3,7 @@ package net.gepafin.tendermanagement.model.request; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonValue; import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import lombok.Getter; @@ -14,19 +15,20 @@ import java.time.LocalDateTime; @Setter public class UserReq { - - private String password; - - private String confPassword; - + @NotBlank(message = "{email.not.blank}") + @Email(message = "{email.invalid}") private String email; + @NotEmpty + private String password; + @NotEmpty + private String confPassword; private String firstName; private String lastName; private String phoneNumber; - + @NotEmpty private Long roleId; private String organization; @@ -39,6 +41,4 @@ public class UserReq { private String status; - private LocalDateTime lastLogin; - } diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/LoginResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/LoginResponse.java new file mode 100644 index 00000000..64af6b1a --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/LoginResponse.java @@ -0,0 +1,42 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.time.LocalDateTime; + +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +public class LoginResponse { + private Long id; + + private String email; + + private String firstName; + + private String lastName; + + private RoleResponseBean role; + + private String phoneNumber; + + private String organization; + + private String address; + + private String city; + + private String country; + + private String status; + + private LocalDateTime lastLogin; + + private LocalDateTime createdDate; + + private LocalDateTime updatedDate; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/RegionResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/RegionResponseBean.java index c16d4c94..55182822 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/RegionResponseBean.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/RegionResponseBean.java @@ -2,14 +2,14 @@ package net.gepafin.tendermanagement.model.response; import lombok.Getter; import lombok.Setter; +import net.gepafin.tendermanagement.model.BaseBean; import java.math.BigDecimal; import java.time.LocalDateTime; @Getter @Setter -public class RegionResponseBean { - private Long id; +public class RegionResponseBean extends BaseBean { private String regionName; private String description; private String country; @@ -23,6 +23,4 @@ public class RegionResponseBean { private BigDecimal educationLevel; private BigDecimal healthcareAccess; private BigDecimal environmentalScore; - private LocalDateTime createdDate; - private LocalDateTime updatedDate; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/RoleResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/RoleResponseBean.java index 1e708b58..d5d579e5 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/RoleResponseBean.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/RoleResponseBean.java @@ -4,16 +4,14 @@ import lombok.Data; import lombok.Getter; import lombok.Setter; import net.gepafin.tendermanagement.entities.RegionEntity; +import net.gepafin.tendermanagement.model.BaseBean; import java.time.LocalDateTime; @Data -public class RoleResponseBean { - private Long id; +public class RoleResponseBean extends BaseBean { private String roleName; private String description; - private LocalDateTime createdDate; - private LocalDateTime updatedDate; private String permissions; - private RegionEntity region; + private RegionResponseBean region; } 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 2c036804..1dcaa944 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/UserResponseBean.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/UserResponseBean.java @@ -6,22 +6,23 @@ import jakarta.validation.constraints.NotNull; import lombok.Getter; import lombok.Setter; import net.gepafin.tendermanagement.entities.RoleEntity; +import net.gepafin.tendermanagement.model.BaseBean; import java.time.LocalDateTime; @Getter @Setter -public class UserResponseBean { - private Long id; +public class UserResponseBean extends BaseBean { + private String email; private String firstName; private String lastName; - private String phoneNumber; + private RoleResponseBean role; - private RoleEntity role; + private String phoneNumber; private String organization; @@ -35,7 +36,4 @@ public class UserResponseBean { private LocalDateTime lastLogin; - private LocalDateTime createdDate; - - private LocalDateTime updatedDate; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/util/JWTToken.java b/src/main/java/net/gepafin/tendermanagement/model/util/JWTToken.java new file mode 100644 index 00000000..53596d25 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/util/JWTToken.java @@ -0,0 +1,26 @@ +package net.gepafin.tendermanagement.model.util; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import net.gepafin.tendermanagement.model.response.LoginResponse; +import net.gepafin.tendermanagement.model.response.UserResponseBean; + +/** + * JWTToken + */ +@Data +public class JWTToken { + @JsonProperty("token") + private String token; + + @JsonProperty("user") + private LoginResponse loginResponse; + public JWTToken(String token, LoginResponse loginResponse) { + this.token = token; + this.loginResponse = loginResponse; + } + +} + diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java index 2fdee718..dc0aad37 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java @@ -6,4 +6,6 @@ import org.springframework.data.jpa.repository.JpaRepository; import java.util.Optional; public interface UserRepository extends JpaRepository { + UserEntity findByEmail(String email); + boolean existsByEmail(String email); } diff --git a/src/main/java/net/gepafin/tendermanagement/service/UserService.java b/src/main/java/net/gepafin/tendermanagement/service/UserService.java index 71faf129..68912240 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/UserService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/UserService.java @@ -1,12 +1,19 @@ package net.gepafin.tendermanagement.service; +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.model.response.UserResponseBean; +import net.gepafin.tendermanagement.model.util.JWTToken; public interface UserService { UserResponseBean createUser(UserReq userReq); + UserResponseBean updateUser(Long userId, UpdateUserReq userReq); + UserResponseBean getUserById(Long userId); + void deleteUser(Long userId); + + JWTToken login(LoginReq loginReq); } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java b/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java new file mode 100644 index 00000000..1b5137ce --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java @@ -0,0 +1,60 @@ +package net.gepafin.tendermanagement.service.impl; + +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.UserEntity; +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.util.JWTToken; +import net.gepafin.tendermanagement.repositories.UserRepository; +import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; +import net.gepafin.tendermanagement.web.rest.api.errors.Status; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; + +import java.util.Collections; + +@Service +public class AuthenticationService { + + private final TokenProvider tokenProvider; + private final AuthenticationManager authenticationManager; + + @Autowired + private UserRepository userRepository; + @Autowired + private PasswordEncoder passwordEncoder; + @Autowired + private RoleDao roleDao; + + @Autowired + public AuthenticationService(TokenProvider tokenProvider, AuthenticationManager authenticationManager) { + this.tokenProvider = tokenProvider; + this.authenticationManager = authenticationManager; + } + + public JWTToken login(LoginReq loginReq) { + UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginReq.getEmail(),loginReq.getPassword()); + Authentication authentication = this.authenticationManager.authenticate(authenticationToken); + SecurityContextHolder.getContext().setAuthentication(authentication); + String token = tokenProvider.createToken(authentication,loginReq.getRememberMe()); + UserEntity user = userRepository.findByEmail(loginReq.getEmail()); + if (user == null) { + throw new CustomValidationException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG)); + } + RoleResponseBean roleResponseBean = roleDao.convertRoleEntityToRoleResponse(user.getRoleEntity()); + return new JWTToken(token, new LoginResponse(user.getId(),user.getEmail(), + user.getFirstName(),user.getLastName(),roleResponseBean, user.getPhoneNumber(), user.getAddress(), user.getOrganization(), user.getCountry(),user.getStatus() + ,user.getCity(),user.getLastLogin(),user.getCreatedDate(),user.getUpdatedDate())); + } + } + + diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/RegionServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/RegionServiceImpl.java index 63921ef1..345362d3 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/RegionServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/RegionServiceImpl.java @@ -10,6 +10,8 @@ import net.gepafin.tendermanagement.model.request.UpdateRegionReq; import net.gepafin.tendermanagement.service.RegionService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + @Service public class RegionServiceImpl implements RegionService { @@ -17,26 +19,31 @@ public class RegionServiceImpl implements RegionService { private RegionDao regionDao; @Override + @Transactional(rollbackFor = Exception.class) public RegionResponseBean createRegion(RegionReq regionReq) { return regionDao.createRegion(regionReq); } @Override + @Transactional(rollbackFor = Exception.class) public RegionResponseBean updateRegion(Long regionId, RegionReq regionReq) { return regionDao.updateRegion(regionId,regionReq); } @Override + @Transactional(readOnly = true) public RegionEntity getRegionById(Long regionId) { return regionDao.getRegionById(regionId); } @Override + @Transactional(rollbackFor = Exception.class) public void deleteRegion(Long regionId) { regionDao.deleteById(regionId); } @Override + @Transactional(readOnly = true) public List getAllRegions() { return regionDao.getAllRegions(); } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/RoleServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/RoleServiceImpl.java index 41f3f6ba..9f66415a 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/RoleServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/RoleServiceImpl.java @@ -9,6 +9,7 @@ import net.gepafin.tendermanagement.model.response.RoleResponseBean; import net.gepafin.tendermanagement.service.RoleService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service @@ -18,25 +19,30 @@ public class RoleServiceImpl implements RoleService { private RoleDao roleDao; @Override + @Transactional(rollbackFor = Exception.class) public RoleResponseBean createRole(RoleReq roleReq) { return roleDao.createRole(roleReq); } @Override + @Transactional(rollbackFor = Exception.class) public RoleResponseBean updateRole(Long roleId, RoleReq roleReq) { return roleDao.updateRole(roleId,roleReq); } @Override + @Transactional(readOnly = true) public RoleEntity getRoleById(Long roleId) { return roleDao.getRoleById(roleId); } @Override + @Transactional(rollbackFor = Exception.class) public void deleteRole(Long roleId) { roleDao.deleteById(roleId); } @Override + @Transactional(readOnly = true) public List getAllRoles() { return roleDao.getAllRoles(); 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 4d39ffc5..c6205aae 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java @@ -1,12 +1,16 @@ package net.gepafin.tendermanagement.service.impl; import net.gepafin.tendermanagement.dao.UserDao; +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.model.response.LoginResponse; import net.gepafin.tendermanagement.model.response.UserResponseBean; +import net.gepafin.tendermanagement.model.util.JWTToken; import net.gepafin.tendermanagement.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.time.format.DateTimeFormatter; @@ -15,24 +19,35 @@ public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; + + @Transactional(rollbackFor = Exception.class) public UserResponseBean createUser(UserReq userReq) { return userDao.createUser(userReq); } @Override + @Transactional(rollbackFor = Exception.class) public UserResponseBean updateUser(Long userId, UpdateUserReq userReq) { return userDao.updateUser(userId, userReq); } @Override + @Transactional(readOnly = true) public UserResponseBean getUserById(Long userId) { return userDao.getUserById(userId); } @Override + @Transactional(rollbackFor = Exception.class) public void deleteUser(Long userId) { userDao.deleteUser(userId); } -} + @Override + public JWTToken login(LoginReq loginReq) { + return userDao.login(loginReq); + + } + +} \ No newline at end of file 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 3c9eadc6..beae1296 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 @@ -6,9 +6,11 @@ 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.validation.Valid; +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.model.response.UserResponseBean; +import net.gepafin.tendermanagement.model.util.JWTToken; import net.gepafin.tendermanagement.model.util.Response; import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants; import org.springframework.http.HttpStatus; @@ -28,13 +30,13 @@ public interface UserApi { 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) })), + @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) })), + @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) })) }) + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE)}))}) @RequestMapping(value = "", - produces = { "application/json" }, + produces = {"application/json"}, method = RequestMethod.POST) default ResponseEntity> createUser( @Parameter(description = "User request object", required = true) @Valid @RequestBody UserReq userReq) { @@ -45,13 +47,13 @@ public interface UserApi { 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) })), + @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) })), + @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) })) }) + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE)}))}) @RequestMapping(value = "/{userId}", - produces = { "application/json" }, + produces = {"application/json"}, method = RequestMethod.PUT) default ResponseEntity> updateUser( @Parameter(description = "The user id", required = true) @PathVariable("userId") Long userId, @@ -63,13 +65,13 @@ public interface UserApi { 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) })), + @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) })), + @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) })) }) + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE)}))}) @RequestMapping(value = "/{userId}", - produces = { "application/json" }, + produces = {"application/json"}, method = RequestMethod.GET) default ResponseEntity> getUserById( @Parameter(description = "The user id", required = true) @PathVariable("userId") Long userId) { @@ -80,15 +82,26 @@ public interface UserApi { 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) })), + @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) })), + @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) })) }) + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE)}))}) @RequestMapping(value = "/{userId}", method = RequestMethod.DELETE) default ResponseEntity> deleteUser( @Parameter(description = "The user id", required = true) @PathVariable("userId") Long userId) { return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); } + + @Operation(summary = "Api to login user", + responses = { + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "400", description = "Bad Request"), + @ApiResponse(responseCode = "401", description = "Unauthorized")}) + @RequestMapping(value = "/login", + produces = {"application/json"}, + method = RequestMethod.POST) + ResponseEntity> login( + @Parameter(description = "Login request object", required = true) @Valid @RequestBody LoginReq loginReq); } 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 new file mode 100644 index 00000000..6a6b00ef --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/errors/GlobalExceptionHandler.java @@ -0,0 +1,23 @@ +package net.gepafin.tendermanagement.web.rest.api.errors; + +import net.gepafin.tendermanagement.model.util.Response; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.http.ResponseEntity; + +@ControllerAdvice +public class GlobalExceptionHandler { + + @ExceptionHandler(CustomValidationException.class) + public ResponseEntity> handleCustomValidationException(CustomValidationException ex) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(new Response<>(null, ex.getStatus(), ex.getMessage())); + } + + @ExceptionHandler(ResourceNotFoundException.class) + public ResponseEntity> handleResourceNotFoundException(ResourceNotFoundException ex) { + return ResponseEntity.status(HttpStatus.NOT_FOUND) + .body(new Response<>(null, ex.getStatus(), ex.getMessage())); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CustomUserDetailsService.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CustomUserDetailsService.java new file mode 100644 index 00000000..102a388c --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CustomUserDetailsService.java @@ -0,0 +1,55 @@ +package net.gepafin.tendermanagement.web.rest.api.impl; + +import net.gepafin.tendermanagement.entities.RoleEntity; +import net.gepafin.tendermanagement.entities.UserEntity; +import net.gepafin.tendermanagement.repositories.RoleRepository; +import net.gepafin.tendermanagement.repositories.UserRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Collections; + +@Service +public class CustomUserDetailsService implements UserDetailsService { + + private final Logger log = LoggerFactory.getLogger(CustomUserDetailsService.class); + + private final UserRepository userRepository; + private final RoleRepository roleRepository; + + public CustomUserDetailsService(UserRepository userRepository, RoleRepository roleRepository) { + this.userRepository = userRepository; + this.roleRepository = roleRepository; + } + + @Override + @Transactional + public UserDetails loadUserByUsername(final String email) throws UsernameNotFoundException { + log.debug("Authenticating {}", email); + + UserEntity user = userRepository.findByEmail(email); + if (user == null) { + throw new UsernameNotFoundException("User " + email + " was not found in the database"); + } + + return createSpringSecurityUser(user); + } + + private org.springframework.security.core.userdetails.User createSpringSecurityUser(UserEntity user) { + RoleEntity role = user.getRoleEntity(); + GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(role.getRoleName()); + + return new org.springframework.security.core.userdetails.User( + user.getEmail(), + user.getPassword(), + Collections.singletonList(grantedAuthority) + ); + } +} 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 ad169e42..caf3c61a 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 @@ -3,14 +3,16 @@ package net.gepafin.tendermanagement.web.rest.api.impl; import jakarta.validation.Valid; import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.constants.GepafinConstant; +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.model.response.UserResponseBean; +import net.gepafin.tendermanagement.model.util.JWTToken; import net.gepafin.tendermanagement.model.util.Response; import net.gepafin.tendermanagement.service.UserService; import net.gepafin.tendermanagement.web.rest.api.UserApi; -import net.gepafin.tendermanagement.web.rest.api.errors.Status; +import net.gepafin.tendermanagement.web.rest.api.errors.Status; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -21,6 +23,7 @@ import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("${openapi.gepafin.base-path:/v1/user}") +@Validated public class UserApiController implements UserApi { private final Logger log = LoggerFactory.getLogger(UserApiController.class); @@ -31,42 +34,45 @@ public class UserApiController implements UserApi { @Override public ResponseEntity> createUser( @Valid @RequestBody UserReq userReq) { - log.info("Create User with - Request Body: {}", userReq); - UserResponseBean createdUser = userService.createUser(userReq); - return ResponseEntity.status(HttpStatus.CREATED) - .body(new Response<>(createdUser, Status.SUCCESS, Translator.toLocale(GepafinConstant.USER_CREATED_SUCCESS_MSG))); + log.info("Create User with - Request Body: {}", userReq); + UserResponseBean createdUser = userService.createUser(userReq); + return ResponseEntity.status(HttpStatus.CREATED) + .body(new Response<>(createdUser, Status.SUCCESS, Translator.toLocale(GepafinConstant.USER_CREATED_SUCCESS_MSG))); } @Override public ResponseEntity> updateUser( @PathVariable("userId") Long userId, @Valid @RequestBody UpdateUserReq userReq) { - log.info("Update User - User ID: {}, Request Body: {}", userId, userReq); - UserResponseBean updatedUser = userService.updateUser(userId, userReq); - - return ResponseEntity.status(HttpStatus.OK) - .body(new Response<>(updatedUser, Status.SUCCESS, Translator.toLocale(GepafinConstant.USER_UPDATED_SUCCESS_MSG))); - + log.info("Update User - User ID: {}, Request Body: {}", userId, userReq); + UserResponseBean updatedUser = userService.updateUser(userId, userReq); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(updatedUser, Status.SUCCESS, Translator.toLocale(GepafinConstant.USER_UPDATED_SUCCESS_MSG))); } @Override public ResponseEntity> getUserById( @PathVariable("userId") Long userId) { - log.info("Get User by ID - User ID: {}", userId); - UserResponseBean user = userService.getUserById(userId); - return ResponseEntity.status(HttpStatus.OK) - .body(new Response<>(user, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_USER_SUCCESS_MSG))); - + log.info("Get User by ID - User ID: {}", userId); + UserResponseBean user = userService.getUserById(userId); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(user, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_USER_SUCCESS_MSG))); } @Override public ResponseEntity> deleteUser( @PathVariable("userId") Long userId) { - log.info("Delete User By- User ID: {}", userId); - userService.deleteUser(userId); - - return ResponseEntity.status(HttpStatus.OK) - .body(new Response<>(null, Status.SUCCESS, Translator.toLocale(GepafinConstant.USER_DELETED_SUCCESS_MSG))); + log.info("Delete User - User ID: {}", userId); + userService.deleteUser(userId); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(null, Status.SUCCESS, Translator.toLocale(GepafinConstant.USER_DELETED_SUCCESS_MSG))); + } + @Override + public ResponseEntity> login( + @Valid @RequestBody LoginReq loginReq) { + log.info("User login attempt "); + JWTToken jwtToken = userService.login(loginReq); + return ResponseEntity.ok(new Response<>(jwtToken, Status.SUCCESS, Translator.toLocale(GepafinConstant.LOGIN_SUCCESS_MSG))); } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 9126bd0a..54a465f5 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -23,4 +23,13 @@ spring.liquibase.enabled=true # Debugging and SQL Output logging.level.org.springframework.boot.autoconfigure.liquibase=ERROR -logging.level.liquibase=ERROR \ No newline at end of file +logging.level.liquibase=ERROR +# JWT configuration +# 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 + + +spring.main.allow-circular-references=true + + diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index bdbcf92b..3149b6fc 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -27,3 +27,10 @@ create.regiom.error=Error occurred while creating the region. update.region.error=Error occurred while updating the region. password.doesnt.match=Password and confirm password do not match. +login.successfully=Login successfully. +pass.min.len.msg=Password must be at least 8 characters long. +email.already.exists=A user with this email already exists. + + + + diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index bfd0d8f3..d6b29447 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -26,3 +26,10 @@ user.region.not.found=Regione non trovata. create.regiom.error=Errore durante la creazione della regione. update.region.error=Errore durante l'aggiornamento della regione. password.doesnt.match=La password e la conferma della password non corrispondono. + +# Login-related messages +login.successfully=Accesso effettuato con successo. +pass.min.len.msg=La password deve essere lunga almeno 8 caratteri. +email.already.exists=Esiste già un utente con questa email. + + From fa714faef96c4beab0f96b9cc2deaf842b6759a5 Mon Sep 17 00:00:00 2001 From: rajesh Date: Wed, 21 Aug 2024 19:34:15 +0530 Subject: [PATCH 4/9] updated swagger configation --- src/main/resources/application-dev.properties | 8 ++++++ .../resources/application-local.properties | 8 ++++++ .../resources/application-testing.properties | 7 +++++ src/main/resources/application.properties | 26 +++++++++---------- 4 files changed, 36 insertions(+), 13 deletions(-) create mode 100644 src/main/resources/application-dev.properties create mode 100644 src/main/resources/application-local.properties create mode 100644 src/main/resources/application-testing.properties diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties new file mode 100644 index 00000000..72135766 --- /dev/null +++ b/src/main/resources/application-dev.properties @@ -0,0 +1,8 @@ +# DataSource Configuration +spring.datasource.url=jdbc:postgresql://dbstaging.memento.credit:20184/gepaDb +spring.datasource.username=usergepa +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 diff --git a/src/main/resources/application-local.properties b/src/main/resources/application-local.properties new file mode 100644 index 00000000..7ed5944b --- /dev/null +++ b/src/main/resources/application-local.properties @@ -0,0 +1,8 @@ +# DataSource Configuration +spring.datasource.url=jdbc:postgresql://localhost:5432/gepafin_local +spring.datasource.username=postgres +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 diff --git a/src/main/resources/application-testing.properties b/src/main/resources/application-testing.properties new file mode 100644 index 00000000..ea3a5732 --- /dev/null +++ b/src/main/resources/application-testing.properties @@ -0,0 +1,7 @@ +# DataSource Configuration +spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1 +spring.datasource.username=sa +spring.datasource.password=sa + +# JPA Configuration +spring.h2.console.enabled=true \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 9126bd0a..f72dc2c4 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,26 +1,26 @@ spring.application.name=tendermanagement -springdoc.api-docs.path=/v1/api-docs -springdoc.swagger-ui.configUrl=/v1/api-docs -springfox.documentation.swagger-ui.path=/v1/api-docs -springdoc.swagger-ui.disable-swagger-default-url=true -springdoc.swagger-ui.path=/swagger-ui.html -# DataSource Configuration -spring.datasource.url=jdbc:postgresql://localhost:5432/gepafin_local -spring.datasource.username=postgres -spring.datasource.password=root -spring.datasource.driver-class-name=org.postgresql.Driver +# Multipart Configuration +spring.servlet.multipart.max-file-size=50MB +spring.servlet.multipart.max-request-size=50MB + +spring.profiles.active=testing + # JPA Configuration spring.jpa.properties.hibernate.default_schema=gepafin_schema spring.jpa.hibernate.ddl-auto=none +spring.jpa.show-sql=false # Liquibase Configuration spring.liquibase.change-log=classpath:db/changelog/db.changelog-master.xml spring.liquibase.default-schema=gepafin_schema -spring.liquibase.enabled=true +spring.liquibase.enabled=true + # Debugging and SQL Output -logging.level.org.springframework.boot.autoconfigure.liquibase=ERROR -logging.level.liquibase=ERROR \ No newline at end of file + +# Swagger Configuration +springdoc.api-docs.path=/v1/api-docs + From 04e9ff57a7bf4c65d548079789edaf6722a341e5 Mon Sep 17 00:00:00 2001 From: harish Date: Wed, 21 Aug 2024 19:54:27 +0530 Subject: [PATCH 5/9] Add Logger --- .../config/jwt/TokenProvider.java | 39 +++++++---- .../tendermanagement/dao/RegionDao.java | 56 ++++++++++------ .../gepafin/tendermanagement/dao/RoleDao.java | 66 +++++++++++++------ .../gepafin/tendermanagement/dao/UserDao.java | 34 ++++++++-- .../service/impl/AuthenticationService.java | 45 ++++++++----- 5 files changed, 164 insertions(+), 76 deletions(-) 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 7ac7948e..1964bd1c 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/jwt/TokenProvider.java +++ b/src/main/java/net/gepafin/tendermanagement/config/jwt/TokenProvider.java @@ -36,26 +36,35 @@ public class TokenProvider { @PostConstruct public void init() { this.key = Keys.hmacShaKeyFor(secretKey.getBytes(StandardCharsets.UTF_8)); + log.info("JWT Secret Key initialized."); } - public String createToken(Authentication authentication,Boolean rememberMe) { + + public String createToken(Authentication authentication, Boolean rememberMe) { String authorities = authentication.getAuthorities().stream() .map(GrantedAuthority::getAuthority) .collect(Collectors.joining(",")); - Long now = null; - Date validity=null; - if(Boolean.TRUE.equals(rememberMe)) { - now= DateUtils.addMonths(new Date(), 2).getTime(); + Long now; + Date validity; + + if (Boolean.TRUE.equals(rememberMe)) { + now = DateUtils.addMonths(new Date(), 2).getTime(); validity = new Date(now); - }else { - now=(new Date()).getTime(); + log.info("Creating token with extended validity for 2 months."); + } else { + now = (new Date()).getTime(); validity = new Date(now + (this.tokenValidityInSeconds * 1000)); + log.info("Creating token with standard validity of {} seconds.", this.tokenValidityInSeconds); } - return Jwts.builder() + + String token = Jwts.builder() .setSubject(authentication.getName()) .claim("auth", authorities) .signWith(key, SignatureAlgorithm.HS512) .setExpiration(validity) .compact(); + + log.debug("Generated token: {}", token); + return token; } public Authentication getAuthentication(String token) { @@ -64,18 +73,21 @@ public class TokenProvider { .build() .parseClaimsJws(token) .getBody(); - UserDetails principal = new User(claims.getSubject(), "", Collections.emptyList()); - return new UsernamePasswordAuthenticationToken(principal, token, principal.getAuthorities()); + UserDetails principal = new User(claims.getSubject(), "", Collections.emptyList()); + log.info("Authenticated user: {}", claims.getSubject()); + + return new UsernamePasswordAuthenticationToken(principal, token, ClaimsToAuthorities(claims.get("auth"))); } - private Collection ClaimsToAuthorities(Object authClaim) { - return authClaim == null || ((String) authClaim).isEmpty() ? + Collection authorities = authClaim == null || ((String) authClaim).isEmpty() ? Collections.emptyList() : Arrays.stream(((String) authClaim).split(",")) .map(SimpleGrantedAuthority::new) .collect(Collectors.toList()); + log.debug("Converted authorities from claims: {}", authorities); + return authorities; } public boolean validateToken(String authToken) { @@ -84,9 +96,10 @@ public class TokenProvider { .setSigningKey(key) .build() .parseClaimsJws(authToken); + log.info("Token is valid."); return true; } catch (Exception e) { - log.info("Token validation failed: " + e.getMessage()); + log.error("Token validation failed: {}", e.getMessage()); return false; } } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/RegionDao.java b/src/main/java/net/gepafin/tendermanagement/dao/RegionDao.java index 3cc3d997..9277b167 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/RegionDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/RegionDao.java @@ -3,21 +3,17 @@ package net.gepafin.tendermanagement.dao; 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.model.request.RegionReq; -import net.gepafin.tendermanagement.model.request.RoleReq; import net.gepafin.tendermanagement.model.response.RegionResponseBean; -import net.gepafin.tendermanagement.model.request.UpdateRegionReq; -import net.gepafin.tendermanagement.model.response.RoleResponseBean; import net.gepafin.tendermanagement.repositories.RegionRepository; import net.gepafin.tendermanagement.util.Utils; 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; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; -import java.math.BigDecimal; -import java.time.LocalDateTime; import java.util.List; import java.util.stream.Collectors; @@ -25,14 +21,19 @@ import static net.gepafin.tendermanagement.util.ObjectUtils.setIfUpdated; @Repository public class RegionDao { + private final Logger log = LoggerFactory.getLogger(RegionDao.class); + @Autowired - private RegionRepository regionRepository; + private RegionRepository regionRepository; public RegionResponseBean createRegion(RegionReq regionReq) { + log.info("Creating new region with details: {}", regionReq); RegionEntity regionEntity = convertRegionRequestToRegionEntity(regionReq); - regionRepository.save(regionEntity); + regionEntity = regionRepository.save(regionEntity); + log.info("Region created with ID: {}", regionEntity.getId()); return convertRegionEntityToRegionResponse(regionEntity); } + private RegionEntity convertRegionRequestToRegionEntity(RegionReq regionReq) { RegionEntity regionEntity = new RegionEntity(); regionEntity.setCountry(regionReq.getCountry()); @@ -50,7 +51,8 @@ public class RegionDao { regionEntity.setEducationLevel(regionReq.getEducationLevel()); return regionEntity; } - public RegionResponseBean convertRegionEntityToRegionResponse(RegionEntity regionEntity) { + + public RegionResponseBean convertRegionEntityToRegionResponse(RegionEntity regionEntity) { RegionResponseBean regionResponseBean = new RegionResponseBean(); regionResponseBean.setId(regionEntity.getId()); regionResponseBean.setCreatedDate(regionEntity.getCreatedDate()); @@ -72,7 +74,11 @@ public class RegionDao { } public RegionResponseBean updateRegion(Long id, RegionReq regionReq) { + log.info("Updating region with ID: {}", id); RegionEntity existingRegion = getRegionById(id); + log.info("Current region details: {}", existingRegion); + log.info("New region details: {}", regionReq); + setIfUpdated(existingRegion::getRegionName, existingRegion::setRegionName, regionReq.getRegionName()); setIfUpdated(existingRegion::getDescription, existingRegion::setDescription, regionReq.getDescription()); setIfUpdated(existingRegion::getCountry, existingRegion::setCountry, regionReq.getCountry()); @@ -82,28 +88,40 @@ public class RegionDao { setIfUpdated(existingRegion::getAreaSize, existingRegion::setAreaSize, regionReq.getAreaSize()); setIfUpdated(existingRegion::getGdp, existingRegion::setGdp, regionReq.getGdp()); setIfUpdated(existingRegion::getUnemploymentRate, existingRegion::setUnemploymentRate, regionReq.getUnemploymentRate()); - setIfUpdated(existingRegion::getInfrastructureScore, existingRegion::setInfrastructureScore, regionReq.getInfrastructureScore() ); + setIfUpdated(existingRegion::getInfrastructureScore, existingRegion::setInfrastructureScore, regionReq.getInfrastructureScore()); setIfUpdated(existingRegion::getEducationLevel, existingRegion::setEducationLevel, regionReq.getEducationLevel()); setIfUpdated(existingRegion::getHealthcareAccess, existingRegion::setHealthcareAccess, regionReq.getHealthcareAccess()); setIfUpdated(existingRegion::getEnvironmentalScore, existingRegion::setEnvironmentalScore, regionReq.getEnvironmentalScore()); - regionRepository.save(existingRegion); + + existingRegion = regionRepository.save(existingRegion); + + log.info("Region updated with ID: {}", existingRegion.getId()); return Utils.convertObject(existingRegion, RegionResponseBean.class); } - public RegionEntity getRegionById(Long id) { - return regionRepository.findById(id) - .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.REGION_NOT_FOUND_MSG))); - } - public void deleteById(Long id) { + public RegionEntity getRegionById(Long id) { + log.info("Fetching region with ID: {}", id); + RegionEntity regionEntity = regionRepository.findById(id) + .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.REGION_NOT_FOUND_MSG))); + log.info("Region found: {}", regionEntity); + return regionEntity; + } + + public void deleteById(Long id) { + log.info("Deleting region with ID: {}", id); regionRepository.findById(id) .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.REGION_NOT_FOUND_MSG))); regionRepository.deleteById(id); + log.info("Region deleted with ID: {}", id); } - public List getAllRegions() - { - return regionRepository.findAll() + + public List getAllRegions() { + log.info("Fetching all regions"); + List regions = regionRepository.findAll() .stream() .map(regionEntity -> Utils.convertObject(regionEntity, RegionResponseBean.class)) .collect(Collectors.toList()); + log.info("Total regions found: {}", regions.size()); + return regions; } } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/RoleDao.java b/src/main/java/net/gepafin/tendermanagement/dao/RoleDao.java index fe25a923..e7f4c5f9 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/RoleDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/RoleDao.java @@ -11,6 +11,8 @@ import net.gepafin.tendermanagement.service.RegionService; import net.gepafin.tendermanagement.util.Utils; 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; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -21,10 +23,11 @@ import static net.gepafin.tendermanagement.util.ObjectUtils.setIfUpdated; @Component public class RoleDao { + private final Logger log = LoggerFactory.getLogger(RoleDao.class); @Autowired private RoleRepository roleRepository; - + @Autowired private RegionService regionService; @@ -32,55 +35,76 @@ public class RoleDao { private RegionDao regionDao; public RoleResponseBean createRole(RoleReq roleReq) { + log.info("Creating new role with details: {}", roleReq); RoleEntity roleEntity = convertRoleRequestToRoleEntity(roleReq); roleEntity = roleRepository.save(roleEntity); + log.info("Role created with ID: {}", roleEntity.getId()); return convertRoleEntityToRoleResponse(roleEntity); } + private RoleEntity convertRoleRequestToRoleEntity(RoleReq roleReq) { RoleEntity roleEntity = new RoleEntity(); roleEntity.setRoleName(roleReq.getRoleName()); roleEntity.setPermissions(roleReq.getPermissions()); - roleEntity.setDescription(roleEntity.getDescription()); + roleEntity.setDescription(roleReq.getDescription()); roleEntity.setRegion(regionService.getRegionById(roleReq.getRegionId())); return roleEntity; } + public RoleResponseBean convertRoleEntityToRoleResponse(RoleEntity roleEntity) { - RoleResponseBean roleResponseBean=new RoleResponseBean(); - roleResponseBean.setId(roleEntity.getId()); - roleResponseBean.setCreatedDate(roleEntity.getCreatedDate()); - roleResponseBean.setUpdatedDate(roleEntity.getUpdatedDate()); - roleResponseBean.setRoleName(roleEntity.getRoleName()); - roleResponseBean.setDescription(roleEntity.getDescription()); - roleResponseBean.setPermissions(roleEntity.getPermissions()); - RegionResponseBean regionResponseBean = regionDao.convertRegionEntityToRegionResponse(roleEntity.getRegion()); - roleResponseBean.setRegion(regionResponseBean); + RoleResponseBean roleResponseBean = new RoleResponseBean(); + roleResponseBean.setId(roleEntity.getId()); + roleResponseBean.setCreatedDate(roleEntity.getCreatedDate()); + roleResponseBean.setUpdatedDate(roleEntity.getUpdatedDate()); + roleResponseBean.setRoleName(roleEntity.getRoleName()); + roleResponseBean.setDescription(roleEntity.getDescription()); + roleResponseBean.setPermissions(roleEntity.getPermissions()); + RegionResponseBean regionResponseBean = regionDao.convertRegionEntityToRegionResponse(roleEntity.getRegion()); + roleResponseBean.setRegion(regionResponseBean); return roleResponseBean; } - public RoleResponseBean updateRole(Long id, RoleReq roleReq) { - RoleEntity existingUserRole = getRoleById(id); - setIfUpdated(existingUserRole::getRoleName, existingUserRole::setRoleName, roleReq.getRoleName()); - setIfUpdated(existingUserRole::getDescription, existingUserRole::setDescription, roleReq.getDescription()); - setIfUpdated(existingUserRole::getPermissions, existingUserRole::setPermissions, roleReq.getPermissions()); - roleRepository.save(existingUserRole); - return Utils.convertObject(existingUserRole, RoleResponseBean.class); + public RoleResponseBean updateRole(Long id, RoleReq roleReq) { + log.info("Updating role with ID: {}", id); + RoleEntity existingRole = getRoleById(id); + + // Log changes before update + log.info("Current role details: {}", existingRole); + log.info("New role details: {}", roleReq); + + setIfUpdated(existingRole::getRoleName, existingRole::setRoleName, roleReq.getRoleName()); + setIfUpdated(existingRole::getDescription, existingRole::setDescription, roleReq.getDescription()); + setIfUpdated(existingRole::getPermissions, existingRole::setPermissions, roleReq.getPermissions()); + + existingRole = roleRepository.save(existingRole); + + log.info("Role updated with ID: {}", existingRole.getId()); + return Utils.convertObject(existingRole, RoleResponseBean.class); } public RoleEntity getRoleById(Long id) { - return roleRepository.findById(id) + log.info("Fetching role with ID: {}", id); + RoleEntity roleEntity = roleRepository.findById(id) .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.ROLE_NOT_FOUND))); + log.info("Role found: {}", roleEntity); + return roleEntity; } public void deleteById(Long id) { + log.info("Deleting role with ID: {}", id); roleRepository.findById(id) - .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND,Translator.toLocale(GepafinConstant.ROLE_NOT_FOUND))); + .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.ROLE_NOT_FOUND))); roleRepository.deleteById(id); + log.info("Role deleted with ID: {}", id); } public List getAllRoles() { - return roleRepository.findAll() + log.info("Fetching all roles"); + List roles = roleRepository.findAll() .stream() .map(roleEntity -> Utils.convertObject(roleEntity, RoleResponseBean.class)) .collect(Collectors.toList()); + log.info("Total roles found: {}", roles.size()); + return roles; } } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java index eecdd4e0..af0e19f4 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java @@ -18,45 +18,61 @@ import net.gepafin.tendermanagement.service.impl.AuthenticationService; 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; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Repository; import static net.gepafin.tendermanagement.util.ObjectUtils.setIfUpdated; + @Repository public class UserDao { + private final Logger log = LoggerFactory.getLogger(UserDao.class); + @Autowired private UserRepository userRepository; + @Autowired private AuthenticationService authService; + @Autowired private RoleService roleService; @Autowired private PasswordEncoder passwordEncoder; - + @Autowired private RoleDao roleDao; public UserResponseBean createUser(UserReq userReq) { + log.info("Creating user with email: {}", userReq.getEmail()); if (userRepository.existsByEmail(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())) { + 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) { + 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); } public UserResponseBean updateUser(Long userId, UpdateUserReq userReq) { + log.info("Updating user with ID: {}", userId); UserEntity userEntity = userRepository.findById(userId) .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.REGION_NOT_FOUND_MSG))); + log.info("Current user details: {}", userEntity); + log.info("New user details: {}", userReq); + setIfUpdated(userEntity::getStatus, userEntity::setStatus, userReq.getStatus()); setIfUpdated(userEntity::getFirstName, userEntity::setFirstName, userReq.getFirstName()); setIfUpdated(userEntity::getLastName, userEntity::setLastName, userReq.getLastName()); @@ -68,6 +84,7 @@ public class UserDao { setIfUpdated(userEntity::getRoleEntity, userEntity::setRoleEntity, roleEntity); } userEntity = userRepository.save(userEntity); + log.info("User updated with ID: {}", userEntity.getId()); return convertUserEntityToUserResponse(userEntity); } @@ -90,7 +107,6 @@ public class UserDao { userResponseBean.setId(userEntity.getId()); userResponseBean.setCreatedDate(userEntity.getCreatedDate()); userResponseBean.setUpdatedDate(userEntity.getUpdatedDate()); - userResponseBean.setId(userEntity.getId()); userResponseBean.setEmail(userEntity.getEmail()); userResponseBean.setFirstName(userEntity.getFirstName()); userResponseBean.setLastName(userEntity.getLastName()); @@ -107,19 +123,25 @@ public class UserDao { } public UserResponseBean getUserById(Long id) { + log.info("Fetching user with ID: {}", id); UserEntity userEntity = userRepository.findById(id) - .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND,Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG))); + .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG))); + log.info("User found: {}", userEntity); return convertUserEntityToUserResponse(userEntity); } public void deleteUser(Long id) { + log.info("Deleting user with ID: {}", id); userRepository.findById(id) - .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND,Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG))); + .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG))); userRepository.deleteById(id); + log.info("User deleted with ID: {}", id); } - public JWTToken login(LoginReq loginReq) { - return authService.login(loginReq); + log.info("User login attempt for email: {}", loginReq.getEmail()); + JWTToken jwtToken = authService.login(loginReq); + log.info("Login successful for email: {}", loginReq.getEmail()); + return jwtToken; } } 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 1b5137ce..022f3775 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java @@ -12,6 +12,8 @@ import net.gepafin.tendermanagement.model.util.JWTToken; import net.gepafin.tendermanagement.repositories.UserRepository; 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; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @@ -20,18 +22,20 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; -import java.util.Collections; - @Service public class AuthenticationService { + private final Logger log = LoggerFactory.getLogger(AuthenticationService.class); + private final TokenProvider tokenProvider; private final AuthenticationManager authenticationManager; @Autowired - private UserRepository userRepository; + private UserRepository userRepository; + @Autowired private PasswordEncoder passwordEncoder; + @Autowired private RoleDao roleDao; @@ -42,19 +46,26 @@ public class AuthenticationService { } public JWTToken login(LoginReq loginReq) { - UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginReq.getEmail(),loginReq.getPassword()); - Authentication authentication = this.authenticationManager.authenticate(authenticationToken); - SecurityContextHolder.getContext().setAuthentication(authentication); - String token = tokenProvider.createToken(authentication,loginReq.getRememberMe()); - UserEntity user = userRepository.findByEmail(loginReq.getEmail()); - if (user == null) { - throw new CustomValidationException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG)); - } - RoleResponseBean roleResponseBean = roleDao.convertRoleEntityToRoleResponse(user.getRoleEntity()); - return new JWTToken(token, new LoginResponse(user.getId(),user.getEmail(), - user.getFirstName(),user.getLastName(),roleResponseBean, user.getPhoneNumber(), user.getAddress(), user.getOrganization(), user.getCountry(),user.getStatus() - ,user.getCity(),user.getLastLogin(),user.getCreatedDate(),user.getUpdatedDate())); - } - } + log.info("Attempting login for email: {}", loginReq.getEmail()); + UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginReq.getEmail(), loginReq.getPassword()); + Authentication authentication = this.authenticationManager.authenticate(authenticationToken); + SecurityContextHolder.getContext().setAuthentication(authentication); + log.info("Authentication successful for email: {}", loginReq.getEmail()); + String token = tokenProvider.createToken(authentication, loginReq.getRememberMe()); + log.info("JWT token generated for email: {}", loginReq.getEmail()); + UserEntity user = userRepository.findByEmail(loginReq.getEmail()); + if (user == null) { + log.error("User not found for email: {}", loginReq.getEmail()); + throw new CustomValidationException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG)); + } + RoleResponseBean roleResponseBean = roleDao.convertRoleEntityToRoleResponse(user.getRoleEntity()); + JWTToken jwtToken = new JWTToken(token, new LoginResponse(user.getId(), user.getEmail(), user.getFirstName(), + user.getLastName(), roleResponseBean, user.getPhoneNumber(), user.getAddress(), user.getOrganization(), + user.getCountry(), user.getStatus(), user.getCity(), user.getLastLogin(), user.getCreatedDate(), + user.getUpdatedDate())); + log.info("Login successful for email: {}", loginReq.getEmail()); + return jwtToken; + } +} From e7466d16ec3abf04e6e6c7fafd8e57f7d57592fc Mon Sep 17 00:00:00 2001 From: harish Date: Wed, 21 Aug 2024 20:55:13 +0530 Subject: [PATCH 6/9] Done ticket GEPAFINBE-8 --- pom.xml | 20 ++ .../tendermanagement/config/AmazonConfig.java | 34 ++ .../constants/GepafinConstant.java | 14 + .../gepafin/tendermanagement/dao/CallDao.java | 323 ++++++++++++++++++ .../tendermanagement/dao/DocumentDao.java | 80 +++++ .../tendermanagement/entities/CallEntity.java | 66 ++++ .../CallTargetAudienceChecklistEntity.java | 23 ++ .../entities/DocumentEntity.java | 31 ++ .../entities/EvaluationCriteriaEntity.java | 30 ++ .../tendermanagement/entities/FaqEntity.java | 46 +++ .../entities/LookUpDataEntity.java | 37 ++ .../tendermanagement/enums/CallTypeEnum.java | 21 ++ .../enums/DocumentTypeEnum.java | 20 ++ .../model/request/CreateCallRequest.java | 49 +++ .../model/request/DocumentReq.java | 11 + .../model/request/EvaluationCriteriaReq.java | 11 + .../model/request/FaqReq.java | 13 + .../model/request/LookUpDataReq.java | 11 + .../model/response/CallResponseBean.java | 42 +++ .../response/CreateCallResponseBean.java | 60 ++++ .../model/response/DocumentResponseBean.java | 21 ++ .../EvaluationCriteriaResponseBean.java | 21 ++ .../model/response/FaqResponseBean.java | 30 ++ .../model/response/LookUpDataResponse.java | 22 ++ .../repositories/CallRepository.java | 8 + ...CallTargetAudienceChecklistRepository.java | 7 + .../repositories/DocumentRepository.java | 9 + .../EvaluationCriteriaRepository.java | 7 + .../repositories/FaqRepository.java | 7 + .../repositories/LookUpDataRepository.java | 7 + .../service/AmazonS3Service.java | 20 ++ .../tendermanagement/service/CallService.java | 10 + .../service/DocumentService.java | 14 + .../service/impl/AmazonS3ServiceImpl.java | 91 +++++ .../service/impl/CallServiceImpl.java | 21 ++ .../service/impl/DocumentServiceImpl.java | 28 ++ .../gepafin/tendermanagement/util/Utils.java | 13 + .../web/rest/api/CallApi.java | 36 ++ .../web/rest/api/DocumentApi.java | 53 +++ .../web/rest/api/impl/CallApiController.java | 34 ++ .../rest/api/impl/DocumentApiController.java | 45 +++ src/main/resources/application.properties | 9 + .../db/changelog/db.changelog-1.0.0.xml | 158 +++++++++ src/main/resources/message_en.properties | 14 + src/main/resources/message_it.properties | 15 + 45 files changed, 1642 insertions(+) create mode 100644 src/main/java/net/gepafin/tendermanagement/config/AmazonConfig.java create mode 100644 src/main/java/net/gepafin/tendermanagement/dao/CallDao.java create mode 100644 src/main/java/net/gepafin/tendermanagement/dao/DocumentDao.java create mode 100644 src/main/java/net/gepafin/tendermanagement/entities/CallEntity.java create mode 100644 src/main/java/net/gepafin/tendermanagement/entities/CallTargetAudienceChecklistEntity.java create mode 100644 src/main/java/net/gepafin/tendermanagement/entities/DocumentEntity.java create mode 100644 src/main/java/net/gepafin/tendermanagement/entities/EvaluationCriteriaEntity.java create mode 100644 src/main/java/net/gepafin/tendermanagement/entities/FaqEntity.java create mode 100644 src/main/java/net/gepafin/tendermanagement/entities/LookUpDataEntity.java create mode 100644 src/main/java/net/gepafin/tendermanagement/enums/CallTypeEnum.java create mode 100644 src/main/java/net/gepafin/tendermanagement/enums/DocumentTypeEnum.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/request/CreateCallRequest.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/request/DocumentReq.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/request/EvaluationCriteriaReq.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/request/FaqReq.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/request/LookUpDataReq.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/response/CallResponseBean.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/response/CreateCallResponseBean.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/response/DocumentResponseBean.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/response/EvaluationCriteriaResponseBean.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/response/FaqResponseBean.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/response/LookUpDataResponse.java create mode 100644 src/main/java/net/gepafin/tendermanagement/repositories/CallRepository.java create mode 100644 src/main/java/net/gepafin/tendermanagement/repositories/CallTargetAudienceChecklistRepository.java create mode 100644 src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java create mode 100644 src/main/java/net/gepafin/tendermanagement/repositories/EvaluationCriteriaRepository.java create mode 100644 src/main/java/net/gepafin/tendermanagement/repositories/FaqRepository.java create mode 100644 src/main/java/net/gepafin/tendermanagement/repositories/LookUpDataRepository.java create mode 100644 src/main/java/net/gepafin/tendermanagement/service/AmazonS3Service.java create mode 100644 src/main/java/net/gepafin/tendermanagement/service/CallService.java create mode 100644 src/main/java/net/gepafin/tendermanagement/service/DocumentService.java create mode 100644 src/main/java/net/gepafin/tendermanagement/service/impl/AmazonS3ServiceImpl.java create mode 100644 src/main/java/net/gepafin/tendermanagement/service/impl/CallServiceImpl.java create mode 100644 src/main/java/net/gepafin/tendermanagement/service/impl/DocumentServiceImpl.java create mode 100644 src/main/java/net/gepafin/tendermanagement/web/rest/api/CallApi.java create mode 100644 src/main/java/net/gepafin/tendermanagement/web/rest/api/DocumentApi.java create mode 100644 src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CallApiController.java create mode 100644 src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/DocumentApiController.java diff --git a/pom.xml b/pom.xml index 1572627b..ac87bfdd 100644 --- a/pom.xml +++ b/pom.xml @@ -80,6 +80,26 @@ spring-boot-starter-test test + + + com.amazonaws + aws-java-sdk-s3 + 1.12.312 + + + + com.amazonaws + aws-java-sdk-core + 1.12.341 + + + + commons-io + commons-io + 2.11.0 + + + diff --git a/src/main/java/net/gepafin/tendermanagement/config/AmazonConfig.java b/src/main/java/net/gepafin/tendermanagement/config/AmazonConfig.java new file mode 100644 index 00000000..878cd12f --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/config/AmazonConfig.java @@ -0,0 +1,34 @@ +package net.gepafin.tendermanagement.config; + +import com.amazonaws.auth.AWSCredentials; +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class AmazonConfig { + + @Value("${aws.access.key.id}") + private String accessKey; + + @Value("${aws.secret.access.key}") + private String secretKey; + + @Value("${aws.s3.region}") + private String region; + + @Bean + public AmazonS3 mementoBucket() { + AWSCredentials awsCredentials = + new BasicAWSCredentials(accessKey, secretKey); + return AmazonS3ClientBuilder + .standard() + .withRegion(region) + .withCredentials(new AWSStaticCredentialsProvider(awsCredentials)) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index 7d00913f..cdb9e573 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -24,4 +24,18 @@ public class GepafinConstant { public static final String DELETE_REGION_SUCCESS_MSG = "delete.region.success"; public static final String REGION_NOT_FOUND_MSG = "user.region.not.found"; public static final String PASSWORD_DOESNT_MATCH ="password.doesnt.match"; + public static final String USER_NOT_EXIST_MSG = "user.not.exist"; + public static final String REGION_NOT_FOUND = "region.not.found"; + public static final String USER_ID_NOT_NULL_MSG = "user.id.not.null"; + public static final String QUESTION_NOT_EMPTY_MSG = "question.not.empty"; + public static final String NAME_NOT_EMPTY_MSG = "name.not.empty"; + public static final String TYPE_NOT_EMPTY_MSG = "type.not.empty"; + public static final String REGION_NOT_NULL_MSG = "region.not.null"; + public static final String AMOUNT_GREATER_THAN_ZERO_MSG = "amount.greater.than.zero"; + public static final String LOOK_UP_DATA_NOT_VALID_MSG = "look.up.data.not.valid"; + public static final String FILES_UPLOADED_MSG = "files.uploaded"; + public static final String CALL_CREATED_SUCCESSFULLY_MSG = "call.created.successfully"; + public static final String FILE_DELETED_SUCCESSFULLY_MSG="file.deleted.successfully"; + public static final String DOCUMENT_NOT_FOUND="document.not.found"; + } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java new file mode 100644 index 00000000..fc2b966c --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java @@ -0,0 +1,323 @@ +package net.gepafin.tendermanagement.dao; + +import net.gepafin.tendermanagement.config.Translator; +import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.entities.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import net.gepafin.tendermanagement.enums.CallTypeEnum; +import net.gepafin.tendermanagement.model.request.*; +import net.gepafin.tendermanagement.model.response.*; +import net.gepafin.tendermanagement.repositories.*; +import net.gepafin.tendermanagement.service.AmazonS3Service; +import net.gepafin.tendermanagement.util.DateTimeUtil; +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; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; +import net.gepafin.tendermanagement.entities.LookUpDataEntity.LookUpDataTypeEnum; + +@Component +public class CallDao { + + @Autowired + private CallRepository callRepository; + + @Autowired + private DocumentRepository documentRepository; + + @Autowired + private EvaluationCriteriaRepository evaluationCriteriaRepository; + + @Autowired + private FaqRepository faqRepository; + + @Autowired + private RegionRepository regionRepository; + + @Autowired + private LookUpDataRepository lookUpDataRepository; + + @Autowired + private CallTargetAudienceChecklistRepository callTargetAudienceChecklistRepository; + + public CreateCallResponseBean createCall(CreateCallRequest createCallRequest) { + try { + CreateCallResponseBean createCallResponseBean=null; + CallEntity callEntity = convertToCallEntity(createCallRequest); + List evaluationCriteriaEntities = convertToEvaluationCriteriaEntities(createCallRequest.getCriteria(), callEntity); + List documentEntities = convertToDocumentEntities(createCallRequest.getDocs(), callEntity); + List imageEntities=convertToDocumentEntities(createCallRequest.getImages(),callEntity); + List faqEntities = convertToFaqEntities(createCallRequest.getFaq(), callEntity); + List amiedTo=convertLookUpDataEntities(createCallRequest.getAimedTo(),callEntity,LookUpDataTypeEnum.AIMED_TO); + List checkList=convertLookUpDataEntities(createCallRequest.getAimedTo(),callEntity,LookUpDataTypeEnum.CHECKLIST); + createCallResponseBean= assembleCreateCallResponseBean(callEntity, evaluationCriteriaEntities, documentEntities, faqEntities,imageEntities); + createCallResponseBean.setAimedTo(amiedTo); + createCallResponseBean.setCheckList(checkList); + return createCallResponseBean; + } catch (Exception e) { + throw new RuntimeException("Error processing create call request", e); + } + } + + + public CallEntity convertToCallEntity(CreateCallRequest createCallRequest) { + CallEntity callEntity = new CallEntity(); + validateCallEntity(createCallRequest.getRegionId(), createCallRequest.getAmount()); + RegionEntity region = regionRepository.findById(createCallRequest.getRegionId()) + .orElseThrow(() -> new ResourceNotFoundException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.REGION_NOT_FOUND))); + callEntity.setRegion(region); + callEntity.setName(createCallRequest.getName()); + callEntity.setDescriptionShort(createCallRequest.getDescriptionShort()); + callEntity.setDescriptionLong(createCallRequest.getDescriptionLong()); + callEntity.setStartDate(createCallRequest.getStartDate()); + callEntity.setEndDate(createCallRequest.getEndDate()); + callEntity.setStatus(String.valueOf(createCallRequest.getStatus())); + callEntity.setAmountMax(createCallRequest.getAmountMax()); + callEntity.setAmount(createCallRequest.getAmountMax()); + callEntity.setThreshold(createCallRequest.getThreshold()); + callEntity.setConfidi(false); + if(createCallRequest.getConfidi()!=null){ + callEntity.setConfidi(createCallRequest.getConfidi()); + } + callEntity.setDocumentation_requested(createCallRequest.getDocumentationRequested()); + callEntity = callRepository.save(callEntity); + return callEntity; + } + + public List convertToEvaluationCriteriaEntities(List criteriaReqList, CallEntity callEntity) { + List evaluationCriteriaEntities = criteriaReqList.stream().map(req -> convertToEvaluationCriteriaEntity(req, callEntity)).collect(Collectors.toList()); + evaluationCriteriaRepository.saveAll(evaluationCriteriaEntities); + return evaluationCriteriaEntities; + } + + private EvaluationCriteriaEntity convertToEvaluationCriteriaEntity(EvaluationCriteriaReq criteriaReq, CallEntity callEntity) { + EvaluationCriteriaEntity criteriaEntity = new EvaluationCriteriaEntity(); + validateEvolutionCrieteriaEntity(criteriaReq.getName()); + criteriaEntity.setName(criteriaReq.getName()); + criteriaEntity.setDescription(criteriaReq.getValue()); + criteriaEntity.setScore(criteriaReq.getScore()); + criteriaEntity.setCall(callEntity); + return criteriaEntity; + } + + + public List convertToDocumentEntities(List documentReqList, CallEntity callEntity) { + List documentEntities = documentReqList.stream().map(req -> convertToDocumentEntity(req, callEntity)).collect(Collectors.toList()); + documentRepository.saveAll(documentEntities); + return documentEntities; + } + + private DocumentEntity convertToDocumentEntity(DocumentReq documentReq, CallEntity callEntity) { + DocumentEntity documentEntity = new DocumentEntity(); + validateDocumentEntity(documentReq.getFileName()); + documentEntity.setFileName(documentReq.getFileName()); + documentEntity.setFilePath(documentReq.getUrl()); + documentEntity.setCall(callEntity); + return documentEntity; + } + + + public List convertToFaqEntities(List faqReqList, CallEntity callEntity) { + List faqEntities = faqReqList.stream().map(req -> convertToFaqEntity(req, callEntity)).collect(Collectors.toList()); + faqRepository.saveAll(faqEntities); + return faqEntities; + } + + private FaqEntity convertToFaqEntity(FaqReq faqReq, CallEntity callEntity) { + FaqEntity faqEntity = new FaqEntity(); + validateFaqEntity(faqReq.getQuestion()); +// UserEntity userEntity= userRepository.findById(1l) +// .orElseThrow(() -> new ResourceNotFoundException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.LOOK_UP_DATA_NOT_VALID_MSG))); +// faqEntity.setUser(userEntity); + faqEntity.setIsVisible(true); + if(faqReq.getIsVisible()!=null){ + faqEntity.setIsVisible(faqReq.getIsVisible()); + } + faqEntity.setQuestionShort(faqReq.getQuestionShort()); + faqEntity.setQuestion(faqReq.getQuestion()); + if(faqReq.getResponse()!=null ||faqReq.getResponseShort()!=null){ + faqEntity.setResponseDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now())); + } + faqEntity.setResponseShort(faqReq.getResponseShort()); + faqEntity.setResponse(faqReq.getResponse()); + faqEntity.setCall(callEntity); + return faqEntity; + } + + public void validateFaqEntity( String question) { + if (!StringUtils.hasText(question)) { + throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.QUESTION_NOT_EMPTY_MSG)); + } + } + + public void validateDocumentEntity(String name) { + if (!StringUtils.hasText(name)) { + throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.NAME_NOT_EMPTY_MSG)); + } + } + + public void validateEvolutionCrieteriaEntity(String name) { + if (!StringUtils.hasText(name)) { + throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.NAME_NOT_EMPTY_MSG)); + } + } + + public void validateCallEntity(Long regionId, BigDecimal fundingAmount) { + if (regionId == null) { + throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.REGION_NOT_FOUND_MSG)); + } + + if (fundingAmount == null || fundingAmount.compareTo(BigDecimal.ZERO) <= 0) { + throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.AMOUNT_GREATER_THAN_ZERO_MSG)); + } + } + public CreateCallResponseBean convertToCallResponseBean(CallEntity callEntity) { + CreateCallResponseBean createCallResponseBean = new CreateCallResponseBean(); + createCallResponseBean.setId(callEntity.getId()); + createCallResponseBean.setName(callEntity.getName()); + createCallResponseBean.setDates(List.of(callEntity.getStartDate(), callEntity.getEndDate())); + createCallResponseBean.setDescriptionShort(callEntity.getDescriptionShort()); + createCallResponseBean.setDescriptionLong(callEntity.getDescriptionLong()); + createCallResponseBean.setStatus(CallTypeEnum.valueOf(callEntity.getStatus())); + createCallResponseBean.setRegionId(callEntity.getRegion().getId()); + createCallResponseBean.setAmount(callEntity.getAmount()); + createCallResponseBean.setAmountMax(callEntity.getAmountMax()); + createCallResponseBean.setContactInfo(callEntity.getContactInfo()); + createCallResponseBean.setSubmissionMethod(callEntity.getSubmissionMethod()); + createCallResponseBean.setThreshold(callEntity.getThreshold()); + createCallResponseBean.setDocumentationReqested(callEntity.getDocumentation_requested()); + createCallResponseBean.setPriorityArea(callEntity.getPriorityArea()); + createCallResponseBean.setCreatedDate(callEntity.getCreatedDate()); + createCallResponseBean.setUpdatedDate(callEntity.getUpdatedDate()); + return createCallResponseBean; + } + public EvaluationCriteriaResponseBean convertToEvaluationCriteriaResponseBean(EvaluationCriteriaEntity entity) { + EvaluationCriteriaResponseBean responseBean = new EvaluationCriteriaResponseBean(); + responseBean.setId(entity.getId()); + responseBean.setName(entity.getName()); + responseBean.setDescription(entity.getDescription()); + responseBean.setScore(entity.getScore()); + responseBean.setCreatedDate(entity.getCreatedDate()); + responseBean.setUpdatedDate(entity.getUpdatedDate()); + return responseBean; + } + public DocumentResponseBean convertToDocumentResponseBean(DocumentEntity entity) { + DocumentResponseBean responseBean = new DocumentResponseBean(); + responseBean.setId(entity.getId()); + responseBean.setName(entity.getFileName()); + responseBean.setDescription(entity.getDescription()); + responseBean.setFilePath(entity.getFilePath()); + responseBean.setCreatedDate(entity.getCreatedDate()); + responseBean.setUpdatedDate(entity.getUpdatedDate()); + return responseBean; + } + public FaqResponseBean convertToFaqResponseBean(FaqEntity entity) { + FaqResponseBean responseBean = new FaqResponseBean(); + responseBean.setId(entity.getId()); + responseBean.setQuestionShort(entity.getQuestionShort()); + responseBean.setResponseShort(entity.getResponseShort()); + responseBean.setResponse(entity.getResponse()); + responseBean.setQuestion(entity.getQuestion()); + responseBean.setUserId(entity.getUser().getId()); + responseBean.setIsVisible(entity.getIsVisible()); + responseBean.setCreatedDate(entity.getCreatedDate()); + responseBean.setUpdatedDate(entity.getUpdatedDate()); + return responseBean; + } + public CreateCallResponseBean assembleCreateCallResponseBean( + CallEntity callEntity, + List evaluationCriteriaEntities, + List documentEntities, + List faqEntities,List images) { + + CreateCallResponseBean callResponseBean = convertToCallResponseBean(callEntity); + + List evaluationCriteriaResponseBeans = evaluationCriteriaEntities.stream() + .map(this::convertToEvaluationCriteriaResponseBean) + .collect(Collectors.toList()); + + List documentResponseBeans = documentEntities.stream() + .map(this::convertToDocumentResponseBean) + .collect(Collectors.toList()); + + List faqResponseBeans = faqEntities.stream() + .map(this::convertToFaqResponseBean) + .collect(Collectors.toList()); + + List imagesResponseBean = images.stream() + .map(this::convertToDocumentResponseBean) + .collect(Collectors.toList()); + CreateCallResponseBean createCallResponseBean =callResponseBean; + createCallResponseBean.setCriteria(evaluationCriteriaResponseBeans); + createCallResponseBean.setDocs(documentResponseBeans); + createCallResponseBean.setFaq(faqResponseBeans); + createCallResponseBean.setImages(imagesResponseBean); + return createCallResponseBean; + } + public List convertLookUpDataEntities(List lookUpData, CallEntity callEntity, LookUpDataEntity.LookUpDataTypeEnum type) { + List lookUpDataEntities = lookUpData.stream() + .map(req -> convertLookUpDataRequestIntoLookUpDataEntity(req, type)) + .collect(Collectors.toList()); + + lookUpDataRepository.saveAll(lookUpDataEntities); + + return createCallTargetAudienceCheckList(callEntity, lookUpDataEntities); + } + + private List createCallTargetAudienceCheckList(CallEntity callEntity, List lookUpDataEntities) { + List lookUpDataResponses=new ArrayList<>(); + List callTargetAudienceChecklistEntities=new ArrayList<>(); + for(LookUpDataEntity lookUpDataEntity:lookUpDataEntities){ + CallTargetAudienceChecklistEntity callTargetAudienceChecklistEntity=new CallTargetAudienceChecklistEntity(); + callTargetAudienceChecklistEntity.setIsValidated(false); + callTargetAudienceChecklistEntity.setLookupData(lookUpDataEntity); + callTargetAudienceChecklistEntity.setCall(callEntity); + callTargetAudienceChecklistEntities.add(callTargetAudienceChecklistEntity); + lookUpDataResponses.add(convertToLookUpDataResponseBean(lookUpDataEntity,callTargetAudienceChecklistEntity)); + } + callTargetAudienceChecklistRepository.saveAll(callTargetAudienceChecklistEntities); + return lookUpDataResponses; + } + + private LookUpDataEntity convertLookUpDataRequestIntoLookUpDataEntity(LookUpDataReq req, LookUpDataEntity.LookUpDataTypeEnum type) { + if (req.getLookUpDataId() == null || req.getLookUpDataId().equals(BigDecimal.ZERO)) { + LookUpDataEntity newEntity = new LookUpDataEntity(); + newEntity.setValue(req.getValue()); + newEntity.setType(type.getValue()); + return newEntity; + } + + return lookUpDataRepository.findById(req.getLookUpDataId()) + .orElseThrow(() -> new ResourceNotFoundException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.LOOK_UP_DATA_NOT_VALID_MSG))); + } + + private CallTargetAudienceChecklistEntity createChecklistEntity(CallEntity callEntity, LookUpDataEntity lookUpDataEntity) { + CallTargetAudienceChecklistEntity checklistEntity = new CallTargetAudienceChecklistEntity(); + checklistEntity.setCall(callEntity); + checklistEntity.setLookupData(lookUpDataEntity); + checklistEntity.setIsValidated(false); + return checklistEntity; + } + + public LookUpDataResponse convertToLookUpDataResponseBean(LookUpDataEntity lookUpDataEntity,CallTargetAudienceChecklistEntity callTargetAudienceChecklistEntity) { + LookUpDataResponse lookUpDataResponse = new LookUpDataResponse(); + lookUpDataResponse.setId(callTargetAudienceChecklistEntity.getId()); + lookUpDataResponse.setLookUpDataId(lookUpDataEntity.getId()); + lookUpDataResponse.setValue(lookUpDataEntity.getValue()); + lookUpDataResponse.setTitle(lookUpDataEntity.getTitle()); + lookUpDataResponse.setCreatedDate(lookUpDataEntity.getCreatedDate()); + lookUpDataResponse.setUpdatedDate(lookUpDataEntity.getUpdatedDate()); + return lookUpDataResponse; + } +} + + + diff --git a/src/main/java/net/gepafin/tendermanagement/dao/DocumentDao.java b/src/main/java/net/gepafin/tendermanagement/dao/DocumentDao.java new file mode 100644 index 00000000..3c5cd708 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/dao/DocumentDao.java @@ -0,0 +1,80 @@ +package net.gepafin.tendermanagement.dao; + +import net.gepafin.tendermanagement.config.Translator; +import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.entities.DocumentEntity; +import net.gepafin.tendermanagement.enums.DocumentTypeEnum; +import net.gepafin.tendermanagement.model.response.DocumentResponseBean; +import net.gepafin.tendermanagement.repositories.DocumentRepository; +import net.gepafin.tendermanagement.service.AmazonS3Service; +import net.gepafin.tendermanagement.util.Utils; +import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException; +import net.gepafin.tendermanagement.web.rest.api.errors.Status; +import org.apache.commons.io.FilenameUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@Component +public class DocumentDao { + + @Autowired + private AmazonS3Service amazonS3Service; + + @Autowired + private DocumentRepository documentRepository; + + @Autowired + private CallDao callDao; + + @Value("${aws.s3.bucket.name}") + private String bucketName; + + @Value("${aws.s3.url.folder}") + private String s3Folder; + + @Value("${aws.s3.url}") + private String s3Url; + + public List uploadFiles(List files, DocumentTypeEnum fileType) { + List documentEntities = new ArrayList<>(); + + for (MultipartFile file : files) { + try { + String extension = FilenameUtils.getExtension(file.getOriginalFilename()); + String fileName = StringUtils.cleanPath(file.getOriginalFilename()); + String firstNameContain = fileName.substring(0, fileName.lastIndexOf('.')); + fileName = (firstNameContain + "." + extension); + String filepath = amazonS3Service.upload(fileName,file); + DocumentEntity documentEntity = new DocumentEntity(); + documentEntity.setFileName(fileName); + documentEntity.setType(fileType.getValue()); + documentEntity.setFilePath(filepath); + documentEntities.add(documentEntity); + } catch (IOException e) {} + } + documentRepository.saveAll(documentEntities); + return documentEntities.stream() + .map(callDao::convertToDocumentResponseBean) + .collect(Collectors.toList()); + } + public Void deleteFile(Long documentId){ + DocumentEntity documentEntity= documentRepository.findById(documentId); + if(documentEntity==null){ + new ResourceNotFoundException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.DOCUMENT_NOT_FOUND)); + } + String fileName= Utils.extractFileName(documentEntity.getFilePath()); + try { + amazonS3Service.delete(bucketName, fileName); + documentRepository.delete(documentEntity); + }catch (Exception e){} + return null; + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/entities/CallEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/CallEntity.java new file mode 100644 index 00000000..1ee48d6b --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/entities/CallEntity.java @@ -0,0 +1,66 @@ +package net.gepafin.tendermanagement.entities; + +import jakarta.persistence.*; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; +import lombok.Builder; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Entity +@Table(name = "CALL") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class CallEntity extends BaseEntity { + + @Column(name = "NAME", nullable = false, length = 255) + private String name; + + @Column(name = "DESCRIPTION_SHORT", columnDefinition = "TEXT") + private String descriptionShort; + + @Column(name = "DESCRIPTION_LONG", columnDefinition = "TEXT") + private String descriptionLong; + + @Column(name = "START_DATE", nullable = false) + private LocalDateTime startDate; + + @Column(name = "END_DATE", nullable = false) + private LocalDateTime endDate; + + @Column(name = "STATUS", nullable = false, length = 255) + private String status; + + @ManyToOne + @JoinColumn(name = "REGION_ID", nullable = false, foreignKey = @ForeignKey(name = "fk_region_call")) + private RegionEntity region; + + @Column(name = "AMOUNT", nullable = false) + private BigDecimal amount; + + @Column(name = "AMOUNT_MAX", nullable = false) + private BigDecimal amountMax; + + @Column(name = "CONTACT_INFO", columnDefinition = "TEXT") + private String contactInfo; + + @Column(name = "SUBMISSION_METHOD", columnDefinition = "TEXT") + private String submissionMethod; + + @Column(name = "THRESHOLD", nullable = false) + private Integer threshold; + + @Column(name="DOCUMENTATION_REQUESTED",columnDefinition = "TEXT") + private String documentation_requested; + + @Column(name = "PRIORITY_AREA", columnDefinition = "TEXT") + private String priorityArea; + + @Column(name = "CONFIDI") + private Boolean confidi; +} + diff --git a/src/main/java/net/gepafin/tendermanagement/entities/CallTargetAudienceChecklistEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/CallTargetAudienceChecklistEntity.java new file mode 100644 index 00000000..be94ee59 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/entities/CallTargetAudienceChecklistEntity.java @@ -0,0 +1,23 @@ +package net.gepafin.tendermanagement.entities; + +import jakarta.persistence.*; +import lombok.Data; + +@Entity +@Table(name = "CALL_TARGET_AUDIENCE_CHECKLIST") +@Data +public class CallTargetAudienceChecklistEntity extends BaseEntity{ + + @ManyToOne + @JoinColumn(name = "CALL_ID") + private CallEntity call; + + @ManyToOne + @JoinColumn(name = "LOOKUP_DATA_ID") + private LookUpDataEntity lookupData; + + @Column(name = "IS_VALIDATED") + private Boolean isValidated; + + +} diff --git a/src/main/java/net/gepafin/tendermanagement/entities/DocumentEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/DocumentEntity.java new file mode 100644 index 00000000..5a15351c --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/entities/DocumentEntity.java @@ -0,0 +1,31 @@ +package net.gepafin.tendermanagement.entities; + +import jakarta.persistence.*; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; +import lombok.Builder; + +@Entity +@Table(name = "DOCUMENT") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class DocumentEntity extends BaseEntity{ + @Column(name = "FILE_NAME", length = 255) + private String fileName; + + @Column(name = "FILE_PATH", length = 255) + private String filePath; + + @Column(name="TYPE") + private String type; + + @ManyToOne + @JoinColumn(name = "CALL_ID") + private CallEntity call; + + @Column(name = "DESCRIPTION", columnDefinition = "TEXT") + private String description; +} diff --git a/src/main/java/net/gepafin/tendermanagement/entities/EvaluationCriteriaEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/EvaluationCriteriaEntity.java new file mode 100644 index 00000000..539d9c30 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/entities/EvaluationCriteriaEntity.java @@ -0,0 +1,30 @@ +package net.gepafin.tendermanagement.entities; +import jakarta.persistence.*; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; +import lombok.Builder; + + +@Entity +@Table(name = "EVALUATION_CRITERIA") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class EvaluationCriteriaEntity extends BaseEntity { + + @ManyToOne + @JoinColumn(name = "CALL_ID", nullable = false) + private CallEntity call; + + @Column(name = "NAME", nullable = false, columnDefinition = "TEXT") + private String name; + + @Column(name = "DESCRIPTION", columnDefinition = "TEXT") + private String description; + + @Column(name = "SCORE", nullable = false) + private Integer score; + +} diff --git a/src/main/java/net/gepafin/tendermanagement/entities/FaqEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/FaqEntity.java new file mode 100644 index 00000000..aa521521 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/entities/FaqEntity.java @@ -0,0 +1,46 @@ +package net.gepafin.tendermanagement.entities; + +import jakarta.persistence.*; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; +import lombok.Builder; + +import java.time.LocalDateTime; + +@Entity +@Table(name = "FAQ") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class FaqEntity extends BaseEntity { + + @ManyToOne + @JoinColumn(name = "CALL_ID", nullable = false) + private CallEntity call; + + @ManyToOne + @JoinColumn(name = "USER_ID", nullable = false, foreignKey = @ForeignKey(name = "fk_user_faq")) + private UserEntity user; + + @Column(name = "IS_VISIBLE", nullable = false) + private Boolean isVisible; + + @Column(name = "QUESTION_SHORT", length = 255) + private String questionShort; + + @Column(name = "QUESTION", columnDefinition = "TEXT") + private String question; + + @Column(name = "RESPONSE_SHORT", length = 255) + private String responseShort; + + @Column(name = "RESPONSE", columnDefinition = "TEXT") + private String response; + + @Column(name = "RESPONSE_DATE") + private LocalDateTime responseDate; + +} + diff --git a/src/main/java/net/gepafin/tendermanagement/entities/LookUpDataEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/LookUpDataEntity.java new file mode 100644 index 00000000..41ca9ba7 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/entities/LookUpDataEntity.java @@ -0,0 +1,37 @@ +package net.gepafin.tendermanagement.entities; + +import com.fasterxml.jackson.annotation.JsonValue; +import jakarta.persistence.*; +import lombok.Data; + +@Entity +@Table(name = "LOOKUP_DATA") +@Data +public class LookUpDataEntity extends BaseEntity{ + + @Column(name = "TITLE", length = 255, nullable = true) + private String title; + + @Column(name = "TYPE", length = 255, nullable = false) + private String type; + + @Column(name = "VALUE", columnDefinition = "TEXT", nullable = true) + private String value; + + public enum LookUpDataTypeEnum { + CHECKLIST("CHECKLIST"), + AIMED_TO("AIMED_TO"), + EVALUATION_CRITERIA("EVALUATION_CRITERIA"); + + private String value; + + LookUpDataTypeEnum(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/enums/CallTypeEnum.java b/src/main/java/net/gepafin/tendermanagement/enums/CallTypeEnum.java new file mode 100644 index 00000000..46b88869 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/enums/CallTypeEnum.java @@ -0,0 +1,21 @@ +package net.gepafin.tendermanagement.enums; + +import com.fasterxml.jackson.annotation.JsonValue; + +public enum CallTypeEnum { + + DRAFT("DRAFT"), + PUBLISH("PUBLISH"), + EXPIRE("EXPIRE"); + + private String value; + + CallTypeEnum(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/enums/DocumentTypeEnum.java b/src/main/java/net/gepafin/tendermanagement/enums/DocumentTypeEnum.java new file mode 100644 index 00000000..d5275796 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/enums/DocumentTypeEnum.java @@ -0,0 +1,20 @@ +package net.gepafin.tendermanagement.enums; + +import com.fasterxml.jackson.annotation.JsonValue; + +public enum DocumentTypeEnum { + + DOCUMENT("DOCUMENT"), + IMAGES("IMAGES"); + + private String value; + + DocumentTypeEnum(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/CreateCallRequest.java b/src/main/java/net/gepafin/tendermanagement/model/request/CreateCallRequest.java new file mode 100644 index 00000000..80d828fc --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/CreateCallRequest.java @@ -0,0 +1,49 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; +import net.gepafin.tendermanagement.enums.CallTypeEnum; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Data +public class CreateCallRequest { + + private String name; + + private String descriptionShort; + + private String descriptionLong; + + private LocalDateTime startDate; + + private LocalDateTime endDate; + + private Long regionId; + + private BigDecimal amount; + + private BigDecimal amountMax; + + private List aimedTo; + + private String documentationRequested; + + private Integer threshold; + + private Boolean Confidi; + + List criteria; + + private List faq; + + private List checkList; + + private List docs; + + private List images; + + private CallTypeEnum status; + +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/DocumentReq.java b/src/main/java/net/gepafin/tendermanagement/model/request/DocumentReq.java new file mode 100644 index 00000000..a2f65bba --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/DocumentReq.java @@ -0,0 +1,11 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; + +@Data +public class DocumentReq { + + private Long id; + private String url; + private String fileName; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/EvaluationCriteriaReq.java b/src/main/java/net/gepafin/tendermanagement/model/request/EvaluationCriteriaReq.java new file mode 100644 index 00000000..a8b90e1c --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/EvaluationCriteriaReq.java @@ -0,0 +1,11 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; + +@Data +public class EvaluationCriteriaReq { + + private String name; + private String value; + private Integer score; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/FaqReq.java b/src/main/java/net/gepafin/tendermanagement/model/request/FaqReq.java new file mode 100644 index 00000000..de9f5225 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/FaqReq.java @@ -0,0 +1,13 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; + +@Data +public class FaqReq { + + private Boolean isVisible; + private String questionShort; + private String question; + private String responseShort; + private String response; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/LookUpDataReq.java b/src/main/java/net/gepafin/tendermanagement/model/request/LookUpDataReq.java new file mode 100644 index 00000000..18b847b4 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/LookUpDataReq.java @@ -0,0 +1,11 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; + +@Data +public class LookUpDataReq { + + private Long lookUpDataId; + + private String value; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/CallResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/CallResponseBean.java new file mode 100644 index 00000000..0efff823 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/CallResponseBean.java @@ -0,0 +1,42 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Data +public class CallResponseBean { + + + private Long id; + + private String title; + + private String description; + + private LocalDateTime startDate; + + private LocalDateTime endDate; + + private String status; + + private RegionResponseBean region; + + private BigDecimal fundingAmount; + + private String contactInfo; + + private String submissionMethod; + + private Integer totalScore; + + private Integer minimumScore; + + private String priorityArea; + + private LocalDateTime createdDate; + + private LocalDateTime updatedDate; + +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/CreateCallResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/CreateCallResponseBean.java new file mode 100644 index 00000000..b913f85b --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/CreateCallResponseBean.java @@ -0,0 +1,60 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; +import net.gepafin.tendermanagement.enums.CallTypeEnum; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Data +public class CreateCallResponseBean { + + private Long id; + + private String name; + + private String descriptionShort; + + private String descriptionLong; + + private List dates; + + private CallTypeEnum status; + + private Long regionId; + + private BigDecimal amount; + + private BigDecimal amountMax; + + private String contactInfo; + + private String submissionMethod; + + private Integer threshold; + + private String priorityArea; + + private String documentationReqested; + + private LocalDateTime createdDate; + + private LocalDateTime updatedDate; + + private List aimedTo; + + private List criteria; + + private List docs; + + private List faq; + + private List images; + + private List checkList; + +} + + + diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/DocumentResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/DocumentResponseBean.java new file mode 100644 index 00000000..82aa9b9a --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/DocumentResponseBean.java @@ -0,0 +1,21 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class DocumentResponseBean { + + private Long id; + + private String name; + + private String filePath; + + private String description; + + private LocalDateTime createdDate; + + private LocalDateTime updatedDate; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/EvaluationCriteriaResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/EvaluationCriteriaResponseBean.java new file mode 100644 index 00000000..29cfed21 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/EvaluationCriteriaResponseBean.java @@ -0,0 +1,21 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class EvaluationCriteriaResponseBean { + + private Long id; + + private String name; + + private String description; + + private Integer score; + + private LocalDateTime createdDate; + + private LocalDateTime updatedDate; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/FaqResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/FaqResponseBean.java new file mode 100644 index 00000000..fdc4be63 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/FaqResponseBean.java @@ -0,0 +1,30 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; + + +import java.time.LocalDateTime; + +@Data +public class FaqResponseBean { + + private Long id; + + private Long userId; + + private Boolean isVisible; + + private String questionShort; + + private String question; + + private String responseShort; + + private String response; + + private LocalDateTime responseDate; + + private LocalDateTime createdDate; + + private LocalDateTime updatedDate; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/LookUpDataResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/LookUpDataResponse.java new file mode 100644 index 00000000..27811e63 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/LookUpDataResponse.java @@ -0,0 +1,22 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class LookUpDataResponse { + + private Long id; + + private Long lookUpDataId; + + private String title; + + private String value; + + private LocalDateTime createdDate; + + private LocalDateTime updatedDate; + +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/CallRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/CallRepository.java new file mode 100644 index 00000000..ef6e144f --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/repositories/CallRepository.java @@ -0,0 +1,8 @@ +package net.gepafin.tendermanagement.repositories; +import net.gepafin.tendermanagement.entities.CallEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CallRepository extends JpaRepository { + + +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/CallTargetAudienceChecklistRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/CallTargetAudienceChecklistRepository.java new file mode 100644 index 00000000..fe70f982 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/repositories/CallTargetAudienceChecklistRepository.java @@ -0,0 +1,7 @@ +package net.gepafin.tendermanagement.repositories; + +import net.gepafin.tendermanagement.entities.CallTargetAudienceChecklistEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CallTargetAudienceChecklistRepository extends JpaRepository { +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java new file mode 100644 index 00000000..d8d4f07a --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java @@ -0,0 +1,9 @@ +package net.gepafin.tendermanagement.repositories; +import net.gepafin.tendermanagement.entities.DocumentEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface DocumentRepository extends JpaRepository { + + DocumentEntity findById(Long id); +} + diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/EvaluationCriteriaRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/EvaluationCriteriaRepository.java new file mode 100644 index 00000000..057566a6 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/repositories/EvaluationCriteriaRepository.java @@ -0,0 +1,7 @@ +package net.gepafin.tendermanagement.repositories; + +import net.gepafin.tendermanagement.entities.EvaluationCriteriaEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface EvaluationCriteriaRepository extends JpaRepository { +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/FaqRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/FaqRepository.java new file mode 100644 index 00000000..9453ade3 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/repositories/FaqRepository.java @@ -0,0 +1,7 @@ +package net.gepafin.tendermanagement.repositories; + +import net.gepafin.tendermanagement.entities.FaqEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface FaqRepository extends JpaRepository { +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/LookUpDataRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/LookUpDataRepository.java new file mode 100644 index 00000000..e4ffb08a --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/repositories/LookUpDataRepository.java @@ -0,0 +1,7 @@ +package net.gepafin.tendermanagement.repositories; + +import net.gepafin.tendermanagement.entities.LookUpDataEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface LookUpDataRepository extends JpaRepository { +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/AmazonS3Service.java b/src/main/java/net/gepafin/tendermanagement/service/AmazonS3Service.java new file mode 100644 index 00000000..188d131a --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/AmazonS3Service.java @@ -0,0 +1,20 @@ +package net.gepafin.tendermanagement.service; + + +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.io.InputStream; + +@Component +public interface AmazonS3Service { + + + public String upload(String fileName, + MultipartFile file) throws IOException; + + public Boolean delete(String bucketName ,String fileName); + + InputStream getFile(String filePath) throws IOException; +} \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/service/CallService.java b/src/main/java/net/gepafin/tendermanagement/service/CallService.java new file mode 100644 index 00000000..5f688af3 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/CallService.java @@ -0,0 +1,10 @@ +package net.gepafin.tendermanagement.service; + +import net.gepafin.tendermanagement.model.request.CreateCallRequest; +import net.gepafin.tendermanagement.model.response.CreateCallResponseBean; + +public interface CallService { + + CreateCallResponseBean createCall(CreateCallRequest createCallRequest); + +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/DocumentService.java b/src/main/java/net/gepafin/tendermanagement/service/DocumentService.java new file mode 100644 index 00000000..806d81cc --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/DocumentService.java @@ -0,0 +1,14 @@ +package net.gepafin.tendermanagement.service; + +import net.gepafin.tendermanagement.enums.DocumentTypeEnum; +import net.gepafin.tendermanagement.model.response.DocumentResponseBean; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +public interface DocumentService { + + public List uploadFile(List files, DocumentTypeEnum fileType); + + public Void deleteFile(Long documentId); +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/AmazonS3ServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/AmazonS3ServiceImpl.java new file mode 100644 index 00000000..ad865d13 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/AmazonS3ServiceImpl.java @@ -0,0 +1,91 @@ +package net.gepafin.tendermanagement.service.impl; + +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.model.*; +import net.gepafin.tendermanagement.service.AmazonS3Service; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + + +@Service +public class AmazonS3ServiceImpl implements AmazonS3Service { + + @Autowired + private AmazonS3 amazonS3; + + @Autowired + private Environment environment; + + @Value("${aws.s3.bucket.name}") + private String bucketName; + + @Value("${aws.s3.url.folder}") + private String s3Folder; + + @Value("${aws.s3.url}") + private String s3Url; + + + @Override + public String upload(String fileName, + MultipartFile file) throws IOException { + + String path = bucketName+"/"+s3Folder; + + InputStream inputStream = file.getInputStream(); + + ObjectMetadata objectMetadata = new ObjectMetadata(); + Map metadata = new HashMap<>(); + metadata.put("Content-Type", file.getContentType()); + metadata.put("Content-Length", String.valueOf(file.getSize())); + + Optional> optionalMetaData = Optional.of(metadata); + optionalMetaData.ifPresent(map -> { + if (!map.isEmpty()) { + map.forEach(objectMetadata::addUserMetadata); + } + }); + + if(Boolean.FALSE.equals(isTestProfileActivated())) { + amazonS3.putObject(path, fileName, inputStream, objectMetadata); + } + return s3Url + s3Folder +"/"+ fileName; + } + + @Override + public Boolean delete(String bucketName,String fileName) { + + final DeleteObjectRequest deleteObjectRequest = new DeleteObjectRequest(bucketName, fileName); + if(Boolean.FALSE.equals(isTestProfileActivated())) { + amazonS3.deleteObject(deleteObjectRequest); + } + return true; + } + + public Boolean isTestProfileActivated() { + String[] activeProfiles = environment.getActiveProfiles(); + return Arrays.stream(activeProfiles).anyMatch("test"::equals); + } + + @Override + public InputStream getFile(String filePath) throws IOException { + try { + String path = bucketName+ s3Folder +"/"; + GetObjectRequest getObjectRequest = new GetObjectRequest(path, filePath); + S3Object s3Object = amazonS3.getObject(getObjectRequest); + return s3Object.getObjectContent(); + } catch (AmazonS3Exception e) { + throw new IOException("Error getting file from Amazon S3", e); + } + } +} \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/CallServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/CallServiceImpl.java new file mode 100644 index 00000000..7e59aff6 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/CallServiceImpl.java @@ -0,0 +1,21 @@ +package net.gepafin.tendermanagement.service.impl; + +import net.gepafin.tendermanagement.dao.CallDao; +import net.gepafin.tendermanagement.model.request.CreateCallRequest; +import net.gepafin.tendermanagement.model.response.CreateCallResponseBean; +import net.gepafin.tendermanagement.service.CallService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + + +@Service +public class CallServiceImpl implements CallService { + + @Autowired + private CallDao callDao; + + @Override + public CreateCallResponseBean createCall(CreateCallRequest createCallRequest) { + return callDao.createCall(createCallRequest); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/DocumentServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/DocumentServiceImpl.java new file mode 100644 index 00000000..e7bf864e --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/DocumentServiceImpl.java @@ -0,0 +1,28 @@ +package net.gepafin.tendermanagement.service.impl; + +import net.gepafin.tendermanagement.dao.DocumentDao; +import net.gepafin.tendermanagement.enums.DocumentTypeEnum; +import net.gepafin.tendermanagement.model.response.DocumentResponseBean; +import net.gepafin.tendermanagement.service.DocumentService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +@Service +public class DocumentServiceImpl implements DocumentService { + + + @Autowired + private DocumentDao fileDao; + + @Override + public List uploadFile(List files, DocumentTypeEnum fileType) { + return fileDao.uploadFiles(files,fileType); + } + @Override + public Void deleteFile(Long documentId){ + return fileDao.deleteFile(documentId); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/util/Utils.java b/src/main/java/net/gepafin/tendermanagement/util/Utils.java index aa1fe35b..ee81849b 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/Utils.java +++ b/src/main/java/net/gepafin/tendermanagement/util/Utils.java @@ -46,4 +46,17 @@ public class Utils { } return null; } + public static String extractFileName(String filePath) { + if (filePath == null || filePath.isEmpty()) { + return null; + } + int lastSlashIndex = filePath.lastIndexOf('/'); + + if (lastSlashIndex >= 0 && lastSlashIndex < filePath.length() - 1) { + return filePath.substring(lastSlashIndex + 1); + } else { + return filePath; + } + } + } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/CallApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/CallApi.java new file mode 100644 index 00000000..a6c9bfc0 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/CallApi.java @@ -0,0 +1,36 @@ +package net.gepafin.tendermanagement.web.rest.api; + +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.validation.Valid; +import net.gepafin.tendermanagement.model.request.CreateCallRequest; +import net.gepafin.tendermanagement.model.response.CreateCallResponseBean; +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.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + + +public interface CallApi { + + @Operation(summary = "API to create call", + 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 = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity> createCall( + @Parameter(description = "Call request object", required = true) + @Valid @RequestBody CreateCallRequest createCallRequest); + +} 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 new file mode 100644 index 00000000..4c3386c6 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/DocumentApi.java @@ -0,0 +1,53 @@ +package net.gepafin.tendermanagement.web.rest.api; + +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.enums.DocumentTypeEnum; +import net.gepafin.tendermanagement.model.response.DocumentResponseBean; +import net.gepafin.tendermanagement.model.util.Response; +import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +public interface DocumentApi { + + @Operation(summary = "Api to upload a file", + 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 = "/uploadFile", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + default ResponseEntity>> uploadFile(HttpServletRequest httpServletRequest, + @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 = { + @ApiResponse(responseCode = "200", description = "File deleted successfully"), + @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 = "/deleteFile") + default ResponseEntity> deleteFile(HttpServletRequest httpServletRequest, + @RequestParam( "id") Long id) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CallApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CallApiController.java new file mode 100644 index 00000000..5e68ecbd --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CallApiController.java @@ -0,0 +1,34 @@ +package net.gepafin.tendermanagement.web.rest.api.impl; + +import net.gepafin.tendermanagement.config.Translator; +import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.model.request.CreateCallRequest; +import net.gepafin.tendermanagement.model.response.CreateCallResponseBean; +import net.gepafin.tendermanagement.model.util.Response; +import net.gepafin.tendermanagement.service.CallService; +import net.gepafin.tendermanagement.web.rest.api.CallApi; +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; + + +@RestController +@RequestMapping("${openapi.gepafin.base-path:/v1/call}") +public class CallApiController implements CallApi { + + @Autowired + private CallService callService; + + + @Override + @Transactional(rollbackFor=Exception.class) + public ResponseEntity> createCall(CreateCallRequest createCallRequest) { + CreateCallResponseBean createCallResponseBean = callService.createCall(createCallRequest); + return ResponseEntity.status(HttpStatus.CREATED) + .body(new Response<>(createCallResponseBean, Status.SUCCESS, Translator.toLocale(GepafinConstant.CALL_CREATED_SUCCESSFULLY_MSG))); + } +} \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/DocumentApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/DocumentApiController.java new file mode 100644 index 00000000..d4a151b0 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/DocumentApiController.java @@ -0,0 +1,45 @@ +package net.gepafin.tendermanagement.web.rest.api.impl; + +import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.config.Translator; +import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.enums.DocumentTypeEnum; +import net.gepafin.tendermanagement.model.response.DocumentResponseBean; +import net.gepafin.tendermanagement.model.util.Response; +import net.gepafin.tendermanagement.service.DocumentService; +import net.gepafin.tendermanagement.web.rest.api.DocumentApi; +import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; +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.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +@RestController +@RequestMapping("${openapi.swaggerBflowsMiddleware.base-path:/v1/document}") +public class DocumentApiController implements DocumentApi { + + @Autowired + private DocumentService fileService; + + @Override + public ResponseEntity>> uploadFile(HttpServletRequest httpServletRequest, + List files, DocumentTypeEnum fileType) { + try { + List responseBeans=fileService.uploadFile(files,fileType); + return ResponseEntity.status(HttpStatus.CREATED) + .body(new Response>(responseBeans, Status.SUCCESS, Translator.toLocale(GepafinConstant.FILES_UPLOADED_MSG))); + } catch (CustomValidationException ex) { + throw ex; + } + } + @Override + public ResponseEntity> deleteFile(HttpServletRequest httpServletRequest, Long documentId) { + fileService.deleteFile(documentId); + return ResponseEntity.status(HttpStatus.CREATED) + .body(new Response(null, Status.SUCCESS, Translator.toLocale(GepafinConstant.FILE_DELETED_SUCCESSFULLY_MSG))); + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index f72dc2c4..b4351d76 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -24,3 +24,12 @@ spring.liquibase.enabled=true # Swagger Configuration springdoc.api-docs.path=/v1/api-docs + +#aws configuration +aws.access.key.id=AKIAVWDQWCUEOSUN4LUW +aws.secret.access.key=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 +aws.s3.region=eu-west-1 +aws.s3.bucket.name=mementoresources +aws.s3.url = https://mementoresources.s3.eu-west-1.amazonaws.com/ +aws.s3.url.folder=gepafin + 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 20506096..9877f940 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 @@ -134,4 +134,162 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index bdbcf92b..540a6b3e 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -27,3 +27,17 @@ create.regiom.error=Error occurred while creating the region. update.region.error=Error occurred while updating the region. password.doesnt.match=Password and confirm password do not match. +#call related messages +user.not.exist=User does not exist. +region.not.found=Region not found. +user.id.not.null=User ID cannot be null. +question.not.empty=Question cannot be empty. +name.not.empty=Name cannot be empty. +type.not.empty=Type cannot be empty. +region.not.null=Region ID cannot be null. +amount.greater.than.zero=Amount must be greater than zero. +look.up.data.not.valid=Look up data entity is not valid. +files.uploaded=Files uploaded successfully. +call.created.successfully=Call created successfully. +file.deleted.successfully=File deleted successfully. +document.not.found=Document not found. diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index bfd0d8f3..b6cf8f79 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -26,3 +26,18 @@ user.region.not.found=Regione non trovata. create.regiom.error=Errore durante la creazione della regione. update.region.error=Errore durante l'aggiornamento della regione. password.doesnt.match=La password e la conferma della password non corrispondono. + +#call related messages +user.not.exist=L'utente non esiste. +region.not.found=Regione non trovata. +user.id.not.null=L'ID utente non può essere nullo. +question.not.empty=La domanda non può essere vuota. +name.not.empty=Il nome non può essere vuoto. +type.not.empty=Il tipo non può essere vuoto. +region.not.null=L'ID regione non può essere nullo. +amount.greater.than.zero=L'importo del finanziamento deve essere maggiore di zero. +look.up.data.not.valid=L'entità dati di ricerca non è valida. +files.uploaded=File caricati correttamente. +call.created.successfully=Chiamata creata correttamente. +file.deleted.successfully=File eliminato con successo. +document.not.found=Documento non trovato. \ No newline at end of file From 84283ba69f0616a592cb34e3cae10be57eff2998 Mon Sep 17 00:00:00 2001 From: rajesh Date: Thu, 22 Aug 2024 11:38:17 +0530 Subject: [PATCH 7/9] updated user table name to gepafin_user --- .../net/gepafin/tendermanagement/entities/UserEntity.java | 2 +- src/main/resources/db/changelog/db.changelog-1.0.0.xml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/entities/UserEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/UserEntity.java index 042fe962..719f9a5b 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/UserEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/UserEntity.java @@ -12,7 +12,7 @@ import lombok.Setter; import java.time.LocalDateTime; @Entity -@Table(name = "\"USER\"") +@Table(name = "GEPAFIN_USER") @Getter @Setter public class UserEntity extends BaseEntity { 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 20506096..5406e4a5 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 @@ -86,10 +86,10 @@ - + + primaryKeyName="gepafin_user_pkey"/> @@ -105,7 +105,7 @@ - + From 5517550d7d16eaa902504fcbb57754e292ffe10e Mon Sep 17 00:00:00 2001 From: rajesh Date: Thu, 22 Aug 2024 11:52:33 +0530 Subject: [PATCH 8/9] added userId in the token --- .../tendermanagement/config/jwt/TokenProvider.java | 11 +++++++++-- .../gepafin/tendermanagement/model/util/JWTToken.java | 4 +--- .../service/impl/AuthenticationService.java | 8 ++------ 3 files changed, 12 insertions(+), 11 deletions(-) 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 1964bd1c..27887e26 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/jwt/TokenProvider.java +++ b/src/main/java/net/gepafin/tendermanagement/config/jwt/TokenProvider.java @@ -5,6 +5,8 @@ import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import io.jsonwebtoken.security.Keys; import jakarta.annotation.PostConstruct; +import net.gepafin.tendermanagement.entities.UserEntity; + import org.apache.commons.lang3.time.DateUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,7 +41,7 @@ public class TokenProvider { log.info("JWT Secret Key initialized."); } - public String createToken(Authentication authentication, Boolean rememberMe) { + public String createToken(Authentication authentication, Boolean rememberMe, UserEntity user) { String authorities = authentication.getAuthorities().stream() .map(GrantedAuthority::getAuthority) .collect(Collectors.joining(",")); @@ -55,9 +57,14 @@ public class TokenProvider { validity = new Date(now + (this.tokenValidityInSeconds * 1000)); log.info("Creating token with standard validity of {} seconds.", this.tokenValidityInSeconds); } + + String payload = authentication.getName(); + if(user != null) { + payload += ":"+user.getId(); + } String token = Jwts.builder() - .setSubject(authentication.getName()) + .setSubject(payload) .claim("auth", authorities) .signWith(key, SignatureAlgorithm.HS512) .setExpiration(validity) diff --git a/src/main/java/net/gepafin/tendermanagement/model/util/JWTToken.java b/src/main/java/net/gepafin/tendermanagement/model/util/JWTToken.java index 53596d25..a57b7d59 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/util/JWTToken.java +++ b/src/main/java/net/gepafin/tendermanagement/model/util/JWTToken.java @@ -1,11 +1,9 @@ package net.gepafin.tendermanagement.model.util; import com.fasterxml.jackson.annotation.JsonProperty; + import lombok.Data; -import lombok.Getter; -import lombok.Setter; import net.gepafin.tendermanagement.model.response.LoginResponse; -import net.gepafin.tendermanagement.model.response.UserResponseBean; /** * JWTToken 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 022f3775..1d76fc3c 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java @@ -19,7 +19,6 @@ import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; @Service @@ -33,9 +32,6 @@ public class AuthenticationService { @Autowired private UserRepository userRepository; - @Autowired - private PasswordEncoder passwordEncoder; - @Autowired private RoleDao roleDao; @@ -51,13 +47,13 @@ public class AuthenticationService { Authentication authentication = this.authenticationManager.authenticate(authenticationToken); SecurityContextHolder.getContext().setAuthentication(authentication); log.info("Authentication successful for email: {}", loginReq.getEmail()); - String token = tokenProvider.createToken(authentication, loginReq.getRememberMe()); - log.info("JWT token generated for email: {}", loginReq.getEmail()); UserEntity user = userRepository.findByEmail(loginReq.getEmail()); if (user == null) { log.error("User not found for email: {}", loginReq.getEmail()); throw new CustomValidationException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG)); } + String token = tokenProvider.createToken(authentication, loginReq.getRememberMe(), user); + log.info("JWT token generated for email: {}", loginReq.getEmail()); RoleResponseBean roleResponseBean = roleDao.convertRoleEntityToRoleResponse(user.getRoleEntity()); JWTToken jwtToken = new JWTToken(token, new LoginResponse(user.getId(), user.getEmail(), user.getFirstName(), user.getLastName(), roleResponseBean, user.getPhoneNumber(), user.getAddress(), user.getOrganization(), From f8f58689c4651e51057e4b1c5b260e04978def37 Mon Sep 17 00:00:00 2001 From: harish Date: Thu, 22 Aug 2024 12:32:27 +0530 Subject: [PATCH 9/9] added userId in the faq table --- pom.xml | 8 ++ .../config/jwt/TokenProvider.java | 92 ++++++++++++++++++- .../gepafin/tendermanagement/dao/CallDao.java | 20 ++-- .../tendermanagement/service/CallService.java | 3 +- .../service/impl/CallServiceImpl.java | 12 ++- .../gepafin/tendermanagement/util/Utils.java | 10 ++ .../web/rest/api/CallApi.java | 3 +- .../web/rest/api/impl/CallApiController.java | 5 +- .../db/changelog/db.changelog-1.0.0.xml | 2 +- 9 files changed, 136 insertions(+), 19 deletions(-) diff --git a/pom.xml b/pom.xml index 07434795..1b55d803 100644 --- a/pom.xml +++ b/pom.xml @@ -129,6 +129,14 @@ hibernate-validator + + com.google.code.gson + gson + 2.10.1 + + + + 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 27887e26..c3c54d99 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/jwt/TokenProvider.java +++ b/src/main/java/net/gepafin/tendermanagement/config/jwt/TokenProvider.java @@ -5,8 +5,10 @@ import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import io.jsonwebtoken.security.Keys; import jakarta.annotation.PostConstruct; +import jakarta.servlet.http.HttpServletRequest; import net.gepafin.tendermanagement.entities.UserEntity; - +import net.gepafin.tendermanagement.util.Utils; +import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.time.DateUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -18,11 +20,17 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; import javax.crypto.SecretKey; import java.nio.charset.StandardCharsets; import java.util.*; import java.util.stream.Collectors; +import com.google.gson.Gson; + +import static io.micrometer.common.util.StringUtils.isEmpty; + + @Component public class TokenProvider { private final Logger log = LoggerFactory.getLogger(TokenProvider.class); @@ -35,13 +43,19 @@ public class TokenProvider { private SecretKey key; + private static final String AUTHORITIES_KEY = "auth"; + private static final String MERCHANTID="merchantId"; + + public static final String INVALID_USER = "invalid_user"; + static final String AUTH_SECRET = "X-Api-Secret"; + @PostConstruct public void init() { this.key = Keys.hmacShaKeyFor(secretKey.getBytes(StandardCharsets.UTF_8)); log.info("JWT Secret Key initialized."); } - public String createToken(Authentication authentication, Boolean rememberMe, UserEntity user) { + public String createToken(Authentication authentication, Boolean rememberMe, UserEntity user) { String authorities = authentication.getAuthorities().stream() .map(GrantedAuthority::getAuthority) .collect(Collectors.joining(",")); @@ -60,7 +74,7 @@ public class TokenProvider { String payload = authentication.getName(); if(user != null) { - payload += ":"+user.getId(); + payload += ":"+user.getId(); } String token = Jwts.builder() @@ -110,4 +124,76 @@ public class TokenProvider { return false; } } + public Map getUserInfoAndUserIdFromToken(HttpServletRequest request) { + Map userInfo = new HashMap<>(); + String authSecretHeader=request.getHeader(AUTH_SECRET); +// userInfo.put(MERCHANTID, null); + String bearerToken = request.getHeader("Authorization"); + String token = ""; + if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) { + token = bearerToken.substring(7, bearerToken.length()); + } + extractDetailsFromTheToken(userInfo, authSecretHeader, token); + return userInfo; + } + public Map extractDetailsFromTheToken(Map userInfo, String authSecretHeader, + String token) { + String payload = null; + Boolean isSuperAdmin = false; +// if (StringUtils.hasText(token) && token.endsWith("_superKey" + getSuperUserToken())) { +// Map payloadMap = getUserDetailsForSuperUser(token); +// payload = payloadMap.get("sub").toString(); +// isSuperAdmin = true; +// +// } else + if (!isEmpty(authSecretHeader)) { + String secret = Utils.decodeBase64String(authSecretHeader); + String[] tokenArr = secret.split("\\.", 2); + String[] merchant = tokenArr[0].split("-"); + if (ArrayUtils.isNotEmpty(merchant) && 2 <= merchant.length) { + userInfo.put(MERCHANTID, merchant[1]); + return userInfo; + } + + } else { + payload = getUserDetails(token); + } + if (payload != null && !isSuperAdmin) { + String[] payloadString = payload.split(":");{ + + if (payloadString.length > 1) { +// userInfo.put(MERCHANTID, payloadString[1]); +// userInfo.put("associatedTags", payloadString[2]); + userInfo.put("userId", payloadString[1]); + } + } + + if (payloadString.length > 1) { +// userInfo.put(MERCHANTID, payloadString[1]); +// userInfo.put("associatedTags", payloadString[2]); + userInfo.put("userId", payloadString[1]); + } + } else { + String[] payloadString = payload.split(":"); + + if (payloadString.length > 1) { + userInfo.put("userId", payloadString[1]); + } + } + + return userInfo; + } + public Map getUserDetailsForSuperUser(String token) { + Base64.Decoder decoder = Base64.getUrlDecoder(); + String[] parts = token.split("\\."); // Splitting header, payload and signature + Gson g = new Gson(); + return g.fromJson(new String(decoder.decode(parts[1])), Map.class); + } +// public String getSuperUserToken() { +// return superUserToken; +// } + public String getUserDetails(String token) { + Claims claims = Jwts.parser().setSigningKey(key).parseClaimsJws(token).getBody(); + return claims.getSubject(); + } } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java index fc2b966c..d034f8a7 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java @@ -14,7 +14,6 @@ import net.gepafin.tendermanagement.enums.CallTypeEnum; import net.gepafin.tendermanagement.model.request.*; import net.gepafin.tendermanagement.model.response.*; import net.gepafin.tendermanagement.repositories.*; -import net.gepafin.tendermanagement.service.AmazonS3Service; import net.gepafin.tendermanagement.util.DateTimeUtil; import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException; @@ -48,14 +47,17 @@ public class CallDao { @Autowired private CallTargetAudienceChecklistRepository callTargetAudienceChecklistRepository; - public CreateCallResponseBean createCall(CreateCallRequest createCallRequest) { + @Autowired + private UserRepository userRepository; + + public CreateCallResponseBean createCall(CreateCallRequest createCallRequest, Long userId) { try { CreateCallResponseBean createCallResponseBean=null; CallEntity callEntity = convertToCallEntity(createCallRequest); List evaluationCriteriaEntities = convertToEvaluationCriteriaEntities(createCallRequest.getCriteria(), callEntity); List documentEntities = convertToDocumentEntities(createCallRequest.getDocs(), callEntity); List imageEntities=convertToDocumentEntities(createCallRequest.getImages(),callEntity); - List faqEntities = convertToFaqEntities(createCallRequest.getFaq(), callEntity); + List faqEntities = convertToFaqEntities(createCallRequest.getFaq(), callEntity, userId); List amiedTo=convertLookUpDataEntities(createCallRequest.getAimedTo(),callEntity,LookUpDataTypeEnum.AIMED_TO); List checkList=convertLookUpDataEntities(createCallRequest.getAimedTo(),callEntity,LookUpDataTypeEnum.CHECKLIST); createCallResponseBean= assembleCreateCallResponseBean(callEntity, evaluationCriteriaEntities, documentEntities, faqEntities,imageEntities); @@ -125,18 +127,18 @@ public class CallDao { } - public List convertToFaqEntities(List faqReqList, CallEntity callEntity) { - List faqEntities = faqReqList.stream().map(req -> convertToFaqEntity(req, callEntity)).collect(Collectors.toList()); + public List convertToFaqEntities(List faqReqList, CallEntity callEntity, Long userId) { + List faqEntities = faqReqList.stream().map(req -> convertToFaqEntity(req, callEntity, userId)).collect(Collectors.toList()); faqRepository.saveAll(faqEntities); return faqEntities; } - private FaqEntity convertToFaqEntity(FaqReq faqReq, CallEntity callEntity) { + private FaqEntity convertToFaqEntity(FaqReq faqReq, CallEntity callEntity, Long userId) { FaqEntity faqEntity = new FaqEntity(); validateFaqEntity(faqReq.getQuestion()); -// UserEntity userEntity= userRepository.findById(1l) -// .orElseThrow(() -> new ResourceNotFoundException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.LOOK_UP_DATA_NOT_VALID_MSG))); -// faqEntity.setUser(userEntity); + UserEntity userEntity= userRepository.findById(userId) + .orElseThrow(() -> new ResourceNotFoundException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.LOOK_UP_DATA_NOT_VALID_MSG))); + faqEntity.setUser(userEntity); faqEntity.setIsVisible(true); if(faqReq.getIsVisible()!=null){ faqEntity.setIsVisible(faqReq.getIsVisible()); diff --git a/src/main/java/net/gepafin/tendermanagement/service/CallService.java b/src/main/java/net/gepafin/tendermanagement/service/CallService.java index 5f688af3..40dfd65f 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/CallService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/CallService.java @@ -1,10 +1,11 @@ package net.gepafin.tendermanagement.service; +import jakarta.servlet.http.HttpServletRequest; import net.gepafin.tendermanagement.model.request.CreateCallRequest; import net.gepafin.tendermanagement.model.response.CreateCallResponseBean; public interface CallService { - CreateCallResponseBean createCall(CreateCallRequest createCallRequest); + CreateCallResponseBean createCall(HttpServletRequest request, CreateCallRequest createCallRequest); } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/CallServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/CallServiceImpl.java index 7e59aff6..cb4b76bc 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/CallServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/CallServiceImpl.java @@ -1,5 +1,7 @@ package net.gepafin.tendermanagement.service.impl; +import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.config.jwt.TokenProvider; import net.gepafin.tendermanagement.dao.CallDao; import net.gepafin.tendermanagement.model.request.CreateCallRequest; import net.gepafin.tendermanagement.model.response.CreateCallResponseBean; @@ -7,6 +9,8 @@ import net.gepafin.tendermanagement.service.CallService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.util.Map; + @Service public class CallServiceImpl implements CallService { @@ -14,8 +18,12 @@ public class CallServiceImpl implements CallService { @Autowired private CallDao callDao; + @Autowired + private TokenProvider tokenProvider; + @Override - public CreateCallResponseBean createCall(CreateCallRequest createCallRequest) { - return callDao.createCall(createCallRequest); + public CreateCallResponseBean createCall(HttpServletRequest request, CreateCallRequest createCallRequest) { + Map userInfo= tokenProvider.getUserInfoAndUserIdFromToken(request); + return callDao.createCall(createCallRequest, Long.parseLong(userInfo.get("userId").toString())); } } diff --git a/src/main/java/net/gepafin/tendermanagement/util/Utils.java b/src/main/java/net/gepafin/tendermanagement/util/Utils.java index ee81849b..21392d61 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/Utils.java +++ b/src/main/java/net/gepafin/tendermanagement/util/Utils.java @@ -3,9 +3,12 @@ package net.gepafin.tendermanagement.util; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import io.micrometer.common.util.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.nio.charset.StandardCharsets; +import java.util.Base64; import java.util.List; import java.util.stream.Collectors; @@ -58,5 +61,12 @@ public class Utils { return filePath; } } + public static String decodeBase64String(String decodedString) { + if (StringUtils.isBlank(decodedString)) { + return decodedString; + } + byte[] decode = Base64.getDecoder().decode(decodedString.getBytes(StandardCharsets.UTF_8)); + return new String(decode, StandardCharsets.UTF_8); + } } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/CallApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/CallApi.java index a6c9bfc0..bd8863b5 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/CallApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/CallApi.java @@ -5,6 +5,7 @@ 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 jakarta.validation.Valid; import net.gepafin.tendermanagement.model.request.CreateCallRequest; import net.gepafin.tendermanagement.model.response.CreateCallResponseBean; @@ -29,7 +30,7 @@ public interface CallApi { @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) @PostMapping(value = "", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity> createCall( + public ResponseEntity> createCall(HttpServletRequest request, @Parameter(description = "Call request object", required = true) @Valid @RequestBody CreateCallRequest createCallRequest); diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CallApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CallApiController.java index 5e68ecbd..d4165383 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CallApiController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CallApiController.java @@ -1,5 +1,6 @@ package net.gepafin.tendermanagement.web.rest.api.impl; +import jakarta.servlet.http.HttpServletRequest; import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.model.request.CreateCallRequest; @@ -26,8 +27,8 @@ public class CallApiController implements CallApi { @Override @Transactional(rollbackFor=Exception.class) - public ResponseEntity> createCall(CreateCallRequest createCallRequest) { - CreateCallResponseBean createCallResponseBean = callService.createCall(createCallRequest); + public ResponseEntity> createCall(HttpServletRequest request, CreateCallRequest createCallRequest) { + CreateCallResponseBean createCallResponseBean = callService.createCall(request, createCallRequest); return ResponseEntity.status(HttpStatus.CREATED) .body(new Response<>(createCallResponseBean, Status.SUCCESS, Translator.toLocale(GepafinConstant.CALL_CREATED_SUCCESSFULLY_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 bb80c810..eb0d2fdc 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 @@ -212,7 +212,7 @@ - +