diff --git a/pom.xml b/pom.xml
index 1572627b..2d93875f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -27,14 +27,12 @@
org.projectlombok
lombok
- 1.18.24
com.h2database
h2
- 1.4.200
@@ -80,6 +78,38 @@
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
+
+
+ jakarta.validation
+ jakarta.validation-api
+
+
+ org.hibernate.validator
+ hibernate-validator
+
+
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..1964bd1c
--- /dev/null
+++ b/src/main/java/net/gepafin/tendermanagement/config/jwt/TokenProvider.java
@@ -0,0 +1,106 @@
+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));
+ log.info("JWT Secret Key initialized.");
+ }
+
+ public String createToken(Authentication authentication, Boolean rememberMe) {
+ String authorities = authentication.getAuthorities().stream()
+ .map(GrantedAuthority::getAuthority)
+ .collect(Collectors.joining(","));
+ Long now;
+ Date validity;
+
+ if (Boolean.TRUE.equals(rememberMe)) {
+ now = DateUtils.addMonths(new Date(), 2).getTime();
+ validity = new Date(now);
+ 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);
+ }
+
+ 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) {
+ Claims claims = Jwts.parserBuilder()
+ .setSigningKey(key)
+ .build()
+ .parseClaimsJws(token)
+ .getBody();
+
+ 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 extends GrantedAuthority> ClaimsToAuthorities(Object authClaim) {
+ Collection extends GrantedAuthority> 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) {
+ try {
+ Jwts.parserBuilder()
+ .setSigningKey(key)
+ .build()
+ .parseClaimsJws(authToken);
+ log.info("Token is valid.");
+ return true;
+ } catch (Exception e) {
+ log.error("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..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;
}
- private 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 08c1a40f..e7f4c5f9 100644
--- a/src/main/java/net/gepafin/tendermanagement/dao/RoleDao.java
+++ b/src/main/java/net/gepafin/tendermanagement/dao/RoleDao.java
@@ -4,12 +4,15 @@ 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;
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;
@@ -20,61 +23,88 @@ 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;
+ @Autowired
+ 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;
}
- 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());
+
+ 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);
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 63a7c353..b2fd8190 100644
--- a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java
+++ b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java
@@ -4,39 +4,73 @@ 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.LoginReq;
import net.gepafin.tendermanagement.model.request.UpdateUserReq;
import net.gepafin.tendermanagement.model.request.UserReq;
+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.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())) {
- throw new CustomValidationException(Status.VALIDATION_ERROR,Translator.toLocale(GepafinConstant.PASSWORD_DOESNT_MATCH));
+ 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());
@@ -48,20 +82,21 @@ public class UserDao {
setIfUpdated(userEntity::getRoleEntity, userEntity::setRoleEntity, roleEntity);
}
userEntity = userRepository.save(userEntity);
+ log.info("User updated with ID: {}", userEntity.getId());
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()));
+ 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;
}
@@ -70,7 +105,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());
@@ -80,20 +114,32 @@ 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;
}
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) {
+ 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/entities/RegionEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/RegionEntity.java
index d9687dd1..386b9787 100644
--- a/src/main/java/net/gepafin/tendermanagement/entities/RegionEntity.java
+++ b/src/main/java/net/gepafin/tendermanagement/entities/RegionEntity.java
@@ -2,19 +2,15 @@ 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\"")
+@Table(name = "REGION")
@Getter
@Setter
public class RegionEntity extends BaseEntity {
diff --git a/src/main/java/net/gepafin/tendermanagement/entities/RoleEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/RoleEntity.java
index 25693802..ff741702 100644
--- a/src/main/java/net/gepafin/tendermanagement/entities/RoleEntity.java
+++ b/src/main/java/net/gepafin/tendermanagement/entities/RoleEntity.java
@@ -6,7 +6,7 @@ import lombok.Getter;
import lombok.Setter;
@Entity
-@Table(name = "\"ROLE\"")
+@Table(name = "ROLE")
@Getter
@Setter
public class RoleEntity extends BaseEntity {
diff --git a/src/main/java/net/gepafin/tendermanagement/entities/UserEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/UserEntity.java
index 890fdc32..042fe962 100644
--- a/src/main/java/net/gepafin/tendermanagement/entities/UserEntity.java
+++ b/src/main/java/net/gepafin/tendermanagement/entities/UserEntity.java
@@ -8,7 +8,6 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.Setter;
-import net.gepafin.tendermanagement.entities.BaseEntity;
import java.time.LocalDateTime;
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..97a59438 100644
--- a/src/main/java/net/gepafin/tendermanagement/model/request/UserReq.java
+++ b/src/main/java/net/gepafin/tendermanagement/model/request/UserReq.java
@@ -1,32 +1,30 @@
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;
import lombok.Setter;
-import java.time.LocalDateTime;
-
@Getter
@Setter
public class UserReq {
-
- private String password;
-
- private String confPassword;
-
+ @NotBlank
+ @Email
private String email;
+ @NotEmpty
+ private String password;
+ @NotEmpty
+ private String confPassword;
private String firstName;
private String lastName;
private String phoneNumber;
-
+ @NotNull
private Long roleId;
private String organization;
@@ -39,6 +37,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..022f3775
--- /dev/null
+++ b/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java
@@ -0,0 +1,71 @@
+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.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;
+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
+public class AuthenticationService {
+
+ private final Logger log = LoggerFactory.getLogger(AuthenticationService.class);
+
+ 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) {
+ 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;
+ }
+}
+
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..7c310b83 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;
@@ -21,23 +23,22 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Validated
-//@RequestMapping("/user")
public interface UserApi {
@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) })),
+ @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) {
+ @Parameter(description = "User request object", required = true) @Validated @RequestBody UserReq userReq) {
return new ResponseEntity>(HttpStatus.NOT_IMPLEMENTED);
}
@@ -45,13 +46,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 +64,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 +81,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..f44c2e87 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);
@@ -29,44 +32,46 @@ public class UserApiController implements UserApi {
private UserService userService;
@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)));
+ public ResponseEntity> createUser(@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)));
-
+ 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 f72dc2c4..e9ceddde 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -19,8 +19,15 @@ spring.liquibase.default-schema=gepafin_schema
spring.liquibase.enabled=true
-# Debugging and SQL Output
-
# Swagger Configuration
springdoc.api-docs.path=/v1/api-docs
+
+# 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.
+
+