package net.gepafin.tendermanagement.service.impl; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.config.jwt.TokenProvider; import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.dao.CompanyDao; import net.gepafin.tendermanagement.dao.LoginAttemptDao; import net.gepafin.tendermanagement.dao.RoleDao; import net.gepafin.tendermanagement.entities.HubEntity; import net.gepafin.tendermanagement.entities.LoginAttemptEntity; import net.gepafin.tendermanagement.entities.SamlResponseEntity; import net.gepafin.tendermanagement.entities.UserEntity; import net.gepafin.tendermanagement.enums.LoginAttemptResultEnum; import net.gepafin.tendermanagement.enums.LoginAttemptTypeEnum; import net.gepafin.tendermanagement.enums.UserStatusEnum; import net.gepafin.tendermanagement.enums.VersionActionTypeEnum; import net.gepafin.tendermanagement.model.request.LoginReq; import net.gepafin.tendermanagement.model.request.VersionHistoryRequest; import net.gepafin.tendermanagement.model.response.CompanyResponse; import net.gepafin.tendermanagement.model.response.LoginResponse; import net.gepafin.tendermanagement.model.response.RoleResponseBean; import net.gepafin.tendermanagement.model.response.UserSamlResponse; import net.gepafin.tendermanagement.model.util.JWTToken; import net.gepafin.tendermanagement.repositories.LoginAttemptRepository; import net.gepafin.tendermanagement.repositories.SamlResponseRepository; import net.gepafin.tendermanagement.repositories.UserRepository; import net.gepafin.tendermanagement.service.HubService; import net.gepafin.tendermanagement.util.DateTimeUtil; import net.gepafin.tendermanagement.util.LoggingUtil; import net.gepafin.tendermanagement.util.Utils; import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException; import net.gepafin.tendermanagement.web.rest.api.errors.Status; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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.web.authentication.logout.SecurityContextLogoutHandler; import org.springframework.stereotype.Service; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.List; import java.util.Map; @Service public class AuthenticationService { private final Logger log = LoggerFactory.getLogger(AuthenticationService.class); private final TokenProvider tokenProvider; private final AuthenticationManager authenticationManager; @Autowired private CompanyDao companyDao; @Autowired private UserRepository userRepository; @Autowired private RoleDao roleDao; @Autowired private SamlResponseRepository samlResponseLogRepository; @Autowired private LoginAttemptDao loginAttemptDao; @Autowired private HubService hubService; @Autowired private HttpServletRequest request; @Autowired private LoggingUtil loggingUtil; @Autowired LoginAttemptRepository loginAttemptRepository; @Autowired public AuthenticationService(TokenProvider tokenProvider, AuthenticationManager authenticationManager) { this.tokenProvider = tokenProvider; this.authenticationManager = authenticationManager; } public JWTToken login(LoginReq loginReq, HttpServletRequest request) { UserEntity user=null; LoginAttemptEntity loginAttemptEntity = prepareLoginAttemptEntity(loginReq, request); try { log.info("Attempting login for email: {}", loginReq.getEmail()); String emailWithHubId = loginReq.getEmail()+":"+loginReq.getHubUuid(); UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken( emailWithHubId, loginReq.getPassword()); Authentication authentication = this.authenticationManager.authenticate(authenticationToken); SecurityContextHolder.getContext().setAuthentication(authentication); log.info("Authentication successful for email: {}", loginReq.getEmail()); user = userRepository.findByEmailIgnoreCaseAndHubUniqueUuid(loginReq.getEmail(), loginReq.getHubUuid()) .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG))); loginAttemptEntity.setUserId(user.getId()); if (Boolean.FALSE.equals(UserStatusEnum.ACTIVE.getValue().equals(user.getStatus()))) { throw new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG)); } loginAttemptEntity.setUserId(user.getId()); createSuccessLoginAttempt(loginAttemptEntity); } catch (Exception e) { log.info("Authentication failed for email: {}", loginReq.getEmail()); loginAttemptEntity.setUserId(user.getId()); createFailedLoginAttempt(loginAttemptEntity, e.getMessage()); throw e; } return getJWTTokenBean(user, loginReq.getRememberMe(), loginAttemptEntity.getId()); } public LoginAttemptEntity prepareLoginAttemptEntity(LoginReq loginUserReq, HttpServletRequest request) { String ipAddress = Utils.getClientIpAddress(request); String userAgent = request.getHeader("user-agent"); LoginAttemptEntity loginAttemptEntity = new LoginAttemptEntity(); loginAttemptEntity.setType(LoginAttemptTypeEnum.LOGIN.getValue()); loginAttemptEntity.setUsername(loginUserReq.getEmail()); loginAttemptEntity.setIpAddress(ipAddress); loginAttemptEntity.setUserAgent(userAgent); return loginAttemptEntity; } public LoginAttemptEntity createSuccessLoginAttempt(LoginAttemptEntity loginAttemptEntity) { loginAttemptEntity.setResult(LoginAttemptResultEnum.SUCCESS.getValue()); return loginAttemptDao.createLoginAttempt(loginAttemptEntity); } public void createFailedLoginAttempt(LoginAttemptEntity loginAttemptEntity, String errorMsg) { loginAttemptEntity.setResult(LoginAttemptResultEnum.FAILED.getValue()); loginAttemptEntity.setErrorMsg(errorMsg); loginAttemptDao.createLoginAttempt(loginAttemptEntity); } public JWTToken getJWTTokenBean(UserEntity user, Boolean rememberMe, Long loginAttemptId) { UserEntity oldUserEntity = Utils.getClonedEntityForData(user); user.setLastLogin(DateTimeUtil.DateServerToUTC(LocalDateTime.now())); user = userRepository.save(user); String token = tokenProvider.createToken(rememberMe, user, loginAttemptId); log.info("JWT token generated for email: {}", user.getEmail()); RoleResponseBean roleResponseBean = roleDao.convertRoleEntityToRoleResponse(user.getRoleEntity()); LoginResponse loginResponse = getLoginResponse(user, roleResponseBean); JWTToken jwtToken = new JWTToken(token, loginResponse); /** This code is responsible for adding a version history log for the "Create user Or Update user" operation. **/ loggingUtil.addVersionHistoryWithoutToken(VersionHistoryRequest.builder().request(request).oldData(oldUserEntity).newData(user).actionType(VersionActionTypeEnum.UPDATE).build()); log.info("Login successful for email: {}", user.getEmail()); return jwtToken; } private LoginResponse getLoginResponse(UserEntity user, RoleResponseBean roleResponseBean) { LoginResponse loginResponse = new LoginResponse(); loginResponse.setEmail(user.getEmail()); loginResponse.setId(user.getId()); List companyResponseBeans = companyDao.getCompanyByUserId(user.getId()); loginResponse.setCompanies(companyResponseBeans); loginResponse.setRole(roleResponseBean); loginResponse.setStatus(user.getStatus()); loginResponse.setLastLogin(user.getLastLogin()); loginResponse.setCreatedDate(user.getCreatedDate()); loginResponse.setUpdatedDate(user.getUpdatedDate()); if (user.getBeneficiary() == null) { loginResponse.setFirstName(user.getFirstName()); loginResponse.setLastName(user.getLastName()); loginResponse.setPhoneNumber(user.getPhoneNumber()); loginResponse.setAddress(user.getAddress()); loginResponse.setOrganization(user.getOrganization()); loginResponse.setCountry(user.getCountry()); loginResponse.setCity(user.getCity()); loginResponse.setDateOfBirth(user.getDateOfBirth()); }else { loginResponse.setFirstName(user.getBeneficiary().getFirstName()); loginResponse.setLastName(user.getBeneficiary().getLastName()); loginResponse.setPhoneNumber(user.getBeneficiary().getPhoneNumber()); loginResponse.setAddress(user.getBeneficiary().getAddress()); loginResponse.setOrganization(user.getBeneficiary().getOrganization()); loginResponse.setCountry(user.getBeneficiary().getCountry()); loginResponse.setCity(user.getBeneficiary().getCity()); loginResponse.setCodiceFiscale(user.getBeneficiary().getCodiceFiscale()); loginResponse.setDateOfBirth(user.getBeneficiary().getDateOfBirth()); loginResponse.setPrivacy(user.getBeneficiary().getPrivacy()); loginResponse.setMarketing(user.getBeneficiary().getMarketing()); loginResponse.setOffers(user.getBeneficiary().getOffers()); loginResponse.setTerms(user.getBeneficiary().getTerms()); loginResponse.setThirdParty(user.getBeneficiary().getThirdParty()); loginResponse.setEmailPec(user.getBeneficiary().getEmailPec()); } return loginResponse; } public void logout(HttpServletRequest request, HttpServletResponse response) { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth != null) { new SecurityContextLogoutHandler().logout(request, response, auth); } SecurityContextHolder.getContext().setAuthentication(null); SecurityContextHolder.clearContext(); } public JWTToken validateExistingUserToken(HttpServletRequest request,String token) { SamlResponseEntity samlResponseLogEntity = samlResponseLogRepository.findByToken(token); if (samlResponseLogEntity == null) { log.info("Invalid spid login token : {}", token); throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.INVALID_TOKEN_MSG)); } LoginReq loginReq=new LoginReq(); Long userId=null; LoginAttemptEntity loginAttemptEntity =new LoginAttemptEntity(); try { HubEntity hub = hubService.getHubByUuid(samlResponseLogEntity.getHubUuid()); Map> userAttributes = Utils .convertStringIntoMap(samlResponseLogEntity.getAuthenticationObject()); String cf = userAttributes.get("CodiceFiscale").get(0).toString(); UserEntity userEntity = userRepository.findByBeneficiaryCodiceFiscaleAndHubId(cf, hub.getId()) .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG))); userId=userEntity.getId(); //samlResponseLogRepository.delete(samlResponseLogEntity); loginReq.setEmail(userEntity.getEmail()); loginAttemptEntity = prepareLoginAttemptEntity(loginReq, request); loginAttemptEntity.setUserId(userEntity.getId()); LoginAttemptEntity loginAttempt = createSuccessLoginAttempt(loginAttemptEntity); return getJWTTokenBean(userEntity, Boolean.TRUE, loginAttempt.getId()); } catch (Exception e) { log.info("Authentication login failed for email: {}",e.getMessage()); loginAttemptEntity.setUserId(userId); createFailedLoginAttempt(loginAttemptEntity, e.getMessage()); throw e; } } public UserSamlResponse validateNewUserToken(String token) { SamlResponseEntity samlResponseLogEntity = samlResponseLogRepository.findByToken(token); if (samlResponseLogEntity == null) { log.info("Invalid spid login token : {}", token); throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.INVALID_TOKEN_MSG)); } HubEntity hub = hubService.getHubByUuid(samlResponseLogEntity.getHubUuid()); Map> userAttributes = Utils .convertStringIntoMap(samlResponseLogEntity.getAuthenticationObject()); String cf = userAttributes.get("CodiceFiscale").get(0).toString(); if (userRepository.existsByBeneficiaryCodiceFiscaleAndHubId(cf, hub.getId())) { throw new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.USER_ALREADY_EXIST_MSG)); } UserSamlResponse userSamlResponse = new UserSamlResponse(); userSamlResponse.setCodiceFiscale(cf); if (userAttributes.containsKey("nome") && userAttributes.get("nome") != null && !userAttributes.get("nome").isEmpty()) { userSamlResponse.setFirstName(userAttributes.get("nome").get(0).toString()); } if (userAttributes.containsKey("cognome") && userAttributes.get("cognome") != null && !userAttributes.get("cognome").isEmpty()) { userSamlResponse.setLastName(userAttributes.get("cognome").get(0).toString()); } if (userAttributes.containsKey("dataNascita") && userAttributes.get("dataNascita") != null && !userAttributes.get("dataNascita").isEmpty()) { String dateString =userAttributes.get("dataNascita").get(0).toString(); LocalDate dateOfBirth = LocalDate.parse(dateString); LocalDateTime dateOfBirthWithTime = dateOfBirth.atStartOfDay(); userSamlResponse.setDateOfBirth(dateOfBirthWithTime); } userSamlResponse.setCodiceFiscale(cf); return userSamlResponse; } }