gestion creation user #232

Merged
judaur2005 merged 1 commits from features/fiche_refonte into develop 2026-07-02 15:13:50 +00:00
14 changed files with 274 additions and 81 deletions
Showing only changes of commit 81e443b0b6 - Show all commits

View File

@@ -23,7 +23,7 @@ import org.springframework.web.client.HttpClientErrorException;
@RestController
@RequestMapping(value = "api/profil", produces = MediaType.APPLICATION_JSON_VALUE)
@RequestMapping(value = "api/profile", produces = MediaType.APPLICATION_JSON_VALUE)
@SecurityRequirement(name = "bearer")
@Tag(name = "Profile")
@CrossOrigin(origins = "*")

View File

@@ -8,6 +8,7 @@ import io.gmss.fiscad.exceptions.*;
import io.gmss.fiscad.interfaces.user.UserService;
import io.gmss.fiscad.paylaods.ApiResponse;
import io.gmss.fiscad.paylaods.Login;
import io.gmss.fiscad.paylaods.request.ResetPasswordByMailRequest;
import io.gmss.fiscad.paylaods.request.crudweb.UserPaylaodWeb;
import io.gmss.fiscad.security.CurrentUser;
import io.gmss.fiscad.security.UserPrincipal;
@@ -119,6 +120,39 @@ public class UserController {
}
}
@PostMapping("/reset-password-by-mail")
public ResponseEntity<?> resetUserPasswordByMail(@RequestBody @Valid @Validated ResetPasswordByMailRequest resetPasswordByMailRequest) {
try {
if(userService.validationTokenResetPassword(resetPasswordByMailRequest.getToken())){
UserPaylaodWeb userPaylaodWeb = userService.resetPasswordByMail(resetPasswordByMailRequest.getToken(), resetPasswordByMailRequest.getNewPassword());
return new ResponseEntity<>(
new ApiResponse<>(true, userPaylaodWeb.getLogin(), "Mot de passe réinitialiser avec succès."),
HttpStatus.OK
);
}else {
return new ResponseEntity<>(
new ApiResponse<>(false, "Token invalide ou expiré."),
HttpStatus.OK
);
}
} catch (HttpClientErrorException.MethodNotAllowed e) {
logger.error(e.getLocalizedMessage());
return new ResponseEntity<>(new ApiResponse(false, null, "Method POST/GET is required."), HttpStatus.OK);
} catch (NotFoundException | BadRequestException | MyFileNotFoundException | ResourceNotFoundException |
FileStorageException e) {
logger.error(e.getLocalizedMessage());
return new ResponseEntity<>(new ApiResponse(false, null, e.getMessage()), HttpStatus.OK);
} catch (NullPointerException e) {
logger.error(e.getLocalizedMessage());
return new ResponseEntity<>(new ApiResponse(false, null, "Null value has been detected {" + e.getMessage() + "}."), HttpStatus.OK);
} catch (Exception e) {
logger.error(e.getLocalizedMessage());
return new ResponseEntity<>(new ApiResponse(false, null, "An error has been occur and the content is {" + e.getMessage() + "}."), HttpStatus.OK);
}
}
@PostMapping("/validate-user-account/{userName}")
@PreAuthorize("hasAuthority('UPDATE_USER')")
public ResponseEntity<?> validateUserAccount(@PathVariable String userName) {

View File

@@ -1,6 +1,9 @@
package io.gmss.fiscad.entities.user;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import io.gmss.fiscad.deserializer.LocalDateDeserializer;
import io.gmss.fiscad.entities.BaseEntity;
import io.gmss.fiscad.entities.decoupage.Secteur;
import io.gmss.fiscad.entities.infocad.metier.Enquete;
@@ -16,6 +19,8 @@ import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -54,6 +59,11 @@ public class User extends BaseEntity implements Serializable {
@Column(columnDefinition = "boolean default false")
private boolean resetPassword;
private String token;
private LocalDateTime tokenDate;
@OneToMany(mappedBy = "user")
private Set<AvoirFonction> avoirFonctions= new HashSet<>();

View File

@@ -19,6 +19,7 @@ import io.gmss.fiscad.service.EntityFromPayLoadService;
import io.gmss.fiscad.service.MailService;
import io.gmss.fiscad.service.StringService;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.authentication.AuthenticationManager;
@@ -28,10 +29,12 @@ import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
@AllArgsConstructor
//@AllArgsConstructor
@Service
public class UserServiceImpl implements UserService {
@@ -45,7 +48,25 @@ public class UserServiceImpl implements UserService {
private final StringService stringService ;
private final MailService mailService ;
@Value("${dgi.sigibe-foncier.reset-pw.url}")
private String reseturl ;
@Value("${dgi.sigibe-foncier.reset-pw.token-delay}")
private static long tokenDelay ;
public UserServiceImpl(UserRepository userRepository, PasswordEncoder passwordEncoder, RoleService roleService, AuthenticationManager authenticationManager, TokenAuthentificationProvider tokenAuthentificationProvider, StructureService structureService, EntityFromPayLoadService entityFromPayLoadService, StringService stringService, MailService mailService) {
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
this.roleService = roleService;
this.authenticationManager = authenticationManager;
this.tokenAuthentificationProvider = tokenAuthentificationProvider;
this.structureService = structureService;
this.entityFromPayLoadService = entityFromPayLoadService;
this.stringService = stringService;
this.mailService = mailService;
}
@Override
@@ -61,8 +82,19 @@ public class UserServiceImpl implements UserService {
User user = entityFromPayLoadService.getUserFromPayLoadWeb(userPaylaodWeb);
user.setPassword(passwordEncoder.encode(userPaylaodWeb.getPassword()));
user.setTokenDate(LocalDateTime.now());
String token= stringService.getUniqueString();
user.setToken(token);
userRepository.save(user);
mailService.sendValidationMail(user.getEmail(),
user.getPrenom() + " " + user.getNom(),
user.getUsername(),
reseturl + token);
return userRepository.findUserToDtoById(userPaylaodWeb.getId()).orElse(null);
}
@@ -208,10 +240,7 @@ public class UserServiceImpl implements UserService {
@Override
public User disactivateUser(Long id) {
User user = getUserById(id);
user.setActive(false);
return userRepository.save(user);
}
@@ -229,6 +258,19 @@ public class UserServiceImpl implements UserService {
return optionalUserPaylaodWeb.orElse(null);
}
@Override
public UserPaylaodWeb resetPasswordByMail(String token, String password) {
User user = userRepository.findByToken(token).orElseThrow(() -> new NotFoundException(
String.format("Token %s invalide ou inexistant.", token)
));
user.setPassword(passwordEncoder.encode(password));
user.setResetPassword(false);
user= userRepository.save(user);
// mailService.sendAccountReinitMail(user,password);
Optional<UserPaylaodWeb> optionalUserPaylaodWeb = userRepository.findUserToDtoById(user.getId());
return optionalUserPaylaodWeb.orElse(null);
}
@Override
public User validateUserAccount(String username) {
@@ -301,4 +343,44 @@ public class UserServiceImpl implements UserService {
return userRepository.findAllUserByStructureToDtoPageable(structureId,pageable);
}
@Override
public Boolean validationTokenResetPassword(String token) {
Optional<User> optionalUser=userRepository.findByToken(token);
if(optionalUser.isEmpty()){
return false;
}
LocalDateTime tokenDate= optionalUser.get().getTokenDate();
if(isTokenExpired(tokenDate)){
return false ;
}
return true;
}
/**
* Calcule la date d'expiration du token en ajoutant 24h à sa date de génération.
*/
public static LocalDateTime calculerDateExpiration(LocalDateTime dateToken) {
if (dateToken == null) {
throw new IllegalArgumentException("La date du token ne peut pas être null");
}
return dateToken.plusHours(tokenDelay);
}
/**
* Vérifie si le token est expiré.
* Le token expire dès que la date actuelle est égale ou supérieure
* à dateToken + 24h.
*/
public static boolean isTokenExpired(LocalDateTime dateToken) {
if (dateToken == null) {
return true;
}
LocalDateTime dateExpiration = calculerDateExpiration(dateToken);
return !LocalDateTime.now().isBefore(dateExpiration);
}
}

View File

@@ -46,6 +46,7 @@ public interface UserService {
User activateUser(Long id);
User disactivateUser(Long id);
UserPaylaodWeb resetPassword(String username);
UserPaylaodWeb resetPasswordByMail(String token, String password);
User validateUserAccount(String username);
@@ -63,4 +64,6 @@ public interface UserService {
List<UserPaylaodWeb> getListUserByStructureToDto(Long structureId);
Page<UserPaylaodWeb> getListUserByStructureToDto(Long structureId, Pageable pageable);
Boolean validationTokenResetPassword(String token);
}

View File

@@ -0,0 +1,12 @@
package io.gmss.fiscad.paylaods.request;
import io.gmss.fiscad.enums.UserRole;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class ResetPasswordByMailRequest {
private String token;
private String newPassword;
}

View File

@@ -0,0 +1,19 @@
package io.gmss.fiscad.paylaods.request.record;
import java.util.List;
public record EMailBodyRequest(
List<String> to,
List<String> cc,
List<String> bcc,
String from,
String fromName,
String replyTo,
String subject,
String applicantName,
String eServicesNumber,
String passwordCreationLink,
List<EmailAttachmentInput> attachments
) {
}

View File

@@ -0,0 +1,11 @@
package io.gmss.fiscad.paylaods.request.record;
import java.util.List;
public record EmailAttachmentInput(
String filename,
String contentType,
String contentBase64
) {
}

View File

@@ -0,0 +1,17 @@
package io.gmss.fiscad.paylaods.response.record;
import java.time.OffsetDateTime;
import java.util.List;
public record MailSendResponse(
String messageId,
String status,
boolean dryRun,
String subject,
List<String> to,
List<String> cc,
List<String> bcc,
int attachmentCount,
OffsetDateTime timestamp
) {
}

View File

@@ -18,6 +18,7 @@ import java.util.Set;
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String username);
Optional<User> findByToken(String token);
Optional<User> findByEmail(String email);
boolean existsByUsername(String username);

View File

@@ -58,28 +58,6 @@ public class CallAPIService {
}
// public RestTemplate executeRestemplate(String accessToken) {
//
// RestTemplate restTemplate = new RestTemplate();
//
// restTemplate.getInterceptors().add((request, body, execution) -> {
// System.out.println("LE TOKEN dans execute");
// System.out.println(accessToken);
// if (accessToken != null && !accessToken.isBlank()) {
// request.getHeaders().setBearerAuth(accessToken);
// }
//
// request.getHeaders().setAccept(List.of(MediaType.APPLICATION_JSON));
// request.getHeaders().setContentType(MediaType.APPLICATION_JSON);
//
// return execution.execute(request, body);
// });
//
// return restTemplate;
// }
public IfuEnLigneLoginResponse callGetIfuEnLigneToken() {
try {
@@ -121,53 +99,6 @@ public class CallAPIService {
}
// public SygmApiResponse callPostSygmefCentre(String url, String tokenName, String accessToken,
//
// SygmApiResponse sygmApiResponse = new SygmApiResponse() ;
// try {
// HttpEntity<SygmCentre> request = new HttpEntity<>(centre);
// RestTemplate restTemplate = executeRestemplate(tokenName, accessToken);
// ResponseEntity<SygmApiResponse> response = restTemplate.postForEntity(url, request, SygmApiResponse.class);
//
// if(response.getStatusCodeValue()==200){
// return response.getBody() ;
// }else{
// sygmApiResponse.setStatut(false);
//
// sygmApiResponse.setMessage("HttpStatus "+response.getStatusCodeValue()+" --- "
// +response.getBody().toString());
// return sygmApiResponse;
// }
// }catch (Exception e ){
// System.out.println("SYGMEF : "+e.getMessage()) ;
// e.printStackTrace();
// throw new Exception(e.getMessage()) ;
// }
// }
// public void callApiRechercheContribIfuEnLigne(IfuEnLigneRechercheBody ifuEnLigneRechercheBody) {
// try {
// String url = ifuEnLigneBaseUrl+"/api/contribuable/fiscad";
// //ApiResponse
// RestTemplate restTemplate = executeRestemplate("Authorization",ifuEnLigneToken);
// ResponseEntity<List<IfuEnLigneContribuableResponse>> response = restTemplate.getForEntity(url,ifuEnLigneRechercheBody, IfuEnLigneContribuableResponse.class);
// if(response.getStatusCode().value()==200){
// System.out.println(response.getBody());
// }
// } catch (
// MethodNotAllowedException ex) {
// logger.error(ex.toString());
// //return new ResponseEntity(null, HttpStatus.METHOD_NOT_ALLOWED);
// } catch (Exception e) {
// logger.error(e.toString());
// // return new ResponseEntity(null, HttpStatus.INTERNAL_SERVER_ERROR);
// }
// }
public List<IfuEnLigneContribuableResponse> callApiRechercheContribIfuEnLigne(
IfuEnLigneRechercheBody requestBody) {
@@ -216,8 +147,6 @@ public class CallAPIService {
// @PostConstruct
private synchronized void ensureToken() {
@@ -249,4 +178,9 @@ public class CallAPIService {
}

View File

@@ -4,14 +4,19 @@ package io.gmss.fiscad.service;
import io.gmss.fiscad.entities.user.User;
import io.gmss.fiscad.enums.ParametersType;
import io.gmss.fiscad.interfaces.ParametersRepository;
import io.gmss.fiscad.paylaods.request.record.EMailBodyRequest;
import io.gmss.fiscad.paylaods.response.record.MailSendResponse;
import io.gmss.fiscad.utils.Mail;
import io.gmss.fiscad.utils.MailPostmark;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.io.IOException;
import java.util.List;
@Service
public class MailService {
@@ -28,8 +33,16 @@ public class MailService {
@Autowired
ParametersRepository parametersRepository;
// @Value("${}")
// String defaultPassWord;
@Value("${dgi.mail.validaton-compte.url}")
String urlValidationMail;
private final RestTemplate restTemplate;
public MailService(
RestTemplate restTemplate
) {
this.restTemplate = restTemplate;
}
@Async
public void sendMail(String to, String subject, String messageContent, String helloName) {
@@ -421,6 +434,10 @@ public class MailService {
}
public void sendMailByUrl(User user, String passWord) {
}
@Async
public Boolean sendPostmarkMail(String to, String subject, String messageContent, String helloName, String fileName) throws IOException {
String from ;
@@ -432,4 +449,44 @@ public class MailService {
return false ;
}
public MailSendResponse sendValidationMail(
String recipientEmail,
String applicantName,
String eServicesNumber,
String passwordCreationLink
) {
EMailBodyRequest request = new EMailBodyRequest(
List.of(recipientEmail),
List.of(),
List.of(),
null,
null,
null,
"[SIGIBE] Validation de votre demande d'immatriculation fiscale",
applicantName,
eServicesNumber,
passwordCreationLink,
List.of()
);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(List.of(MediaType.APPLICATION_JSON));
HttpEntity<EMailBodyRequest> entity = new HttpEntity<>(request, headers);
ResponseEntity<MailSendResponse> response = restTemplate.exchange(
urlValidationMail,
HttpMethod.POST,
entity,
MailSendResponse.class
);
return response.getBody();
}
}

View File

@@ -2,10 +2,16 @@ server.port=8282
io.gmss.fiscad.profile=test
# LOCAL ENV TEST
spring.datasource.url=jdbc:postgresql://localhost:5432/fiscad_dgi
spring.datasource.username=infocad_user
#spring.datasource.url=jdbc:postgresql://localhost:5432/fiscad_dgi
#spring.datasource.username=infocad_user
#spring.datasource.password=W5fwD({9*q53
spring.datasource.url=jdbc:postgresql://193.181.208.4:5432/fiscad_db
spring.datasource.username=fiscad_user
spring.datasource.password=W5fwD({9*q53
app.default-user.username=fiscad_admin
app.default-user.password=1234567890
@@ -13,3 +19,6 @@ app.default-user.password=1234567890
ifu-en-ligne.api.base-url=https://ifubackend.impots.bj/
ifu-en-ligne.api.username=cakpona
ifu-en-ligne.api.password=try
dgi.mail.validaton-compte.url=http://novatic.vps.webdock.cloud:3308/api/emails/sigibe-validation
dgi.sigibe-foncier.reset-pw.url=https://frontend.sigibe-foncier-test.novatic.org/reset?token=

View File

@@ -42,6 +42,8 @@ file.jasper-reports=./jasperReport
logging.file.name=/app/logs/fiscad.log
app.upload.root=${file.upload_dir}
app.upload.zips.received=${app.upload.root}/zips/received
app.upload.zips.done=${app.upload.root}/zips/done
@@ -78,4 +80,6 @@ logging.level.org.apache.catalina.connector.ClientAbortException=ERROR
#spring.jpa.properties.hibernate.format_sql=true
##logging.level.org.hibernate.SQL=DEBUG
#logging.level.org.hibernate.type.descriptor.sql=TRACE
#logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
#logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
dgi.sigibe-foncier.reset-pw.token-delay=24