mise gestion
This commit is contained in:
@@ -41,6 +41,7 @@ dependencies {
|
||||
implementation('io.jsonwebtoken:jjwt-jackson:0.11.5')
|
||||
|
||||
implementation('org.modelmapper:modelmapper:3.2.0')
|
||||
implementation 'org.springframework.boot:spring-boot-starter-security'
|
||||
}
|
||||
|
||||
tasks.named('test') {
|
||||
|
||||
@@ -7,6 +7,8 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
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;
|
||||
|
||||
@@ -29,5 +31,10 @@ public class SecurityConfig {
|
||||
.addFilterBefore(apiKeyFilter, UsernamePasswordAuthenticationFilter.class)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.pmu.betengine.controller;
|
||||
|
||||
import com.pmu.betengine.model.AuthRequest;
|
||||
import com.pmu.betengine.model.AuthResponse;
|
||||
import com.pmu.betengine.model.User;
|
||||
import com.pmu.betengine.service.AuthService;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@@ -18,7 +19,9 @@ public class AuthController {
|
||||
}
|
||||
|
||||
@PostMapping("/login")
|
||||
public ResponseEntity<AuthResponse> login(@RequestBody AuthRequest request) {
|
||||
return ResponseEntity.ok(authService.login(request));
|
||||
public ResponseEntity<User> login(@RequestBody AuthRequest request) {
|
||||
User loggedUser = authService.login(request);
|
||||
return ResponseEntity.ok(loggedUser);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.pmu.betengine.controller;
|
||||
|
||||
import com.pmu.betengine.model.Mise;
|
||||
import com.pmu.betengine.service.MiseService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/mises")
|
||||
@CrossOrigin(origins = "*")
|
||||
@Tag(name = "Gestion des Mises", description = "Endpoints relatifs aux Mises")
|
||||
public class MiseController {
|
||||
|
||||
private final MiseService miseService;
|
||||
|
||||
public MiseController(MiseService miseService) {
|
||||
this.miseService = miseService;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@Operation(summary = "Lister toutes les Mises")
|
||||
public ResponseEntity<List<Mise>> getAllMises() {
|
||||
return ResponseEntity.ok(miseService.getAll());
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@Operation(summary = "Obtenir une Mise par ID")
|
||||
public ResponseEntity<Mise> getMiseById(@PathVariable Long id) {
|
||||
return ResponseEntity.ok(miseService.getById(id));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@Operation(summary = "Créer une Mise")
|
||||
public ResponseEntity<Mise> createMise(@RequestBody Mise mise) {
|
||||
return new ResponseEntity<>(miseService.create(mise), HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
@Operation(summary = "Modifier une Mise")
|
||||
public ResponseEntity<Mise> updateMise(@PathVariable Long id, @RequestBody Mise mise) {
|
||||
return ResponseEntity.ok(miseService.update(id, mise));
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
@Operation(summary = "Supprimer une Mise")
|
||||
public ResponseEntity<Void> deleteMise(@PathVariable Long id) {
|
||||
miseService.delete(id);
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,9 @@ import com.pmu.betengine.service.ResultatService;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/resultat")
|
||||
@@ -57,10 +59,16 @@ public class ResultatController {
|
||||
}
|
||||
|
||||
// GET BY COURSE
|
||||
@GetMapping("/course/{courseId}")
|
||||
public ResponseEntity<Resultat> getByCourse(@PathVariable Long courseId) {
|
||||
@GetMapping("/course/{courseId}")
|
||||
public ResponseEntity<?> getByCourse(@PathVariable Long courseId) {
|
||||
Resultat r = resultatService.getByCourseId(courseId);
|
||||
return r != null ? ResponseEntity.ok(r) : ResponseEntity.notFound().build();
|
||||
if (r != null) {
|
||||
return ResponseEntity.ok(r);
|
||||
} else {
|
||||
Map<String, String> response = new HashMap<>();
|
||||
response.put("message", "Aucun résultat disponible pour cette course");
|
||||
return ResponseEntity.ok(response);
|
||||
}
|
||||
}
|
||||
|
||||
// UPDATE
|
||||
|
||||
@@ -25,59 +25,38 @@ public class Course {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private String type;
|
||||
|
||||
private Integer numero;
|
||||
|
||||
private String nom;
|
||||
|
||||
@Column(name = "date_depart_course")
|
||||
private LocalDateTime dateDepartCourse;
|
||||
|
||||
@Column(name = "date_debut_paris")
|
||||
private LocalDateTime dateDebutParis;
|
||||
|
||||
@Column(name = "date_fin_paris")
|
||||
private LocalDateTime dateFinParis;
|
||||
|
||||
@Column(name = "reunion_id")
|
||||
private Long reunionId;
|
||||
|
||||
@Column(name = "reunion_course")
|
||||
private Integer reunionCourse;
|
||||
|
||||
private String particularite;
|
||||
|
||||
private Integer partants;
|
||||
|
||||
private Integer distance;
|
||||
|
||||
private String condition;
|
||||
|
||||
private boolean estTerminee;
|
||||
private boolean estAnnulee;
|
||||
private boolean aDeadHeat;
|
||||
|
||||
private String statut;
|
||||
|
||||
private int nombreChevauxInscrits;
|
||||
|
||||
@Column(name = "resultat_statut")
|
||||
private String resultatStatut;
|
||||
|
||||
@Column(name = "created_by")
|
||||
private String createdBy;
|
||||
|
||||
@Column(name = "validated_by")
|
||||
private String validatedBy;
|
||||
|
||||
@Column(name = "created_at")
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@Column(name = "updated_at")
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
@Column(name = "nom_partants")
|
||||
private List<String> nonPartants;
|
||||
|
||||
|
||||
25
src/main/java/com/pmu/betengine/model/Mise.java
Normal file
25
src/main/java/com/pmu/betengine/model/Mise.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package com.pmu.betengine.model;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Entity
|
||||
@Table(name = "mises")
|
||||
public class Mise {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
String typePari;
|
||||
Double montantMise;
|
||||
}
|
||||
@@ -28,6 +28,7 @@ public class User {
|
||||
private String nom;
|
||||
private String prenom;
|
||||
private String identifiant;
|
||||
private String password;
|
||||
private String matriculeAgent;
|
||||
|
||||
@Column(name = "role_id")
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.pmu.betengine.model.statut;
|
||||
|
||||
public enum StatutUser {
|
||||
ACTIF,
|
||||
INACTIF,
|
||||
SUSPENDU
|
||||
}
|
||||
@@ -28,6 +28,4 @@ public enum TypeFormule {
|
||||
CHAMP_TOTAL_1,
|
||||
CHAMP_PARTIEL_1,
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -10,9 +10,7 @@ public enum TypePaiement {
|
||||
QUARTE_PLUS_ORDRE_INEXACT,
|
||||
BONUS_3,
|
||||
BONUS_3_BIS,
|
||||
|
||||
MULTI_4,
|
||||
|
||||
MULTI_5,
|
||||
MULTI_6,
|
||||
MULTI_7,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
package com.pmu.betengine.model.type;
|
||||
|
||||
public enum TypePari {
|
||||
SIMPLE,
|
||||
JUMELE_GAGNANT,
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.pmu.betengine.repository;
|
||||
|
||||
import com.pmu.betengine.model.Mise;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface MiseRepository extends JpaRepository<Mise, Long> {
|
||||
}
|
||||
@@ -2,7 +2,19 @@ package com.pmu.betengine.repository;
|
||||
|
||||
import com.pmu.betengine.model.User;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface UserRepository extends JpaRepository<User, Long> {
|
||||
|
||||
// Récupérer un utilisateur par identifiant (connexion)
|
||||
Optional<User> findByIdentifiant(String identifiant);
|
||||
|
||||
// Vérifier si un identifiant existe déjà (création)
|
||||
boolean existsByIdentifiant(String identifiant);
|
||||
|
||||
// Vérifier si un matricule existe déjà (création)
|
||||
boolean existsByMatriculeAgent(String matriculeAgent);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,9 @@ import com.pmu.betengine.model.AuthRequest;
|
||||
import com.pmu.betengine.model.AuthResponse;
|
||||
import com.pmu.betengine.model.User;
|
||||
import com.pmu.betengine.repository.UserRepository;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
@@ -12,24 +15,26 @@ import java.time.LocalDateTime;
|
||||
public class AuthService {
|
||||
|
||||
private final UserRepository userRepository;
|
||||
@Autowired
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
public AuthService(UserRepository userRepository) {
|
||||
this.userRepository = userRepository;
|
||||
}
|
||||
|
||||
public AuthResponse login(AuthRequest request) {
|
||||
User user = userRepository.findAll().stream()
|
||||
.filter(u -> u.getIdentifiant().equals(request.getIdentifiant()))
|
||||
.findFirst()
|
||||
|
||||
|
||||
|
||||
public User login(AuthRequest request) {
|
||||
User user = userRepository.findByIdentifiant(request.getIdentifiant())
|
||||
.orElseThrow(() -> new RuntimeException("User not found"));
|
||||
|
||||
if (request.getPassword().equals("password123")) {
|
||||
user.setDerniereConnexion(LocalDateTime.now());
|
||||
userRepository.save(user);
|
||||
|
||||
return new AuthResponse("Login successful", user.getId(), user.getNom(), user.getPrenom());
|
||||
} else {
|
||||
|
||||
if (!passwordEncoder.matches(request.getPassword(), user.getPassword())) {
|
||||
throw new RuntimeException("Invalid credentials");
|
||||
}
|
||||
|
||||
user.setDerniereConnexion(LocalDateTime.now());
|
||||
return userRepository.save(user);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
41
src/main/java/com/pmu/betengine/service/MiseService.java
Normal file
41
src/main/java/com/pmu/betengine/service/MiseService.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package com.pmu.betengine.service;
|
||||
|
||||
import com.pmu.betengine.model.Mise;
|
||||
import com.pmu.betengine.repository.MiseRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class MiseService {
|
||||
|
||||
private final MiseRepository repository;
|
||||
|
||||
public MiseService(MiseRepository repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
public Mise create(Mise mise) {
|
||||
return repository.save(mise);
|
||||
}
|
||||
|
||||
public Mise getById(Long id) {
|
||||
return repository.findById(id)
|
||||
.orElseThrow(() -> new RuntimeException("Mise not found"));
|
||||
}
|
||||
|
||||
public List<Mise> getAll() {
|
||||
return repository.findAll();
|
||||
}
|
||||
|
||||
public Mise update(Long id, Mise mise) {
|
||||
Mise existing = getById(id);
|
||||
existing.setTypePari(mise.getTypePari());
|
||||
existing.setMontantMise(mise.getMontantMise());
|
||||
return repository.save(existing);
|
||||
}
|
||||
|
||||
public void delete(Long id) {
|
||||
repository.deleteById(id);
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,16 @@ import com.pmu.betengine.model.Course;
|
||||
import com.pmu.betengine.model.Resultat;
|
||||
import com.pmu.betengine.repository.ResultatRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Map;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@@ -35,6 +43,7 @@ public class ResultatService {
|
||||
return resultatRepository.findByCourseId(courseId).orElse(null);
|
||||
}
|
||||
|
||||
|
||||
// DELETE BY ID
|
||||
public void delete(Long id) {
|
||||
resultatRepository.deleteById(id);
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
package com.pmu.betengine.service;
|
||||
|
||||
import com.pmu.betengine.model.User;
|
||||
import com.pmu.betengine.model.statut.StatutUser;
|
||||
import com.pmu.betengine.repository.UserRepository;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
@@ -12,15 +17,47 @@ public class UserService {
|
||||
|
||||
private final UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
public UserService(UserRepository userRepository) {
|
||||
this.userRepository = userRepository;
|
||||
}
|
||||
|
||||
// CREATE
|
||||
public User create(User user) {
|
||||
// 1. Vérification des champs obligatoires
|
||||
if (!StringUtils.hasText(user.getNom())) {throw new RuntimeException("Le nom est obligatoire");}
|
||||
if (!StringUtils.hasText(user.getPrenom())) {throw new RuntimeException("Le prénom est obligatoire");}
|
||||
if (!StringUtils.hasText(user.getIdentifiant())) {throw new RuntimeException("L'identifiant est obligatoire");}
|
||||
if (!StringUtils.hasText(user.getPassword())) {throw new RuntimeException("Le mot de passe est obligatoire");}
|
||||
if (user.getRoleId() == null) {throw new RuntimeException("L'ID du rôle est obligatoire");}
|
||||
// 2. Vérification de l'unicité
|
||||
if (userRepository.existsByIdentifiant(user.getIdentifiant())) {throw new RuntimeException("Cet identifiant existe déjà");}
|
||||
if (user.getMatriculeAgent() != null &&
|
||||
userRepository.existsByMatriculeAgent(user.getMatriculeAgent())) {throw new RuntimeException("Ce matricule agent existe déjà");}
|
||||
// 3. Validation du mot de passe
|
||||
if (!user.getPassword().matches("^(?=.*[0-9])(?=.*[a-zA-Z]).{8,}$")) {throw new RuntimeException("Le mot de passe doit contenir au moins 8 caractères, incluant lettres et chiffres");}
|
||||
// 4. Définition des valeurs par défaut et encodage du mot de passe
|
||||
user.setId(null);
|
||||
user.setPassword(passwordEncoder.encode(user.getPassword()));
|
||||
user.setStatut(StatutUser.ACTIF.name());
|
||||
user.setCreatedAt(LocalDateTime.now());
|
||||
user.setUpdatedAt(LocalDateTime.now());
|
||||
user.setDerniereConnexion(null);
|
||||
// 5. Vérification des champs numériques
|
||||
if (user.getNombreIpAutorise() == null || user.getNombreIpAutorise() < 0) {
|
||||
user.setNombreIpAutorise(0);
|
||||
}
|
||||
if (user.getNombreIpAutoAutorise() == null || user.getNombreIpAutoAutorise() < 0) {
|
||||
user.setNombreIpAutoAutorise(0);
|
||||
}
|
||||
// 6. Nettoyage des chaînes
|
||||
user.setIdentifiant(user.getIdentifiant().trim().toLowerCase());
|
||||
if (user.getMatriculeAgent() != null) {
|
||||
user.setMatriculeAgent(user.getMatriculeAgent().trim().toUpperCase());
|
||||
}
|
||||
// 7. Enregistrement
|
||||
return userRepository.save(user);
|
||||
}
|
||||
|
||||
@@ -44,13 +81,13 @@ public class UserService {
|
||||
|
||||
return userRepository.save(user);
|
||||
|
||||
}).orElseThrow(() -> new RuntimeException("User not found"));
|
||||
}).orElseThrow(() -> new RuntimeException("Utilisateur introuvable"));
|
||||
}
|
||||
|
||||
// READ by ID
|
||||
public User getById(Long id) {
|
||||
return userRepository.findById(id)
|
||||
.orElseThrow(() -> new RuntimeException("User not found"));
|
||||
.orElseThrow(() -> new RuntimeException("Utilisateur introuvable"));
|
||||
}
|
||||
|
||||
// READ all
|
||||
|
||||
Reference in New Issue
Block a user