diff --git a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java index f000c416..fa2b2020 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java @@ -1,7 +1,5 @@ package net.gepafin.tendermanagement.config; -import java.util.ArrayList; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -17,12 +15,10 @@ 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.access.intercept.AuthorizationFilter; 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.CorsConfigurationSource; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; import org.springframework.web.servlet.handler.HandlerMappingIntrospector; @@ -71,18 +67,6 @@ public class SecurityConfig { .requestMatchers(new AntPathRequestMatcher("/swagger-ui/**")); } - -// @Bean -// public CorsFilter corsFilter() { -// UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); -// CorsConfiguration config = new CorsConfiguration(); -// config.setAllowCredentials(true); -// config.addAllowedOrigin("http://localhost:3000"); -// config.addAllowedMethod("*"); -// config.addAllowedHeader("*"); -// source.registerCorsConfiguration("/**", config); -// return new CorsFilter(source); -// } @Bean public CorsFilter corsFilter() { @@ -109,7 +93,6 @@ public class SecurityConfig { .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() diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index 75b748fe..c3de4e48 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -10,6 +10,7 @@ public class GepafinConstant { 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 USER_NOT_ACTIVE_MSG = "user.not.active"; public static final String ROLE_CREATED_SUCCESS_MSG = "role.created.success"; public static final String ROLE_UPDATED_SUCCESS_MSG = "role.updated.success"; diff --git a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java index b4987c81..179b3f4e 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java @@ -19,6 +19,7 @@ import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationExceptio 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.access.prepost.PreAuthorize; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import net.gepafin.tendermanagement.entities.LookUpDataEntity.LookUpDataTypeEnum; diff --git a/src/main/java/net/gepafin/tendermanagement/dao/RoleDao.java b/src/main/java/net/gepafin/tendermanagement/dao/RoleDao.java index e7f4c5f9..d0c6342c 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/RoleDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/RoleDao.java @@ -45,6 +45,7 @@ public class RoleDao { private RoleEntity convertRoleRequestToRoleEntity(RoleReq roleReq) { RoleEntity roleEntity = new RoleEntity(); roleEntity.setRoleName(roleReq.getRoleName()); + roleEntity.setRoleType(roleReq.getRoleType()); roleEntity.setPermissions(roleReq.getPermissions()); roleEntity.setDescription(roleReq.getDescription()); roleEntity.setRegion(regionService.getRegionById(roleReq.getRegionId())); @@ -57,6 +58,7 @@ public class RoleDao { roleResponseBean.setCreatedDate(roleEntity.getCreatedDate()); roleResponseBean.setUpdatedDate(roleEntity.getUpdatedDate()); roleResponseBean.setRoleName(roleEntity.getRoleName()); + roleResponseBean.setRoleType(roleEntity.getRoleType()); roleResponseBean.setDescription(roleEntity.getDescription()); roleResponseBean.setPermissions(roleEntity.getPermissions()); RegionResponseBean regionResponseBean = regionDao.convertRegionEntityToRegionResponse(roleEntity.getRegion()); @@ -73,6 +75,7 @@ public class RoleDao { log.info("New role details: {}", roleReq); setIfUpdated(existingRole::getRoleName, existingRole::setRoleName, roleReq.getRoleName()); + setIfUpdated(existingRole::getRoleType, existingRole::setRoleType, roleReq.getRoleType()); setIfUpdated(existingRole::getDescription, existingRole::setDescription, roleReq.getDescription()); setIfUpdated(existingRole::getPermissions, existingRole::setPermissions, roleReq.getPermissions()); diff --git a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java index 2ca30fe6..dc06326f 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java @@ -47,7 +47,7 @@ public class UserDao { public UserResponseBean createUser(UserReq userReq) { log.info("Creating user with email: {}", userReq.getEmail()); - if (userRepository.existsByEmail(userReq.getEmail())) { + if (userRepository.existsByEmailIgnoreCase(userReq.getEmail())) { log.error("User creation failed: Email {} already exists", userReq.getEmail()); throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.EMAIL_ALREADY_EXISTS)); } @@ -94,7 +94,7 @@ public class UserDao { userEntity.setPassword(passwordEncoder.encode(userReq.getPassword())); userEntity.setEmail(userReq.getEmail()); userEntity.setFirstName(userReq.getFirstName()); - userEntity.setStatus(userReq.getStatus().getValue()); + userEntity.setStatus(UserStatusEnum.PENDING_VERIFICATION.getValue()); userEntity.setLastName(userReq.getLastName()); userEntity.setOrganization(userReq.getOrganization()); userEntity.setAddress(userReq.getAddress()); @@ -127,10 +127,10 @@ public class UserDao { 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))); - if (!UserStatusEnum.ACTIVE.getValue().equals(userEntity.getStatus())) { - log.info("User with ID: {} is not active", id); - throw new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG)); - } +// if (!UserStatusEnum.ACTIVE.getValue().equals(userEntity.getStatus())) { +// log.info("User with ID: {} is not active", id); +// throw new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG)); +// } log.info("User found: {}", userEntity); return convertUserEntityToUserResponse(userEntity); } diff --git a/src/main/java/net/gepafin/tendermanagement/entities/RoleEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/RoleEntity.java index ff741702..c94b36b9 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/RoleEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/RoleEntity.java @@ -11,7 +11,7 @@ import lombok.Setter; @Setter public class RoleEntity extends BaseEntity { - @Column(name = "ROLE_NAME", length = 50, nullable = true) + @Column(name = "ROLE_NAME", length = 255, nullable = true) private String roleName; @Column(name = "DESCRIPTION", length = 255, nullable = true) @@ -19,8 +19,12 @@ public class RoleEntity extends BaseEntity { @Column(name = "PERMISSIONS", length = 255, nullable = true) private String permissions; + @ManyToOne @JoinColumn(name = "REGION_ID", nullable = true) private RegionEntity region; + + @Column(name = "ROLE_TYPE", length = 255, nullable = true) + private String roleType; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/RoleReq.java b/src/main/java/net/gepafin/tendermanagement/model/request/RoleReq.java index f1fd7d70..50cf17ce 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/request/RoleReq.java +++ b/src/main/java/net/gepafin/tendermanagement/model/request/RoleReq.java @@ -1,8 +1,6 @@ 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; @@ -21,5 +19,7 @@ public class RoleReq { private String permissions; private Long regionId; + + private String roleType; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/UpdateUserReq.java b/src/main/java/net/gepafin/tendermanagement/model/request/UpdateUserReq.java index f4a8a107..65eba841 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/request/UpdateUserReq.java +++ b/src/main/java/net/gepafin/tendermanagement/model/request/UpdateUserReq.java @@ -1,7 +1,5 @@ package net.gepafin.tendermanagement.model.request; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; import lombok.Getter; import lombok.Setter; import net.gepafin.tendermanagement.enums.UserStatusEnum; 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 07761068..54841e9b 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/request/UserReq.java +++ b/src/main/java/net/gepafin/tendermanagement/model/request/UserReq.java @@ -36,6 +36,4 @@ public class UserReq { private String country; - private UserStatusEnum status; - } 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 d5d579e5..da097f48 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/RoleResponseBean.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/RoleResponseBean.java @@ -14,4 +14,5 @@ public class RoleResponseBean extends BaseBean { private String description; private String permissions; private RegionResponseBean region; + private String roleType; } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java index dc0aad37..6b6fcbe0 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java @@ -6,6 +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); + Optional findByEmailIgnoreCase(String email); + boolean existsByEmailIgnoreCase(String email); } 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 6ad8cf5f..6955edf4 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java @@ -5,6 +5,7 @@ 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.enums.UserStatusEnum; import net.gepafin.tendermanagement.model.request.LoginReq; import net.gepafin.tendermanagement.model.response.LoginResponse; import net.gepafin.tendermanagement.model.response.RoleResponseBean; @@ -43,30 +44,32 @@ public class AuthenticationService { 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()); - 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)); - } - user.setLastLogin(DateTimeUtil.DateServerToUTC(LocalDateTime.now())); - userRepository.save(user); - String token = tokenProvider.createToken(authentication, loginReq.getRememberMe(), user); - log.info("JWT token generated for email: {}", loginReq.getEmail()); - RoleResponseBean roleResponseBean = roleDao.convertRoleEntityToRoleResponse(user.getRoleEntity()); + 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()); + UserEntity user = userRepository.findByEmailIgnoreCase(loginReq.getEmail()).orElseThrow(()-> new CustomValidationException(Status.NOT_FOUND, + Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG))); + if (Boolean.FALSE.equals(UserStatusEnum.ACTIVE.getValue().equals(user.getStatus()))) { + new CustomValidationException(Status.NOT_FOUND, + Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG)); + } + user.setLastLogin(DateTimeUtil.DateServerToUTC(LocalDateTime.now())); + userRepository.save(user); + String token = tokenProvider.createToken(authentication, loginReq.getRememberMe(), user); + log.info("JWT token generated for email: {}", loginReq.getEmail()); + RoleResponseBean roleResponseBean = roleDao.convertRoleEntityToRoleResponse(user.getRoleEntity()); - LoginResponse loginResponse = getLoginResponse(user, roleResponseBean); + LoginResponse loginResponse = getLoginResponse(user, roleResponseBean); - JWTToken jwtToken = new JWTToken(token, loginResponse); + JWTToken jwtToken = new JWTToken(token, loginResponse); - log.info("Login successful for email: {}", loginReq.getEmail()); - return jwtToken; - } + log.info("Login successful for email: {}", loginReq.getEmail()); + return jwtToken; + } private static LoginResponse getLoginResponse(UserEntity user, RoleResponseBean roleResponseBean) { LoginResponse loginResponse = new LoginResponse(); 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 b2b335de..637ad6f8 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 @@ -31,7 +31,7 @@ public interface CallApi { @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) @PostMapping(value = "", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE) - @PreAuthorize("hasRole('SUPER_ADMIN')") + @PreAuthorize("hasRole('ROLE_SUPER_ADMIN')") 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/UserApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/UserApi.java index 7c310b83..cca0b247 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 @@ -16,6 +16,7 @@ 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.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; @@ -37,6 +38,7 @@ public interface UserApi { @RequestMapping(value = "", produces = {"application/json"}, method = RequestMethod.POST) + @PreAuthorize("hasRole('ROLE_SUPER_ADMIN')") default ResponseEntity> createUser( @Parameter(description = "User request object", required = true) @Validated @RequestBody UserReq userReq) { return new ResponseEntity>(HttpStatus.NOT_IMPLEMENTED); 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 index 102a388c..7345d13e 100644 --- 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 @@ -1,9 +1,13 @@ package net.gepafin.tendermanagement.web.rest.api.impl; +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.repositories.RoleRepository; import net.gepafin.tendermanagement.repositories.UserRepository; +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.security.core.GrantedAuthority; @@ -22,11 +26,9 @@ 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) { + public CustomUserDetailsService(UserRepository userRepository) { this.userRepository = userRepository; - this.roleRepository = roleRepository; } @Override @@ -34,17 +36,15 @@ public class CustomUserDetailsService implements UserDetailsService { 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"); - } - + UserEntity user = userRepository.findByEmailIgnoreCase(email) + .orElseThrow( + () -> 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()); + GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(role.getRoleType()); return new org.springframework.security.core.userdetails.User( user.getEmail(), 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 ffd93d80..d090e106 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 @@ -66,6 +66,9 @@ + + + @@ -314,7 +317,8 @@ - + + @@ -324,7 +328,8 @@ - + + @@ -334,7 +339,8 @@ - + + @@ -344,7 +350,8 @@ - + + diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index 1c9cc13b..c35db8ac 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -7,6 +7,7 @@ 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. +user.not.active=User is not active. Please contact support. # Role-related messages role.created.success=Role created successfully. role.updated.success=Role updated successfully. diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index 326c7329..085c1ce4 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -7,6 +7,7 @@ update_user_error_msg=Si � verificato un errore durante l'aggiornamento dell'u 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. +user.not.active=Utente non attivo. Si prega di contattare il supporto. # Role-related messages role.created.success=Ruolo creato con successo. role.updated.success=Ruolo aggiornato con successo.